ASP.NET Core中自定義路由約束的實(shí)現(xiàn)
路由約束
ASP.NET Core中,通過定義路由模板,可以在Url上傳遞變量,同時(shí)可以針對(duì)變量提供默認(rèn)值、可選和約束。
約束的使用方法是在屬性路由上添加指定的約束名,用法如下:
// 單個(gè)使用 [Route("users/{id:int}")] public User GetUserById(int id) { } // 組合使用 [Route("users/{id:int:min(1)}")] public User GetUserById(int id) { }
框架內(nèi)部已經(jīng)提供了一些約束,如下所示:
約束 | 示例 | 匹配項(xiàng)示例 | 說明 |
---|---|---|---|
int | {id:int} | 123456789, -123456789 | 匹配任何整數(shù) |
bool | {active:bool} | true, FALSE | 匹配 true或 false(區(qū)分大小寫) |
datetime | {dob:datetime} | 2016-12-31, 2016-12-31 7:32pm | 匹配有效的 DateTime 值(位于固定區(qū)域性中 - 查看警告) |
decimal | {price:decimal} | 49.99, -1,000.01 | 匹配有效的 decimal 值(位于固定區(qū)域性中 - 查看警告) |
double | {weight:double} | 1.234, -1,001.01e8 | 匹配有效的 double 值(位于固定區(qū)域性中 - 查看警告) |
float | {weight:float} | 1.234, -1,001.01e8 | 匹配有效的 float 值(位于固定區(qū)域性中 - 查看警告) |
guid | {id:guid} | CD2C1638-1638-72D5-1638-DEADBEEF1638, {CD2C1638-1638-72D5-1638-DEADBEEF1638} | 匹配有效的 Guid 值 |
long | {ticks:long} | 123456789, -123456789 | 匹配有效的 long 值 |
minlength(value) | {username:minlength(4)} | Rick | 字符串必須至少為 4 個(gè)字符 |
maxlength(value) | {filename:maxlength(8)} | Richard | 字符串不得超過 8 個(gè)字符 |
length(length) | {filename:length(12)} | somefile.txt | 字符串必須正好為 12 個(gè)字符 |
length(min,max) | {filename:length(8,16)} | somefile.txt | 字符串必須至少為 8 個(gè)字符,且不得超過 16 個(gè)字符 |
min(value) | {age:min(18)} | 19 | 整數(shù)值必須至少為 18 |
max(value) | {age:max(120)} | 91 | 整數(shù)值不得超過 120 |
range(min,max) | {age:range(18,120)} | 91 | 整數(shù)值必須至少為 18,且不得超過 120 |
alpha | {name:alpha} | Rick | 字符串必須由一個(gè)或多個(gè)字母字符(a-z,區(qū)分大小寫)組成 |
regex(expression) | {ssn:regex(^\d{{3}}-\d{{2}}-\d{{4}}$)} | 123-45-6789 | 字符串必須匹配正則表達(dá)式(參見有關(guān)定義正則表達(dá)式的提示) |
required | {name:required} | Rick | 用于強(qiáng)制在 URL 生成過程中存在非參數(shù)值 |
內(nèi)置的約束能夠適用于大部分常見的應(yīng)用場(chǎng)景,但是有時(shí)候我們還是需要去自定義我們想要的效果。
自定義路由約束
自定義約束是要實(shí)現(xiàn) IRouteConstraint 接口,然后重載 Match 方法,該方法有四個(gè)參數(shù)。
第一個(gè)參數(shù) httpContext 是當(dāng)前請(qǐng)求的上下文
第二個(gè)參數(shù) route 是當(dāng)前約束所屬的路由
第三個(gè)參數(shù) routeKey 是當(dāng)前檢查的變量名,例如文章開頭示例中的 id
第四個(gè)參數(shù) values 是當(dāng)前Url匹配的字典值,例如文章開頭的示例的路由,如果Url是 users/1 ,那么就有一個(gè)字典,其 key = id , value = 1 。當(dāng)然還有其他的變量的值,比如 controller , action 等。
第五個(gè)參數(shù) routeDirection 是一個(gè)枚舉值,代表是web請(qǐng)求的還是用 Url.Action 等方法生成Url。
舉一個(gè)實(shí)例,我們想要定義一個(gè)約束,指定路由傳過來的參數(shù)必須是指定的枚舉值。
我們先定義一個(gè)枚舉:
public enum BoolEnum { True, False }
然后定義約束:
public class EnumConstraint : IRouteConstraint { private Type _enumType; public EnumConstraint(string enumTypeName) { _enumType = Type.GetType(enumTypeName); } public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) { var value = values[routeKey]; if (value == null) { return false; } if (Enum.TryParse(_enumType, value.ToString(), out object result)) { if (Enum.IsDefined(_enumType, result)) { return true; } } return false; } }
在 Startup.cs 的 ConfigureServices 方法添加自定義約束:
services.Configure<RouteOptions>(options => { options.ConstraintMap.Add("enum", typeof(EnumConstraint)); });
在路由上使用約束:
( WebApplicationTest 是當(dāng)前的 namespace )
[Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { // GET: api/Test [HttpGet("{bool:enum(" + nameof(WebApplicationTest) + "." + nameof(BoolEnum) + ")}")] public string Get(BoolEnum @bool) { return "bool: " + @bool; } [HttpGet("{id:int:min(2)}", Name = "Get")] public string Get(int id) { return "id: " + id; } [HttpGet("{name}")] public string Get(string name) { return "name: " + name; } }
{id:int:min(2)} 路由必須使用 min(2) ,否則對(duì)于 id = 0 或 id = 1 會(huì)有沖突。
運(yùn)行程序,當(dāng)路由是 api/Test/0 、 api/Test/1 、 api/Test/True 和 api/Test/False 的時(shí)候,匹配我們的自定義約束。
當(dāng)路由是 api/Test/{大于2的整數(shù)} 的時(shí)候,匹配第二個(gè)路由。
其他情況匹配第三個(gè)路由。
結(jié)論
路由約束在某些場(chǎng)景下是非常有用的功能,可以減少 controller 中校驗(yàn)參數(shù),將部分參數(shù)校驗(yàn)的功能使用聲明式的 attruibute 來實(shí)現(xiàn),某些重復(fù)的校驗(yàn)可以通過抽取成約束公共使用。
constraint 的構(gòu)造函數(shù)可以使用注入,所以可以擴(kuò)展性十分強(qiáng),可以通過查詢數(shù)據(jù)庫(kù)做一些參數(shù)校驗(yàn)。
官網(wǎng)上對(duì)于路由約束只是簡(jiǎn)單的提了一下,本文對(duì)路由約束的使用提供了具體的示例。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 詳解ASP.NET WEB API 之屬性路由
- ASP.NET?Core?MVC路由(Routing)的用法
- ASP.NET Core中的Razor頁(yè)面實(shí)現(xiàn)路由功能
- ASP.NET?Core使用功能開關(guān)控制路由訪問操作(續(xù))
- ASP.NET?Core使用功能開關(guān)控制路由訪問操作
- Asp.net Core 如何設(shè)置黑白名單(路由限制)
- 詳解ASP.NET Core端點(diǎn)路由的作用原理
- asp.net core webapi項(xiàng)目配置全局路由的方法示例
- asp.net core 屬性路由和約定路由的實(shí)現(xiàn)
相關(guān)文章
DataGrid使用心得(調(diào)用及連接數(shù)據(jù)庫(kù)等等)
在工作中遇到把DataGrid中綁定的后臺(tái)數(shù)據(jù)庫(kù)數(shù)據(jù)展示給用戶時(shí)把負(fù)數(shù)變?yōu)?的小問題,現(xiàn)在把它記錄下來包括DataGrid的調(diào)用/連接數(shù)據(jù)庫(kù)進(jìn)行操作等等,感興趣的朋友可以了解下,或許本新得對(duì)你有所幫助2013-02-02ASP.NET Core啟動(dòng)地址配置方法及優(yōu)先級(jí)順序
這篇文章主要介紹了ASP.NET Core啟動(dòng)地址配置方法及優(yōu)先級(jí)順序,如果在同一臺(tái)機(jī)器上運(yùn)行多個(gè)ASP.NET Core實(shí)例,使用默認(rèn)值肯定不合適,下面我們一起進(jìn)入文章了解具體內(nèi)容吧2022-03-03關(guān)于有些Asp.net項(xiàng)目發(fā)布后出現(xiàn)網(wǎng)址亂碼的解決方法
最近在部署一個(gè)網(wǎng)站,net2.0開發(fā)的,但是遇到一個(gè)很奇怪的問題。2011-07-07.NET CORE中使用AutoMapper進(jìn)行對(duì)象映射的方法
這篇文章主要給大家介紹了關(guān)于.NET CORE中使用AutoMapper進(jìn)行對(duì)象映射的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用.NET CORE具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04.NET CORE動(dòng)態(tài)調(diào)用泛型方法詳解
這篇文章主要為大家詳細(xì)介紹了.NET CORE動(dòng)態(tài)調(diào)用泛型方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08.net 應(yīng)對(duì)網(wǎng)站訪問壓力的方案總結(jié)
本文將總結(jié)下一些應(yīng)對(duì)網(wǎng)站訪問壓力的技術(shù)方案。具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02.NET6環(huán)境下實(shí)現(xiàn)MQTT通信及詳細(xì)代碼演示
本文詳細(xì)講解了.NET6環(huán)境下實(shí)現(xiàn)MQTT通信的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07asp.net實(shí)現(xiàn)圖片以二進(jìn)制流輸出的兩種方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)圖片以二進(jìn)制流輸出的兩種方法,以簡(jiǎn)單實(shí)例形式分析了asp.net實(shí)現(xiàn)以二進(jìn)制流形式讀寫圖片文件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-12-12