asp.net core 系列 6 路由(中)
一.url 生成
接着上篇讲mvc的路由,mvc 应用程序可以使用路由的 url 生成功能,生成指向操作的 url 链接。 生成 url 可消除硬编码 url,使代码更稳定、更易维护。 此部分重点介绍 mvc 提供的 url 生成功能,并且仅涵盖 url 生成工作原理的基础知识。 iurlhelper
接口用于生成 url,是 mvc 与路由之间的基础结构的基础部分。 在控制器、视图和视图组件中,可通过 url
属性找到 iurlhelper
的实例。
// // mvc 框架的controllerbase类下 //摘要: // gets or sets the microsoft.aspnetcore.mvc.iurlhelper. public iurlhelper url { get; set; }
1.1 传统路由下的url生成
下面示例中,通过使用iurlhelper接口在index页面生成指向另一操作destination的 url超连接。
[route("home/index")] public iactionresult index() { // generates /home/destination var url = url.action("destination"); var urladdress = "<a href=\"" + url + "\" >click on to the destination</a>"; viewdata["url"] = urladdress; return view(); } public iactionresult destination() { return view(); } // index.cshtml @html.raw(viewdata["url"].tostring())
当加载index页面后,点击超连接"click on to the destination" 将进入后台控制器的destination操作中。
上面的 url.action 示例假定使用传统路由,但 url 生成功能的工作方式与属性路由相似,只不过概念不同。 在传统路由中,路由值用于扩展模板。controller 和 action 的路由值通常出现在该模板中, 这种做法可行是因为通过路由匹配的 url 遵守某项约定。 这里的扩展模板指的是routes.maproute来添加路由规则约定。
1.2 属性路由下的url生成
在属性路由中,controller
和 action
的路由值不能出现在模板中(也就是不会使用routes.maproute),它们用于查找要使用的模板。
//首先不用传统路由,去掉了routes.maproute public void configure(iapplicationbuilder app) { app.usemvc(); } [route("")] public iactionresult index() { // generates /custom/url/to/destination var url = url.action("destination"); var urladdress = "<a href=\"" + url + "\" >"+url+"</a>"; viewdata["url"] = urladdress; return view(); } [httpget("custom/url/to/destination")] public iactionresult destination() { return view(); }
生成如下图所示 :所以会生成与httpget配置的路径一样,是因为属性路由下的url生成,它们用于查找要使用的模板。mvc 生成一个包含所有属性路由操作的查找表,并匹配 controller 和 action 的值,以选择要用于生成 url 的路由模板。
1.3 根据action名称生成 url
url.action
(iurlhelper
. action
) 以及所有相关重载都基于这样一种想法:用户想通过指定控制器名称和操作名称来指定要链接的内容。
[route("")] public iactionresult index() { // generates /home/destination/1?color=red var url = url.action("destination","home",new { id=1 , color="red"}); var urladdress = "<a href=\"" + url + "\" >" + url + "</a>"; viewdata["url"] = urladdress; return view(); } public iactionresult destination(int id,string color) { return view(); }
1.4 根据路由名称生成 url
iurlhelper 还提供 url.routeurl 系列的方法。 这些方法类似于 url.action。url.routeurl 指定一个路由名称,以使用特定路由来生成 url,通常不指定控制器或操作名称。
[route("")] public iactionresult index() { // generates /custom/url/to/destination var url = url.routeurl("destination_route"); var urladdress = "<a href=\"" + url + "\" >click on to the destination</a>"; viewdata["url"] = urladdress; return view(); } [httpget("custom/url/to/destination", name = "destination_route")] public iactionresult destination() { return view(); }
1.5 其它生成
(1)在 html 中生成 url: ihtmlhelper 提供 htmlhelper 方法 html.beginform 和 html.actionlink,可分别生成 <form> 和 <a>元素。 这些方法使用 url.action 方法来生成 url,并且采用相似的参数。
(2)在action中重定向:redirecttoaction("index");
二. area区域路由
区域是一种 mvc 功能,用于将相关功能整理到一个组中,作为单独的路由命名空间(用于控制器操作)和文件夹结构(用于视图)。 通过使用区域,应用程序可以有多个名称相同的控制器,只要它们具有不同的区域。 通过向 controller
和 action
添加另一个路由参数 area
,可使用区域为路由创建层次结构。
下面是mvc文件结构,对于users控制器,在视图层多了一级manage文件夹。如何使users控制器中adduser操作关联adduser.cshtml呢,下面使用区域路由来实现:
app.usemvc(routes => { //用于名为 blog 的区域 routes.maparearoute("blog_route", "blog","manage/{controller}/{action}/{id?}"); /* * 注释的maproute与上面的区域路由作用一样 routes.maproute("blog_route", "manage/{controller}/{action}/{id?}", defaults: new { area = "blog" }, constraints: new { area = "blog" }); */ routes.maproute( name: "default", template: "{controller=home}/{action=index}/{id?}"); });
//控制器上应用区域路由
[area("blog")] public class userscontroller : controller { // get: /<controller>/ public iactionresult adduser() { return view(); } }
在浏览器中输入/manage/users/adduser 将自动进入adduser()中,这是因为当前路由:manage/{controller}/{action}/{id?}符合blog模板,所以使用blog区域路由。
三. iactionconstraint 路由约束
实现iactionconstraint最简单的方法是创建派生自 system.attribute 的类,并将其置于操作和控制器上。mvc 将自动发现任何应用属性iactionconstraint的操作和控制器。
在下面的示例中,约束基于路由数据中的国家/地区代码选择操作,开发人员负责实现accept
方法,当路由中id值为en-us时accept
方法返回 true
以表示该操作是匹配项,一切按正常解析返回客户端。 如果accept
方法返回false将不执行iactionconstraint标记的action,向客户端返回404错误。
//定义actionconstraint属性约束 public class countryspecificattribute : attribute, iactionconstraint { private readonly string _countrycode; public countryspecificattribute(string countrycode) { _countrycode = countrycode; } public int order { get { return 0; } } public bool accept(actionconstraintcontext context) { return string.equals( context.routecontext.routedata.values["id"].tostring(), _countrycode, stringcomparison.ordinalignorecase); } }
//应用路由的action约束,并且路由中id值为en-us [countryspecific("en-us")] public iactionresult privacy(string countrycode) { return view(); }
在浏览器测试时:如果输入http://localhost:30081/home/privacy/zh-cn,则网页显示404。如果输入http://localhost:30081/home/privacy/en-us 则符合约束,网页显示正常。
参考文献
官方资料:
上一篇: C# log4net
推荐阅读
-
你所不知道的ASP.NET Core MVC/WebApi基础系列 (一)
-
ASP.NET Core MVC/WebApi基础系列1
-
ASP.NET Core 2.2中的Endpoint路由详解
-
asp.net core系列之模型绑定和验证方法
-
ASP.NET Core中自定义路由约束的实现
-
详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁
-
ASP.NET Core中使用默认MVC路由的配置
-
asp.net core 系列之并发冲突的深入理解
-
ASP.NET Core 中的 ObjectPool 对象重用(二)
-
asp.net core系列 72 Exceptionless使用介绍