前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【asp.net core 系列】4. 更高更强的路由

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

作者头像
程序员小高
发布2020-06-09 13:04:30
6000
发布2020-06-09 13:04:30
举报
文章被收录于专栏:不做码农的开发者

0. 前言

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

1. 路由属性(Route Attribute)

按照英文的直接翻译,Routing Attribute 的意思是路由属性,但实际上 Attribute在微软的官方称呼是特性。嗯,所以个人觉得Route Attribute应该是特性路由,路由特性。

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

1.1 如何设置

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

代码语言:javascript
复制
[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 表示被该特性标注的类其子类是否也自动继承了这个特性。

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

  • Name 表示这个路由特性的名称
  • Order 表示启用顺序,值越小,越先被匹配。默认情况下是0
  • Template 路由解析模板,也就是在《【asp.net core 系列】2 控制器与路由的恩怨情仇》中介绍的路由表的格式串

介绍了这么多,我们先来试试看,先拿出来之前文章创建的MvcWeb项目,新建一个控制器:

代码语言:javascript
复制
using Microsoft.AspNetCore.Mvc;

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

创建对应视图:

Views > RouteTest > Index.cshtml

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

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

代码语言:javascript
复制
[Route("/Route")]
public IActionResult Index()
{
    return View();
}

启动项目,访问 http://localhost:5006/Route 后,如果不出意外可以看到跟下图类似的界面:

那么我们试一试通过路由表设置的路径是否可以访问:

代码语言:javascript
复制
http://localhost:5006/RouteTest

可以看到提示404,也就是说这个Action无法通过路由表的形式查找到了。

1.2 设置参数

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

1.2.1 不做任何操作

在RouteTestController里添加方法:

代码语言:javascript
复制
[Route("/route/norest")]
public IActionResult NoRest(string name)
{
    ViewBag.Name = name;
    return View();
}

创建对应的View:

代码语言:javascript
复制
<h1>@ViewBag.Name</h1>

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

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

尝试变更name的值,可以发现网页中的值也发生了变化,证明我们可以获取到这个值。

1.2.2 当做请求目录的一部分

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

代码语言:javascript
复制
[Route("/route/norest/{name}/")]
public IActionResult NoRest(string name)
{
    ViewBag.Name = name;
    return View();
}

请求方式:

代码语言:javascript
复制
http://localhost:5006/route/norest/1232

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

1.2.3 给参数一个默认值

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

代码语言:javascript
复制
[Route("/route/norest/{name=demo}/")]
public IActionResult NoRest(string name)
{
    ViewBag.Name = name;
    return View();
}

访问连接:

代码语言:javascript
复制
http://localhost:5006/route/norest/

可以看见:

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

代码语言:javascript
复制
[Route("/route/norest/{name?}/")]
public IActionResult NoRest(string name)
{
    ViewBag.Name = name;
    return View();
}

访问连接:

代码语言:javascript
复制
http://localhost:5006/route/norest/

可以看到页面没有任何显示:

正常情况下,如果不对参数设置可空而且参数被我们当做目录的一部分时,不给值是会提示404。

1.3 路由约束

约束

示例

匹配项示例

说明

int

{id:int}

123456789, -123456789

匹配任何整数

bool

{active:bool}

true, FALSE

匹配 true 或 false。不区分大小写

datetime

{dob:datetime}

2016-12-31, 2016-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,不过与之前不同的是,这次直接在控制器类上标记:

代码语言:javascript
复制
[Route("/Route")]
public class RouteCtrTestController: Controller
{
}

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

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

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

示例代码如下:

代码语言:javascript
复制
[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. 总结

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 不做码农的开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0. 前言
  • 1. 路由属性(Route Attribute)
    • 1.1 如何设置
      • 1.2 设置参数
        • 1.2.1 不做任何操作
        • 1.2.2 当做请求目录的一部分
        • 1.2.3 给参数一个默认值
      • 1.3 路由约束
      • 2. 路由统一前缀
      • 2. 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档