上周给你们分享了Nancy in .NET Core学习笔记 - 路由以后, 就一直在考虑.NET Core可否实现和Nancy中同样的路由约束, 最近查阅了一下MSDN及一些国外博客, 发现.NET Core中已经实现了相同的功能,因此这里给你们分享一下。html
路由约束是路由中的一种设置,能够帮助咱们限制Url中的参数类型,只有当参数符合约束条件的时候,action才会被激活并触发。正则表达式
好比咱们如今有如下2个Urlexpress
[GET] /api/posts/{id}
[GET] /api/posts/{name}api
咱们但愿当Posts后面的参数是int类型的时候触发第一个Url所指向action, 参数是string类型的时候触发第二个Url所指向的action。app
在这种场景下,咱们就须要使用路由约束。post
在.NET Core中有2种添加路由约束的方法。学习
当路由引擎发现当前的请求Url符合某个路由设置以后,就会去触发当前路由设置中的全部路由约束,当全部的约束都返回true, 这个路由对应的action就会被激活。ui
所谓的行内约束,即在路由Url模板中直接定义。定义的方式是在参数后面加冒号,并制定约束类型。code
例:htm
"/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()方法来添加约束。
例:
using Microsoft.AspNetCore.Routing.Constraints; app.UseMvc(routes => { routes.MapRoute("default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index" }, new { id = new IntRouteConstraint() }); });
.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。
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.Configure<RouteOptions>(routeOptions => { routeOptions.ConstraintMap.Add("email", typeof(EmailConstraint)); }); }
最后咱们看一下效果, 页面中正确显示除了"Coming from GetPostByEmail"。