本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
跟我一起学.NetCore之路由的最佳实现
mylove136 · 294浏览 · 发布于2020-09-22 +关注

前言

路由,这词绝对不陌生,不管在前端还是后端都经常提到,而这节不说其他,就聊.NetCore的路由;在之前的Asp.Net MVC 中,路由算是面试时必问的考点,可见其重要性,它的主要作用是映射URL,而不需要关注服务器的物理文件结构,提高安全性,同时规范了URL请求,有利于搜索引擎优化;所以在Asp.NetCore中当然也不能缺少,以下说说其应用。

正文

在Asp.NetCore中,注册路由方式有两种:

  • 模板路由注册:适合应用于MVC页面项目,相对于来说,使用模板的形式更加方便,约定大于配置,统一URL;

  • 特性路由注册(RouteAttribute):适合应用于API项目,针对于不同业务路由会进行定制,特性标注显得更加便捷;

少说话,多撸码,这里就创建一个WebAPI项目来进行演示:

img

默认情况下,创建的WebAPI项目是推荐使用特性路由方式进行注册(MVC默认是使用路由模板方式),当然也可以在Api项目中进行使用模板路由方式注册,如下:

img

当注释掉特性路由,在注册终结点时增加路由模板,最终运行时会出现异常,因为用ApiController标识的Controller必须是特性路由,那把ApiController特性也注释掉,结果就正常运行了,如下:

img

这里其实有一个重要的知识点:路由匹配规则,考虑到小伙伴们之前使用Asp.Net MVC时就用到,先默认小伙伴们了解这块知识(抽时间单独整理一篇出来);以下内容着重说说特性路由应用和路由约束这块,因为有关注到接触的项目中不管是之前的Asp.Net, 还是现在的Asp.NetCore项目,几乎没有看到路由约束的应用,而在很多场景,路由约束很有必要,用于消除路由的歧义。

特性路由应用

直接在Action上加Route 特性,如下:

img

运行结果如下:

img

通常为了避免在每个Action中的重复的指定路径前缀,可以将公共部分提取到Controller类上进行Route标识,如下:

img

统一前缀之后,运行结果:

img

以上的方式都是将路径写成固定的字符串,有时候会要求像模板路由中那样动态替换指定标记([area],[controller],[action] ),通常项目中会如下使用:

img

以上只是简单说说特性路由的用法,小伙伴们可以根据实际情况进行标注,当然如果有特殊需求,也可以进行自定义路由特性,只要继承IRouteTemplateProvider接口即可,上面标注的Route和HttpGet特性也是继承于这个接口,把RouteAtrribute的源代码扒出来参考参考:

namespace Microsoft.AspNetCore.Mvc
{
   // 标识此特性只能在类和方法上使用
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class RouteAttribute : Attribute, IRouteTemplateProvider
    {
        private int? _order;
        // 构造函数,传入一个Url模板参数
        public RouteAttribute(string template)
        {
            Template = template ?? throw new ArgumentNullException(nameof(template));
        }

        public string Template { get; }
        // 路由执行顺序,默认为0
        public int Order
        {
            get { return _order ?? 0; }
            set { _order = value; }
        }

        /// <inheritdoc />
        int? IRouteTemplateProvider.Order => _order;

        // 路由名称,后续可以根据路由名称生成Url,而不是硬编码编写
        public string Name { get; set; }
    }
}


来,自己也搞一个特性路由练练:

img

有没有很简单,其实这里是忍住没去扒代码的,后续单独去扒;用法就先暂时说这么多,接下来说说路由传参和约束。

路由传参和约束

一般情况,会针对路由中动态参数进行约束;从而路由约束可能会被作为输入校验,但是官方不推荐,因为当规则不匹配的时候,返回状态404(找不到),而事实对应地址可以到达请求,只是参数输入不合法而已,所以官方推荐作为消除路由歧义 ,同时也能避免不规则的路由进行业务处理;直接来案例演示(废话多了怕掉坑里):

img

新增的Controller完整代码:

namespace RouteDemo.Controllers
{
    [ApiController]
    [Route("/api/[controller]")]
    public class TestConstraintController
    {
        /// <summary>
        /// 验证必须输入,没有输入就返回404
        /// </summary>
        [HttpGet("TestRequiredConstraint/{name:required}")]
        public string TestRequiredConstraint(string name)
        {
            return "TestRequiredConstraint";
        }

