详解如何在ASP.NET Core中使用Route特性
ASP.NETCore中的Route中间件的职责在于将request匹配到各自Route处理程序上,Route分两种:基于约定和基本特性模式。
基于约定模式的Route采用集中化的方式,而基于特性的方式允许你在Action或者Controller上单独定义,到底采用哪一种可以基于你自己的应用场景,本篇就来讨论如何使用基于特性模式。
创建Controller类
创建一个DefaultController类,新增如下代码。
publicclassDefaultController:Controller { [Route("")] [Route("Default")] [Route("Default/Index")] publicActionResultIndex() { returnnewEmptyResult(); } [Route("Default/GetRecordsById/{id}")] publicActionResultGetRecordsById(intid) { stringstr=string.Format ("Theidpassedasparameteris:{0}",id); returnOk(str); } }
Controller级别定义Route特性
Route特性可用于Controller和Action级别,值得注意的是,如果应到到前者,那么Controller下的所有Action都受这个Route管控。
如果你仔细观察上面的DefaultController类代码,你会发现两个Action方法的Route路径都有Default前缀,这就不优雅了,优化方式就是把Route路径中的Default提取到Controller级别,代码如下:
[Route("Default")] publicclassDefaultController:Controller { [Route("")] [Route("Index")] publicActionResultIndex() { returnnewEmptyResult(); } [HttpGet] [Route("GetRecordsById/{id}")] publicActionResultGetRecordsById(intid) { stringstr=string.Format("Theidpassedasparameteris:{0}",id); returnOk(str); } }
可以看出当Controller和Action级别都被Route打上标记之后,Asp.NetCore中的Route引擎会自动将两者拼接起来,当然更简单粗暴的做法就是在Controller上使用RoutePrefix特性,如下代码所示:
[RoutePrefix("services")] publicclassHomeController:Controller { //Actionmethods }
Action级别定义Route特性
参考刚才的DefaultController类,我在Index方法上面定义了三个Route特性,这就意味着下面三种Route都可以访问到Index()方法,如下代码所示:
http://localhost:11277
http://localhost:11277/home
http://localhost:11277/home/index
常常在基于约定模式的Route中,它的Routetemplate会有一些对参数的约定,比如下面的代码:
app.UseEndpoints(endpoints=> { endpoints.MapControllerRoute( name:"default", pattern:"{controller=Home}/{action=Index}/{id?}"); });
同样基于特性模式的Route也是可以使用参数模式的,比如文章之前的DefaultController.GetRecordsById就是的,值得注意的是模板中的{id}表示可接收任何参数,如string,int等等,如果你想限定为int的话,也是可以实现的。
使用Route约束
Route约束就是Controller前的一个防火墙,他会踢掉一些不合规范的Action请求,比如说:你要求某个Action接收的参数必须是int,那在Route模板中定义的语法格式一定是这样的{parameter:constraint},如下代码所示:
[Route("Default/GetRecordsById/{id:int}")] publicActionResultGetRecordsById(intid) { stringstr=string.Format("Theidpassedasparameteris:{0}",id); returnOk(str); }
在Route中使用可选参数
你也可以在RouteTemplate上指定可选参数,意味着这个参数可传可不传,格式如下:
[Route("Sales/GetSalesByRegionId/{id?}")]
有一点非常重要,当你使用了Route特性之后,其实Controller或者Action的名字就不再重要了,因为Route处理引擎已经不再将其作为参考选项,下面的代码片段展示了如何在Action方法上变更Routetemplate格式。
[Route("Home/GetRecordsById/{id:int}")] publicActionResultGetRecordsById(intid) { stringstr=string.Format("Theidpassedasparameteris:{0}",id); returnOk(str); }
接下来可以直接使用如下地址访问GetRecordsById方法。
http://localhost:11277/home/GetRecordsById/1
对Action中的参数使用多个约束
真实场景中你不仅要求id必须是整数,还要求必须有一定意义,比如说最小值为1,对这种有多重约束的需求如何去实现呢?请看下面代码。
[Route("Default/GetRecordsById/{id:int:min(1)}")] publicActionResultGetRecordsById(intid) { stringstr=string.Format("Theidpassedasparameteris:{0}",id); returnOk(str); }
常使用的Route约束
- int限定为int类型
- max/min限定int的最大数和最小数
- minlength限定string的最小长度
- regex限定符合的正则
创建自定义的Route约束
如果上面的一些约束不满足你的要求,你完全可以为你的场景深度定制,做法就是使用IRouteConstraint接口并实现它的Match方法即可,如下代码所示:
publicclassCustomRouteConstraint:IRouteConstraint { publicboolMatch(HttpContexthttpContext,IRouterroute, stringrouteKey, RouteValueDictionaryvalues,RouteDirectionrouteDirection) { thrownewNotImplementedException(); } }
在Controller上使用token占位符
所谓的token占位符就是具有一些特定含义的占位符号,比如说:[action],[area]和[controller],分别表示用你真实的Controller和Action去替换,下面的代码展示了如何使用这种模式去实现。
[Route("[controller]/[action]")] publicclassHomeController:Controller { privatereadonlyILogger_logger; publicHomeController(ILogger logger) { _logger=logger; } publicIActionResultIndex() { returnView(); } //Otheractionmethods }
整体来看,基于特性的Route给了你更多的操控权限,灵活的RouteTemplate配置实现了Controller和Action的解耦,当然这里也不是说基于约定的Route不好,毕竟人家是Global级别的,真实场景下两者更多的是混着用。
译文链接:https://www.infoworld.com/article/3569369/how-to-use-attribute-routing-in-aspnet-core.html
到此这篇关于如何在ASP.NETCore中使用Route特性的文章就介绍到这了,更多相关ASP.NETCoreRoute特性内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!