【asp.net core 系列】4. 更高更强的路由

0. 前言

在以前咱们介绍了请求经过路由寻找到控制器,以及控制器与视图的数据流转。那么,咱们回过头来,再看看路由的一些其余用法。html

图片

1. 路由属性(Route Attribute)

按照英文的直接翻译,Routing Attribute 的意思是路由属性,但实际上 Attribute在微软的官方称呼是特性。嗯,因此我的以为Route Attribute应该是特性路由,路由特性。正则表达式

嗯,暂且甩开称呼的问题,小伙伴们知道这是一种使用Attribute标记的路由配置方案就行。咱们以前了解的路由设置都是经过路由表设置的,而Route Attribute则是另一种方案。express

1.1 如何设置

这种方案主要是经过RouteAttribute类来设置的,咱们先来看一下这个类是个什么样的吧:app

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class RouteAttribute : Attribute, IRouteTemplateProvider
{
   public RouteAttribute(string template);
   public string Name { get; set; }
   public int Order { get; set; }
   public string Template { get; }
}

AttributeUsage 这个特性是用来标注特性的适用范围的,其中AttributeTargets.Class | AttributeTargets.Method 表示这个特性是能够设置在类或者方法上的。AllMultiple表示是否容许设置多个,Inherited 表示被该特性标注的类其子类是否也自动继承了这个特性。asp.net

那么,咱们了解了RouteAttribute的适用范围,继续看这个类,一共有三个属性:ide

  • Name 表示这个路由特性的名称ui

  • Order 表示启用顺序,值越小,越先被匹配。默认状况下是0spa

  • Template 路由解析模板,也就是在《【asp.net core 系列】2 控制器与路由的恩怨情仇》中介绍的路由表的格式串.net

介绍了这么多,咱们先来试试看,先拿出来以前文章建立的MvcWeb项目,新建一个控制器:翻译

using Microsoft.AspNetCore.Mvc;

namespace MvcWeb.Controllers
{
   public class RouteTestController: Controller
   {
       public IActionResult Index()
       {
           return View();
       }
   }
}

建立对应视图:

Views > RouteTest > Index.cshtml

在Index.cshtml中随便写点内容,而后保存。

而后,在RouteTestController 添加一个Route特性标记:

[Route("/Route")]
public IActionResult Index()
{
   return View();
}

启动项目,访问 http://localhost:5006/Route 后,若是不出意外能够看到跟下图相似的界面:

那么咱们试一试经过路由表设置的路径是否能够访问:

http://localhost:5006/RouteTest

能够看到提示404,也就是说这个Action没法经过路由表的形式查找到了。

1.2 设置参数

咱们知道所谓的Action其实也是一个方法,而咱们一般请求一个网址的时候,网址中也带有一些查询参数。因此,这一节咱们就介绍一下路由特性(属性路由)如何设置参数的解析吧。

1.2.1 不作任何操做

在RouteTestController里添加方法:

[Route("/route/norest")]
public IActionResult NoRest(string name)
{
   ViewBag.Name = name;
   return View();
}

建立对应的View:

<h1>@ViewBag.Name</h1>

启动程序,并访问:http://localhost:5006/route/norest

添加 ?name=test 在上一个请求的后面:

图片

尝试变动name的值,能够发现网页中的值也发生了变化,证实咱们能够获取到这个值。

1.2.2 当作请求目录的一部分

在上一小节中,没有对参数作任何操做,以查询参数的形式传递。在这一篇,咱们能够把参数设置为请求的一部分,像目录那样,修改上一节示例代码为:

[Route("/route/norest/{name}/")]
public IActionResult NoRest(string name)
{
   ViewBag.Name = name;
   return View();
}

请求方式:

http://localhost:5006/route/norest/1232

图片

修改链接中的1232 内容,而后刷新页面,就能发现页面中的值也发生了变化

1.2.3 给参数一个默认值

以前的设置里咱们都默认参数由请求URL获取,那么在这里咱们介绍一下给参数一个值:

