跟我一起学.NetCore之路由的最佳实现

前言

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

正文

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

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

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

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

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

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

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

特性路由应用

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

运行结果如下:

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

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

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

以上只是简单说说特性路由的用法,小伙伴们可以根据实际情况进行标注,当然如果有特殊需求,也可以进行自定义路由特性,只要继承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; }// 路由执行顺序,默认为0public int Order{get { return _order ?? 0; }set { _order = value; }}/// <inheritdoc />int? IRouteTemplateProvider.Order => _order;// 路由名称,后续可以根据路由名称生成Url,而不是硬编码编写public string Name { get; set; }}
}

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

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

路由传参和约束

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

新增的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。如下例演示:

总结

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

一个被程序搞丑的帅小伙,关注"Code综艺圈",识别关注跟我一起学~~~

撸文不易,莫要白瞟,三连走起~~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/307549.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode844. 比较含退格的字符串

一:题目 二:上码 class Solution {public:/**思路:1.利用栈 我们将字符串中的单个元素都入栈 当遇到#的时候将将栈顶元素弹出*/bool backspaceCompare(string s, string t) {stack<int> s1;stack<int> s2;for (int i 0; i < s.size(); i) {if(s[i] ! #) s1.pu…

BeetleX之HTTP网关部署

BeetleX组件提供了HTTP网关组件&#xff0c;但使用过程中需要自己写宿主程序来启动它。为了更好的直接使用&#xff0c;组件发布了一个基于.net core 3.1的可运行版本程序并集成了管理插件&#xff1b;只需下载程序即可以在linux或windows下部署一个HTTP网关部署。部署安装运行…

深度学习入门笔记(6)—— Logistic Regression

对比第三节中的 Adaline 和 Logistic Regression&#xff0c;可以发现它们只有两点不同&#xff1a;1、激活函数&#xff0c;Adaline 中的激活函数是恒等函数&#xff08;线性&#xff09;&#xff0c;而 Logistic Regression 中的激活函数是 Sigmoid 函数&#xff08;非线性&a…

微服务模式下,实现前后端多资源服务调用

MicroServices首先&#xff0c;我先解释下&#xff0c;文章标题的意思&#xff1a;咋看起来特别像是一个标题党????&#xff0c;可能是我没想好怎么表达&#xff0c;其实白话文就是&#xff1a;在微服务场景下&#xff0c;肯定会有很多子服务API&#xff0c;那多个前端项目…

leetcode54. 螺旋矩阵(详解)

一:题目 二:上码 class Solution { public:/**思路:1.1 2 3 45 6 7 89 10 11 1213 14 15 162.我们模拟顺时针的顺序,那么得分为4步 上面得一行 (1,2,3)左面得一行 (4,8,12)下面得一行 (16,15,14)右面得一行 (13,9,5)可以看到我们在取数字得时候,我们是每次只取…

深度学习入门笔记(7)—— Multinomial Logistic Regression / Softmax Regression

首先介绍一个非常著名的多分类数据集 MNIST&#xff0c;也就是 0 到 9 的手写数字数据集。每个图像都是 28 * 28&#xff0c;用于Pytorch 数据读取的格式是 NCHW&#xff0c;即 Number、Channel、Height、Weight。 读取图像之后&#xff0c;就能看到一个只有单通道的&#xff0…

[C#.NET 拾遗补漏]09:数据标注与数据校验

数据标注&#xff08;Data Annotation&#xff09;是类或类成员添加上下文信息的一种方式&#xff0c;在 C# 通常用特性&#xff08;Attribute&#xff09;类来描述。它的用途主要可以分为下面这三类&#xff1a;验证 Validation&#xff1a;向数据添加验证规则展现 Display&am…

2023届春招实习拉钩一面凉经

面完就当挂了 老想着其实自己其实还能回答的更好 可回不去了 计网的的ioc七层模型各层的作用 为什么是七层模型而不是两层模型 SpringBoot最核心的注解是什么 Spring中IOC原理以及相关注解 说说对Mysql数据库索引的了解 map有哪些实现 分别讲讲&#xff1f; 项目中数据库…

Pytorch中损失函数 NLLLOSS 和 CROSSENTROPYLOSS 的区别

NLLLOSS 是 negative log likelihood loss 负对数似然损失函数&#xff0c;CROSSENTROPYLOSS 是交叉熵损失函数&#xff0c;它们都是用于多分类任务的损失函数&#xff0c;正如我在笔记中提到的&#xff0c;它们实际上是一样的&#xff0c;在 Pytorch 中这两者的区别就只在于接…

收好这张MySQL导图,全是知识点!

感谢阅读&#xff0c;直接上干货&#xff01;最新整理的MySQL知识点全图&#xff0c;完整系统超3万字。直接跳转文末&#xff0c;下载源文件&#xff01;开源跨平台的.NET Core越来越热门了&#xff0c;腾讯、网易、顺丰等大厂都在招聘&#xff0c;而且都开始明确要求MySQL了&a…

深度学习入门笔记(8)—— Multilayer Perceptron 多层感知器

所谓多层感知器&#xff0c;其实就是具有一个或多个隐藏层&#xff08;hidden layer&#xff09;的全连接前馈神经网络&#xff0c;如图所示&#xff0c;在最重要的求取损失关于权重的偏导数的过程上&#xff0c;跟之前的 Logistic Regression 和 Softmax Regression 一样&…

蓝桥杯-填空题-门牌制作

一&#xff1a;题目 二&#xff1a;代码 #include <iostream> using namespace std; int main() {int nums 2020;int count 0;string str to_string(nums);for(int i 1; i < nums; i) {string str to_string(i);for(auto temp: str) {if(temp 2){count;}}}cout…

.NET Core中间件与依赖注入的一些思考

点击上方蓝字"小黑在哪里"关注我吧1.起源? 为什么会有这篇文章呢? 源于我看了老A的aspnet core 3 框架揭秘[1] 请求管道 篇产生的疑惑?三点疑惑:Singleton服务中注入Scoped服务产生内存泄露?关于中间件的生命周期是Singleton的?怎么避免中间件、Singleton服务中…

深度学习入门笔记(9)—— Regularization to avoid overfitting 用正则化来避免过拟合

在维基百科的词条中&#xff0c;正则化就是让答案变得更简单的&#xff0c;目的是防止过拟合。在分类上可以分为显式正则化&#xff08;对目标函数添加先验、惩罚、约束、成本&#xff09;和隐式正则化&#xff08;所有其他形式的正则化如提前停止、集成学习、Dropout 等&#…

蓝桥杯-填空题-购物单

一&#xff1a;题目 **** 180.90 88折 **** 10.25 65折 **** 56.14 9折 **** 104.65 9折 **** 100.30 88折 **** 297.15 半价 **** 26.75 65折 **** 130.62 半价 **** 240.28 …

C# 中 System.Index 结构体和 Hat 运算符(^)的全新用法

翻译自 John Demetriou 2019年2月17日 的文章 《C# 8 – Introducing Index Struct And A Brand New Usage For The Hat Operator》今天我们要讲的是 Hat 运算符(^)。目前为止&#xff0c;Hat 运算符(^)已经被用作布尔类型的异或运算符&#xff0c;以及字节、整型类型的按位异或…

Lagrange Multipliers 拉格朗日乘数法(含 KKT 条件)

最优化问题通常是指对于给定的某一函数&#xff0c;求其在指定作用域上的全局最小值&#xff0c;一般情况下&#xff0c;最优化问题一般分为三种情况&#xff1a; &#xff08;1&#xff09;无约束条件 对于无约束条件的优化问题中&#xff0c;如果一个函数 f 是凸函数&#…

蓝桥杯-代码-数字三角形

一:题目 二:代码 #include <iostream> #include<vector> using namespace std; int main() {/**思路:1.确定dp数组的定义以及下标的含义dp[i][j] 表示的是一条路径到达下标i和j时&#xff0c;的最大值 2.确定dp数组的状态转移公式我们当前位置的最大值其实是由右上…

ABP VNext从单体切换到微服务

注&#xff1a;此处的微服务只考虑服务部分&#xff0c;不考虑内外层网关、认证等。ABP VNext从单体切换到微服务&#xff0c;提供了相当大的便利性&#xff0c;对于各模块内部不要做任何调整&#xff0c;仅需要调整承载体即可。ABP can help you in that point by offerring a…

dotnet 在 UOS 国产系统上使用 Xamarin Forms 创建 xaml 界面的 GTK 应用

在前面几篇博客告诉大家如何部署 GTK 应用&#xff0c;此时的应用是特别弱的&#xff0c;大概只是到拖控件级。尽管和 WinForms 一样也能写出特别强大的应用&#xff0c;但是为了提升一点开发效率&#xff0c;咱开始使用 xaml 神器写界面。本文告诉大家如何在 UOS 国产系统上&a…