.NET 路由约束


theme: github

路由约束

路由约束是路由中的一种设置,可以帮助我们限制Url中的参数类型,只有当参数符合约束条件的时候,action才会被激活并触发。

比如我们现在有以下2个Url

[GET] /api/posts/{id}
[GET] /api/posts/

我们希望当Posts后面的参数是int类型的时候触发第一个Url所指向action, 参数是string类型的时候触发第二个Url所指向的action。

在这种场景下,我们就需要使用路由约束。

如何添加路由约束

在.NET Core中有2种添加路由约束的方法。

  • 行内约束(Inline Constraint)
  • 使用MapRoute方法带Constraint参数的重载

当路由引擎发现当前的请求Url符合某个路由设置之后,就会去触发当前路由设置中的所有路由约束,当所有的约束都返回true, 这个路由对应的action就会被激活。

行内约束(Inline Constraint)

所谓的行内约束,即在路由Url模板中直接定义。定义的方式是在参数后面加冒号,并制定约束类型。

例:

"/api/posts/{id:int}"

所以该方式既可以在MapRoute方法中使用,也可以在路由属性中使用。

在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(); }

使用MapRoute方法带Constraint参数的重载

除了行内约束,我们还可以在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内置的路由约束

.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方法来自定义路由约束。

当前我们有一个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.Version21);

services.Configure<RouteOptions>(routeOptions =>
{
    routeOptions.ConstraintMap.Add("email", typeof(EmailConstraint));
});

} ```

最后我们看一下效果, 页面中正确显示除了"Coming from GetPostByEmail"。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值