[Route("/route/norest/{name=demo}/")]
public IActionResult NoRest(string name)
{
   ViewBag.Name = name;
   return View();
}

访问链接:

http://localhost:5006/route/norest/

能够看见:

图片

设置为可空,也就是参数能够不传:

[Route("/route/norest/{name?}/")]
public IActionResult NoRest(string name)
{
   ViewBag.Name = name;
   return View();
}

访问链接:

http://localhost:5006/route/norest/

能够看到页面没有任何显示:

图片

正常状况下,若是不对参数设置可空并且参数被咱们当作目录的一部分时,不给值是会提示404。

1.3 路由约束

约束 示例 匹配项示例 说明
int {id:int} 123456789,-123456789 匹配任何整数
bool {active:bool} trueFALSE 匹配 true 或false。不区分大小写
datetime {dob:datetime} 2016-12-312016-12-31 7:32pm 在固定区域性中匹配有效的 DateTime 值。请参阅前面的警告。
decimal {price:decimal} 49.99-1,000.01 在固定区域性中匹配有效的 decimal 值。请参阅前面的警告。
double {weight:double} 1.234-1,001.01e8 在固定区域性中匹配有效的 double 值。请参阅前面的警告。
float {weight:float} 1.234-1,001.01e8 在固定区域性中匹配有效的 float 值。请参阅前面的警告。
guid {id:guid} CD2C1638-1638-72D5-1638-DEADBEEF1638 匹配有效的 Guid 值
long {ticks:long} 123456789,-123456789 匹配有效的 long 值
minlength(value) {username:minlength(4)} Rick 字符串必须至少为 4 个字符
maxlength(value) {filename:maxlength(8)} MyFile 字符串不得超过 8 个字符
length(length) {filename:length(12)} somefile.txt 字符串必须正好为 12 个字符
length(min,max) {filename:length(8,16)} somefile.txt 字符串必须至少为 8 个字符,且不得超过 16 个字符
min(value) {age:min(18)} 19 整数值必须至少为 18
max(value) {age:max(120)} 91 整数值不得超过 120
range(min,max) {age:range(18,120)} 91 整数值必须至少为 18,且不得超过 120
alpha {name:alpha} Rick 字符串必须由一个或多个字母字符(a-z,不区分大小写)组成。
regex(expression) {ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)} 123-45-6789 字符串必须与正则表达式匹配。请参阅有关定义正则表达式的提示。
required {name:required} Rick 用于强制在 URL 生成过程当中存在非参数值

2. 路由统一前缀

在第一节中,咱们介绍了如何使用RouteAttribute为控制器里的方法标记路由信息。有时候会出现这样的一个问题,一个控制器方法里可能会出现多个方法(Action)。一般状况下,咱们要求一个控制器处理的请求应当有一个统一的前缀(或者称之为URL目录)。

那么,这种状况咱们仍然继续使用 RouteAttribute,不过与以前不一样的是,此次直接在控制器类上标记:

[Route("/Route")]
public class RouteCtrTestController: Controller
{
}

这时候,在方法上若是添加了RouteAttribute,设置的路由信息若是不是以/ 开始,则会将该Action的路由配置加到Controller后面。若是是以/ 开始,则表示该路由是根路由。

若是没有设置RouteAttribute,则表示当前方法是处理控制器配置的路由的方法。

若是一个控制器里出现多个未设置RouteAttribute,则会出错。

示例代码以下:

[Route("/Route")]
public class RouteCtrTestController: Controller
{
   public int temp{get;set;}
   public IActionResult Index(int temp)
   {
       return Content($"你好{temp}");
   }
   [Route("Demo")]
   public IActionResult Demo()
   {
       return Content($"你好 Demo");
   }
}

2. 总结

今天的内容比较短,这里介绍了一些路由的另外一种用法,小伙伴们对此有个了解就能够了。下一篇将会到视图,开始准备带领你们作一个小项目啦。

相关文章
相关标签/搜索