上一篇介绍了Asp.Net MVC 中,从Http Pipeline上接收到请求如何匹配,匹配限制,以及如何控制在指定命名空间查找,解析出controller和action,并传参。

这篇主要介绍如何使用路由完成url生成,实现页面跳转,以及customize一个路由。

在view中生成一个url连接

路由配置使用默认生成的:

routes.MapRoute(
name:"Default",
url:"{controller}/{action}/{id}",
defaults: new { controller ="Home", action = "Index", id = UrlParameter.Optional }
);

最简单的方法是使用Html.ActionLink ,在home View里添加代码:

@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"content="width=device-width" />
<title>ActionName</title>
</head>
<body>
<div>The controller is:@ViewBag.Controller</div>
<div>The action is: @ViewBag.Action</div>
<div>
@Html.ActionLink("This is an outgoing URL", "CustomVariable")
</div>
</body>
</html>

这样就会生成:

<a href="/Home/CustomVariable">This is anoutgoing URL</a>

这样,实际上是生成了在当前controller内,指向另一个action的url。

使用Html.ActionLink生成链接的好处是什么,可以根据当前的路由配置,自动维护生成好的url,上例使用的是默认配置。例如如果路由配置改为:

routes.MapRoute("NewRoute","App/Do{action}",
new { controller = "Home" });

使用同样的代码:

@Html.ActionLink("This is an outgoing URL","CustomVariable")

此时url连接就会生成为:

<a href="/App/DoCustomVariable">This is anoutgoing URL</a>

因为当我们访问home controller时,NewRoute 在默认路由之前被匹配到了,就会拿它的pattern来生成url了。

当一个请求来时,路由会检测:

1.      Pattern

2.      路由限制

3.      Assign给匿名对象的默认值,就是解析存在Route Dictionary 里面的那些值

跳转到其他controller

最简单的方式:

@Html.ActionLink("Thistargets another controller", "Index", "Admin")

直接传入第二个参数,指向”admin”controller

生成url连接,同时传参

对于同一个controller:

@Html.ActionLink("This is anoutgoing URL",
"CustomVariable", new {id = "Hello" })

跨controller传值:

 @Html.ActionLink("Click me to go to anotherarea","Index", "Test",new {Id="aaa"},null)

意,如果路由成功匹配了传值的参数名称,那么url就会以匹配的格式生成;如果路由匹配成功,可是传的值没有在路由模式中指定,那么就会以?param=value的形式传值。例如,对于以上actionlink,如果是路由:

routes.MapRoute("NewRoute","App/Do{action}",
new { controller ="Home" })

那么生成的url连接就是:

<a href="/Home/CustomVariable?id=Hello">This is an outgoingURL</a>

如果对于路由:

routes.MapRoute("MyRoute","{controller}/{action}/{id}",
new { controller ="Home", action = "Index",
id = UrlParameter.Optional });

那么生成的url就是:

<a href="/Home/CustomVariable/Hello">This is an outgoingURL</a>

设定html属性

简单的,还是同样使用Html.ActionLink:

@Html.ActionLink("This is anoutgoing URL",
"Index","Home", null, new {id = "myAnchorID",
@class = "myCSSClass"})

这样就可以生成一个连接,class设为了myCssClass

<a class="myCSSClass"href="/"id="myAnchorID">This is an outgoing URL</a>

生成一个绝对路径的url连接

@Html.ActionLink("This is anoutgoing URL", "Index", "Home",
"https","myserver.mydomain.com", " myFragmentName",
new { id = "MyId"},
new { id ="myAnchorID", @class = "myCSSClass"})

生成:

<a class="myCSSClass"
href="https://myserver.mydomain.com/Home/Index/MyId#myFragmentName"
id="myAnchorID">This is an outgoing URL</a>

通常,不建议生成绝对路径的url,如需指向外部连接,可以直接使用html标签。

生成URL

有些场景,只需要生成一个连接,而不想和html.ActionLink建立耦合,那么就可以使用Url.Action:

@Url.Action("Index","Home", new { id = "MyId" })

对于默认route({controller}/{action}/{id})生成:

Home/Index/MyId

在action内生成url

public ViewResult MyActionMethod() {
string myActionUrl = Url.Action("Index",new { id = "MyID" });
string myRouteUrl =Url.RouteUrl(new { controller = "Home", action = "Index"});
//... do something with URLs...
return View();
}

当然,更推荐简单的使用 RedirectToAction(),返回值为RedirectToRouteResult:

public RedirectToRouteResult MyActionMethod() {
return RedirectToAction("Index");
}

如果想跳出当前的controller,使用另一个重载:

public  RedirectToRouteResult  TestRedirect()
{
returnRedirectToAction("TestAction", "AnotherController");
}

