1、概述
在以前的Web Form开发中,我们请求的URL都对应一个具体的文件,如/System/News.aspx?id=1 ,则在对应的网站目录下面存在一个News.aspx的文件,而ASP.NET路由使您能够使用不必映射到网站中的特定文件的URL。因为URL不必映射到文件,您可以使用描述用户操作的URL,因此用户更容易理解。ASP.NET MVC框架和ASP.NET动态数据扩展路由以提供仅在MVC应用程序和动态数据应用程序中使用的功能。有关MVC的更多信息,请参阅ASP.NET MVC 3.有关动态数据的更多信息,请参阅ASP.NET动态数据内容映射。在ASP.NET路由中,您可以定义映射到请求处理程序文件的URL模式,但不一定包含URL中这些文件的名称。此外,您可以在URL模式中包含占位符,以便可以将变量数据传递到请求处理程序,而不需要查询字符串。例如,在http:// server / application / Products / show / drinks的请求中,路由解析器可以将值,显示和饮料值传递给页面处理程序。在这个例子中,如果使用URL模式服务器/应用程序/ {area} / {action} / {category}来定义路由,则页面处理程序将接收字典集合,其中与关键区域相关联的值是Products,显示关键操作的值,关键类别的值为饮料。在不由URL路由管理的请求中,/ Products / show / drinks片段将被解释为应用程序中文件的路径。
2、路由配置
2.1、路由匹配说明
先说一下基本的路由规则原则。基本的路由规则是从特殊到一般排列,也就是最特殊(非主流)的规则在最前面,最一般(万金油)的规则排在最后。这是因为匹配路由规则也是照着这个顺序的
2.2、理解默认路由表
ASP.NET路由查找从上向下查找,找到就不在向下匹配。路由关键字有:controller , action , area这三个保留字就别设静态变量里面了,ASP.NET MVC的路由配置在网站App_Start文件夹的RouteConfig.cs文件中配置,在网站启动的时候,通过Global.asax文件中的Application_Start方法注册,注册代码如下:
在RouteConfig.cs文件中有一个默认路由配置,代码如下:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", //Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
}
该路由匹配如下路由
/Home/Index/3
默认的路由将这个URL映射为下面的参数:
Controller = Home
Action = Index
id = 3
Default路由包含了所有三个参数的默认值。如果你不提供控制器,那么控制器参数默认值为Home。如果你不提供动作,动作参数默认为值Index。最后,如果你不提供id,id参数默认为空字符串。
让我们看看几个例子,Default路由是如何将URL映射到控制器动作的。设想你在浏览器地址栏输入了下面的URL:
/Home
由于Default路由参数的默认值,输入这个URL将会调用代码清单2中的HomeController类的Index()方法。
2.3、创建自定义路由
接下来我们来看看自定义路由
routes.MapRoute(
name: "tnews",//Route Name
url: "TNews/{action}/{newsid}",//URL with parameters
defaults: new { controller = "TNews", action = "Details" }//Parameters defaults
);
/* 这样定义的路由,总是报错误:匹配的路由不包括所需的“controller”路由值。 有谁知道的可以在下面留言,告诉我
routes.MapRoute(
name: "tnews",
url: "TNews/{action}/{newsid}"
);*/
上述定义的路由匹配
/TNews/Details/1,如下方法:
public ActionResult Details(string newsid)//注意是newsid,不是id
{
int id = Convert.ToInt32(newsid);
TNews tnews = db.TNews.Find(id);
if (tnews == null)
{
return HttpNotFound();
}
return View(tnews);
}
当然了上述路由也匹配
/TNews/Details/abc
而我们匹配的newsid是一个可以转换为int类型的参数,接下来我们修改路由配置,要求newsid必须是可以转换为int类型的参数,
2.4、创建路由约束
代码如下:
routes.MapRoute(
name: "tnews",
url: "TNews/{action}/{newsid}",
defaults: new { controller = "TNews", action = "Details" },
constraints:new { newsid =@"\d+"}
);
注意到TNews控制器公布的Details()动作接受一个叫做newsid的参数。这个参数是一个整数参数。
正则表达式\d+匹配一个或多个整数。这个限制使得TNews路由匹配了下面的URL:
/TNews/Edit/3
/TNews/Details/8999
但是不匹配下面的URL:
/TNews/Details/apple
/TNews/Edit/abc
这些浏览器请求将由另外的路由处理,或者,如果没有匹配的路由,将会返回一个“The resource could not be found”错误。
routes.MapRoute(
name: "tnews",
url: "{controller}/{action}/{newsid}",
defaults: new { controller = "TNews", action = "Details" },
constraints:new {
controller = "^T.*"//正则约束
},
namespaces:new [] { "MvcFilterWeb.Controllers" }
);
添加约束要求controler以T开头,
可以匹配
/TNews/Details/ab
但是不匹配
/Products/Details/1
添加多个路由约束
routes.MapRoute(
name: "tnews",
url: "TNews/{action}/{newsid}",
defaults: new { controller = "TNews", action = "Details" },
constraints:new {
controller = "^H.*",//正则约束
action ="^Details$|^Edit$"
},
namespaces:new [] { "MvcFilterWeb.Controllers" }
);
指定请求方式
routes.MapRoute(
name: "tnews",
url: "TNews/{action}/{newsid}",
defaults: new { controller = "TNews", action = "Details" },
constraints:new {
controller = "^H.*",//正则约束
action ="^Details$|^Edit$",
httpMethod = new HttpMethodConstraint("GET")
},
namespaces:new [] { "MvcFilterWeb.Controllers" }
);
2.5、可变长度路由
routes.MapRoute(
name: "tnews",
url: "TNews/{action}/{newsid}/{*catchall}",
defaults: new { controller = "TNews", action = "Details" }
);
可以匹配
/TNews/Details/123/abc/def
/TNews/Details/1
等。
2.6在指定命名空间下查找路由
routes.MapRoute(
name: "tnews",
url: "TNews/{action}/{newsid}",
defaults: new { controller = "TNews", action = "Details" },
namespaces:new [] { "MvcFilterWeb.Controllers" }
);
在命名空间MvcFilterWeb.Controllers查找指定路由(如果写多个命名空间约束的话,,如果有多个匹配的路由会报错。 如果添加命名空间约束的话,最好一个命名空间定义一个路由)
2.6 WebForm支持
routes.MapPageRoute("", "", "~/Default.aspx");
routes.MapPageRoute("list",
"Items/{action}",
"~/Items/list.aspx",
false,
new RouteValueDictionary{
{ "action","all"}
});
routes.MapPageRoute("show",
"Show/{action}",
"~/show.aspx",
false,
new RouteValueDictionary{
{ "action","all"}
});
routes.MapPageRoute(
"edit",
"Edit/{id}",
"~/edit.aspx",
false,
new RouteValueDictionary{
{ "id","1"}
},
new RouteValueDictionary{
{ "id",@"\d+"}
});
具体可以参考:
1、RouteCollection.MapPageRoute 方法
2、使用Asp.Net4新特性路由创建WebForm应用
参考资料:
1、https://www.asp.net/mvc
2、ASP.NET Routing