上週給你們分享了Nancy in .NET Core學習筆記 - 路由以後, 就一直在考慮.NET Core可否實現和Nancy中同樣的路由約束, 最近查閱了一下MSDN及一些國外博客, 發現.NET Core中已經實現了相同的功能,因此這裏給你們分享一下。javascript
路由約束是路由中的一種設置,能夠幫助咱們限制Url中的參數類型,只有當參數符合約束條件的時候,action纔會被激活並觸發。html
好比咱們如今有如下2個Urljava
[GET] /api/posts/{id}
[GET] /api/posts/{name}正則表達式
咱們但願當Posts後面的參數是int類型的時候觸發第一個Url所指向action, 參數是string類型的時候觸發第二個Url所指向的action。express
在這種場景下,咱們就須要使用路由約束。api
在.NET Core中有2種添加路由約束的方法。app
當路由引擎發現當前的請求Url符合某個路由設置以後,就會去觸發當前路由設置中的全部路由約束,當全部的約束都返回true, 這個路由對應的action就會被激活。less
所謂的行內約束,即在路由Url模板中直接定義。定義的方式是在參數後面加冒號,並制定約束類型。post
例:學習
"/api/posts/{id:int}"
因此該方式既能夠在MapRoute方法中使用,也能夠在路由屬性中使用。
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id:int}");
Route("Home/Index/{id:int}")]
public string Index(int id) {
return "I got " + id.ToString();
}
[除了行內約束,咱們還能夠在Startup.cs的中經過app.UseMvc()方法來添加約束。
例:
routes =>
{
routes.MapRoute("default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index" },
new { id = new IntRouteConstraint() });
});
using Microsoft.AspNetCore.Routing.Constraints;
app.UseMvc(.NET Core已經提供了不少基礎的路由約束,整體上分爲3種類型。
約束 | 行內 | Constraint類 | 說明 |
---|---|---|---|
int | {id:int} |
IntRouteConstraint |
只容許int32整數 |
alpha | {id:alpha} |
AlphaRouteConstraint |
只能包含大小寫字母 |
bool | {id:bool} |
BoolRouteConstraint |
只容許布爾類型 |
datetime | {id:datetime} |
DateTimeRouteConstraint |
只容許日期格式 |
decimal | {id:decimal} |
DecimalRouteConstraint |
只容許decimal類型 |
double | {id:double} |
DoubleRouteConstraint |
只容許double類型 |
float | {id:float} |
FloatRouteConstraint |
只容許float類型 |
guid | {id:guid} |
GuidRouteConstraint |
只容許guid類型 |
約束 | 行內 | Constraint類 | 說明 |
---|---|---|---|
length(length) | {id:length(12)} |
LengthRouteConstraint |
字符串長度限制 |
maxlength(value) | {id:maxlength(8)} |
MaxLengthRouteConstraint |
字符串最大長度限制 |
minlength(value) | {id:minlength(4)} |
MinLengthRouteConstraint |
字符串最小長度限制 |
range(min,max) | {id:range(18,120)} |
RangeRouteConstraint |
數值範圍限制 |
min(value) | {id:min(18)} |
MinRouteConstraint |
最小數值限制 |
max(value) | {id:max(120)} |
MaxRouteConstraint |
最大數值限制 |
約束 | 行內 | Constraint類 | 說明 |
---|---|---|---|
regex(expression) | {ssn:regex(^\d{{3}}-\d{{2}}-\d{{4}}$)}/ |
RegexRouteConstraint |
正則表達式約束 |
和Nancy同樣,.NET Core也支持自定義路由約束,咱們能夠經過實現IRouteConstraint
接口的Match
方法來自定義路由約束。
咱們舉一個和以前Nancy in .NET Core學習筆記 - 路由中的相似的例子。
當前咱們有一個PostController
類,代碼以下:
ApiController]
public class PostController : ControllerBase
{
[HttpGet]
[Route("~/api/posts/{id:int}")]
public IActionResult GetPostById(int id) {
return Content("Coming from GetPostById");
}
[HttpGet]
[Route("~/api/posts/{name:alpha}")]
public IActionResult GetPostByName(string name) {
return Content("Coming from GetPostByName");
}
}
[這時候咱們添加新的action方法GetPostByEmail, 並追加一個email約束,方法以下:
HttpGet]
[Route("~/api/posts/{email:email}")]
public IActionResult GetPostByEmail(string email) {
return Content("Coming from GetPostByEmail");
}
[咱們但願當posts後面的參數是email格式的時候,顯示"Coming from GetPostByEmail"。
這裏咱們首先添加一個EmailConstraint
類,並實現IRouteConstraint
接口的Match
方法
public class EmailConstraint : IRouteConstraint
{
public bool Match(HttpContext httpContext, IRouter route, string routeKey, RouteValueDictionary values, RouteDirection routeDirection) {
if (httpContext == null)
throw new ArgumentNullException(nameof(httpContext));
if (route == null)
throw new ArgumentNullException(nameof(route));
if (routeKey == null)
throw new ArgumentNullException(nameof(routeKey));
if (values == null)
throw new ArgumentNullException(nameof(values));
object routeValue;
if (values.TryGetValue(routeKey, out routeValue))
{
var parameterValueString = Convert.ToString(routeValue, CultureInfo.InvariantCulture);
return parameterValueString.Contains("@");
}
return false;
}
}
其中values.TryGetValue(routeKey, out routeValue)
是嘗試從路由參數列表中,取出當前參數的值, 若是當前值中包含@, 咱們就簡單的認爲這個Email約束經過, 並返回true。
上述代碼完成以後,咱們打開Startup.cs文件, 在ConfigureServices
方法中, 咱們將這個自定義的路由約束添加到約束列表中,並指定當前的約束名稱是email。
void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.Configure<RouteOptions>(routeOptions =>
{
routeOptions.ConstraintMap.Add("email", typeof(EmailConstraint));
});
}
public 最後咱們看一下效果, 頁面中正確顯示除了"Coming from GetPostByEmail"。