如果这个请求handle不掉,也不想跳到哪个controller,那就还给route吧(这种场景不多):

public RedirectToRouteResult MyActionMethod() {
return RedirectToRoute(new {
controller = "Home",
action = "Index",
id = "MyID" });
}

自定义route system

如果当前route的行为还不能满足场景需要,那么可以自定义route,例如,对于刚从asp.netweb form移植到mvc上的网站,对于旧版本的url,我们也需要支持。

创建controller:

namespace UrlsAndRoutes.Controllers {
public class LegacyController : Controller {
public ActionResult GetLegacyURL(string legacyURL) {
return View((object)legacyURL);
}
}
}

这个controller接收传来的url,打印出当前的url(真正的行为应该是显示出该文件内容)。

View里面显示出controller拿来的url值:

@model string
@{
ViewBag.Title = "GetLegacyURL";
Layout = null;
}
<h2>GetLegacyURL</h2>
The URL requested was: @Model

完成了简单的controller和view,重点在于后面的route。

public class LegacyRoute : RouteBase {
private string[] urls;
public LegacyRoute(params string[] targetUrls) {
urls = targetUrls;
}
public override RouteData GetRouteData(HttpContextBase httpContext) {
RouteData result = null;
string requestedURL =
httpContext.Request.AppRelativeCurrentExecutionFilePath;
if (urls.Contains(requestedURL, StringComparer.OrdinalIgnoreCase)) {
result = new RouteData(this, new MvcRouteHandler());
result.Values.Add("controller", "Legacy");
result.Values.Add("action", "GetLegacyURL");
result.Values.Add("legacyURL", requestedURL);
}
return result;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values) {
return null;
}

创建一个类,继承了routeBase,重点在后面的那两个需要重写的方法:

GetRouteData和GetVirtualPath

对于getroutedata,我们做的操作时从httpcontext对象里拿当前的requesturl,如果是旧版本url里面的,那么直接就把controller指向legacy,action指向GetLegacyURL,并且把参数一起给了:LegacyURL设为当前的url。如果这个请求不是旧版本url里面,那么简单的返回null,让其他的route对象来handle吧。

对于GetVirtualPath,用于生产Url时,先简单的返回null,后面章节会介绍如何生成url。

最后,注册一下自定义的route:

routes.Add(new LegacyRoute(
"~/articles/test1 ",
"~/old/.NET_1.0_Class_Library"));

可以看到,自定义的route已经生效了。

在自定义route中生成URL

把刚才那个GetVirtualPath的函数做个简单实现:

public override VirtualPathData GetVirtualPath(RequestContext requestContext,
RouteValueDictionary values) {
VirtualPathData result = null;
if(values.ContainsKey("legacyURL") &&
urls.Contains((string)values["legacyURL"],StringComparer.OrdinalIgnoreCase)) {
result = newVirtualPathData(this,
new UrlHelper(requestContext)
.Content((string)values["legacyURL"]).Substring(1));
}
return result;
}

函数功能:把传入的匿名对象的legacyURL的值做字符串截取,把首字符滤掉。

在view加入代码:

@Html.ActionLink("Clickme", "GetLegacyURL",
new { legacyURL = "~/articles/Windows_3.1_Overview" })

就会生成:

<a href="/articles/Windows_3.1_Overview">Click me</a>

自定义Route Handler

前面的例子,我们都是用MvcRouteHandler,对于场景:http请求需要被httphandler来处理掉,那么就需要customize一个routehandler了。

1.      提供一个类继承IRouteHandler

public class CustomRouteHandler : IRouteHandler {
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
return new CustomHttpHandler();
}
}

2.      准备好HttpHandler

public class CustomHttpHandler : IHttpHandler {
public bool IsReusable {
get { return false; }
}
public void ProcessRequest(HttpContext context) {
context.Response.Write("Hello");
}
}

用于展示,这个handler拿到httpcontext后仅仅打印出hello。

3.   注册一个路由,对于相应的pattern,指向这个routehandler

utes.Add(newRoute("SayHello", new CustomRouteHandler()));routes.Add(new Route("SayHello", new CustomRouteHandler()));

 routes.Add(new Route("SayHello", new CustomRouteHandler()));

访问SayHello,验证结果正确。