        /// <summary>
        /// 整型约束,非整型数据就返回404
        /// </summary>
        [HttpGet("TestValueConstraint/{id:int}")]
        public string TestValueConstraint(int id)
        {
            return "TestValueConstraint";
        }

        /// <summary>
        /// 传入最小值为100,传入值小于100就返回404
        /// </summary>
        [HttpGet("TestMinConstraint/{id:min(100)}")]
        public string TestMinConstraint(int id)
        {
            return "TestMinConstraint";
        }

        /// <summary>
        /// 范围约束8到18,不在这个范围内就返回404
        /// </summary>
        [HttpGet("TestRangeConstraint/{id:range(8,18)}")]
        public string TestRangeConstraint(int id)
        {
            return "TestRangConstraint";
        }

        /// <summary>
        /// 验证最小长度为5,低于这个长度就返回404
        /// </summary>
        [HttpGet("TestMinLengthConstraint/{name:minLength(5)}")]
        public string TestMinLengthConstraint(string name)
        {
            return "TestMinLengthConstraint";
        } 
        /// <summary>
        /// 正则表达式约束,以三个数字开头,不满足就返回404
        /// </summary>
        [HttpGet("TestRegexConstraint/{msg:regex(^\\d{{3}})}")]
        public string TestRegexConstraint(string msg)
        {
            return "TestRegexConstraint";
        }

        /// <summary>
        /// 整型约束,范围约束8到18,不在这个范围内就返回404
        /// </summary>
        [HttpGet("TestMultiConstraint/{id:int:range(8,18)}")]
        public string TestMultiConstraint(int id)
        {
            return "TestRangConstraint";
        }
    }
}


以上只是挑了几个默认内置的约束进行举例演示,其实还有很多,剩下的小伙伴下来一定要试试,用法都很简单,如下:

  • 单个约束时

    参数:约束

    案例:[HttpGet("TestRequiredConstraint/{name:required}")]

  • 多个约束时

    参数:约束1:约束2:....

    案例:[HttpGet("TestMultiConstraint/{id:int:range(8,18)}")]

框架本身内置的约束,如下(小伙伴一定要敲敲):

约束示例说明
int{id:int}匹配任何整数
bool{active:bool}匹配 true 或 false。 不区分大小写
datetime{dob:datetime}在固定区域性中匹配有效的 DateTime 值。
decimal{price:decimal}在固定区域性中匹配有效的 decimal 值。
double{weight:double}在固定区域性中匹配有效的 double 值。
float{weight:float}在固定区域性中匹配有效的 float 值。
guid{id:guid}匹配有效的 Guid 值
long{ticks:long}匹配有效的 long 值
minlength(value){username:minlength(4)}字符串必须至少为 4 个字符
maxlength(value){filename:maxlength(8)}字符串不得超过 8 个字符
length(length){filename:length(12)}字符串必须正好为 12 个字符
length(min,max){filename:length(8,16)}字符串必须至少为 8 个字符,且不得超过 16 个字符
min(value){age:min(18)}整数值必须至少为 18
max(value){age:max(120)}整数值不得超过 120
range(min,max){age:range(18,120)}整数值必须至少为 18,且不得超过 120
alpha{name:alpha}字符串必须由一个或多个字母字符组成,a-z,并区分大小写。
regex(expression){ssn:regex(^\\d{{3}}-\\d{{2}}-\\d{{4}}$)}字符串必须与正则表达式匹配。 请参阅有关定义正则表达式的提示。
required{name:required}用于强制在 URL 生成过程中存在非参数值

不用说,内置约束肯定不可能面面俱到,所以针对个性化约束,还需要自定义,继承 IRouteConstraint 接口便可实现自定义路由约束。 接口中包含 Match,当满足约束时,它返回 true,否则返回 false。如下例演示:

img

img

总结

特性路由和约束就说到这吧,根据实际需求进行路由约束,但不能盲目,如果是要进行输入数据校验,请考虑使用模型验证!下一节说说集成Swagger。


相关推荐

PHP实现部分字符隐藏

沙雕mars · 1325浏览 · 2019-04-28 09:47:56
Java中ArrayList和LinkedList区别

kenrry1992 · 908浏览 · 2019-05-08 21:14:54
Tomcat 下载及安装配置

manongba · 970浏览 · 2019-05-13 21:03:56
JAVA变量介绍

manongba · 962浏览 · 2019-05-13 21:05:52
什么是SpringBoot

iamitnan · 1086浏览 · 2019-05-14 22:20:36
加载中

0评论

评论
分类专栏
小鸟云服务器
扫码进入手机网页