Asp.Net MVC4 系列--进阶篇之路由 (2)的更多相关文章

  1. Asp.Net MVC4 系列-- 进阶篇之路由(1)

    创建一个路由 打开 RouteConfig.cs  ,发现已经创建了一个默认路由 : routes.MapRoute( name:"Default", url:"{con ...

  2. Asp.Net MVC4 系列-- 进阶篇之路由

    原文  http://blog.csdn.net/lan_liang/article/details/22993839 创建一个路由 打开 RouteConfig.cs  ,发现已经创建了一个默认路由 ...

  3. Asp.Net MVC4 系列-- 进阶篇之路由(1)【转】

    http://blog.csdn.net/lan_liang/article/details/22993839?utm_source=tuicool

  4. bootstrap-data-target触发模态弹出窗元素的data使用 data-toggle与data-target的作用 深入ASP.NET MVC之九:Ajax支持 Asp.Net MVC4系列--进阶篇之AJAX

    bootstrap-data-target触发模态弹出窗元素的data使用 时间:2017-05-27 14:22:34      阅读:4479      评论:0      收藏:0      [ ...

  5. Asp.Net MVC 进阶篇:路由匹配 实现博客路径 和文章路径

    Asp.Net MVC 进阶篇:路由匹配 实现博客路径 和文章路径 我们要实现 通过路由 匹配出 博客地址 和博客文章地址 例如下面的这两个地址 //http://www.cnblogs.com/ma ...

  6. SQL Server调优系列进阶篇(查询语句运行几个指标值监测)

    前言 上一篇我们分析了查询优化器的工作方式,其中包括:查询优化器的详细运行步骤.筛选条件分析.索引项优化等信息. 本篇我们分析在我们运行的过程中几个关键指标值的检测. 通过这些指标值来分析语句的运行问 ...

  7. SQL Server调优系列进阶篇(深入剖析统计信息)

    前言 经过前几篇的分析,其实大体已经初窥到SQL Server统计信息的重要性了,所以本篇就要祭出这个神器了. 该篇内容会很长,坐好板凳,瓜子零食之类... 不废话,进正题 技术准备 数据库版本为SQ ...

  8. SQL Server调优系列进阶篇(如何索引调优)

    前言 上一篇我们分析了数据库中的统计信息的作用,我们已经了解了数据库如何通过统计信息来掌控数据库中各个表的内容分布.不清楚的童鞋可以点击参考. 作为调优系列的文章,数据库的索引肯定是不能少的了,所以本 ...

  9. SQL Server调优系列进阶篇(如何维护数据库索引)

    前言 上一篇我们研究了如何利用索引在数据库里面调优,简要的介绍了索引的原理,更重要的分析了如何选择索引以及索引的利弊项,有兴趣的可以点击查看. 本篇延续上一篇的内容,继续分析索引这块,侧重索引项的日常 ...

随机推荐

  1. poj 1986LCA离线dfs+并查集

    题意,给出边和权值,求出两个点间的最短距离. 用离线算法的时候有个地方不知道怎么处理了.在线的本来想用倍增的,但发现倍增算法貌似需要预处理深度而不是权值,不知道怎么处理.套一个rmq的模板吧,用来处理 ...

  2. oracle12之 多租户容器数据库架构

    解读: 这张幻灯片展示了三个被部署的应用程序的整合 三个不同的非cdbs成为一个单一的.幻灯片中的图形显示了一个多租户 容器数据库有四个容器:根和三个可插入的数据库.每一个 可插入数据库有它自己的专用 ...

  3. OSX 10.8+下开启Web 共享 的方法

    MENU Home Archives About SUBSCRIBE ☰MENU OSX 10.8+ Mountain Lion 下开启 Web Sharing(Web 共享)的方法 JUL 28, ...

  4. 第02周-Java作业评价

    1. 本周作业简评与建议 作业存在的问题 格式上还是存在问题,但是比较第一次有很大的进步. 答题上,有的同学还是很敷衍,题目要求有分析过程,但是只写一个false,true,没有分析.也比较缺少自己的 ...

  5. 团队作业4——第一次项目冲刺(Alpha版本)2nd day

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 界面 1.四个用户登录界面已经完成. 2.界面内的功能完成了一小部分. 登陆部分 1.QQ授权已经申请,还未通过. 2.通过好 ...

  6. 201521123042 《Java程序设计》第3周学习总结

    1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...

  7. JavaScript的5中基本数据类型

    javascript的5种基本数据类型有: Undefined,Null,Bollean,Number,String,1种复杂数据类型:Object. 1Boolean类型 将一个值转换为Bollea ...

  8. sscanf和正则表达式

    sscanf() - 从一个字符串中读进与指定格式相符的数据.      函数原型: Int sscanf( string str, string fmt, mixed var1, mixed var ...

  9. lintcode 155 二叉树的最小深度

    二叉树的最小深度   描述 笔记 数据 评测 给定一个二叉树,找出其最小深度. 二叉树的最小深度为根节点到最近叶子节点的距离. 您在真实的面试中是否遇到过这个题? Yes 哪家公司问你的这个题? Ai ...

  10. XML【介绍、用途、了解XML技术架构、语法】

    什么是XML? XML:extensiable markup language 被称作可扩展标记语言 XML简单的历史介绍: gml->sgml->html->xml gml(通用标 ...