1. ASP.NET Core中自定义路由约束的实现

     更新时间:2019年03月25日 09:27:35   作者:weilence   我要评论

    这篇文章主要介绍了ASP.NET Core中自定义路由约束的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    路由约束

    ASP.NET Core中,通过定义路由模板,可以在Url上传递变量,同时可以针对变量提供默?#29616;怠?#21487;选和约束。

    约束的使用方法是在属性路由上添加指定的约束名,用法如下:

    // 单个使用
    [Route("users/{id:int}")]
    public User GetUserById(int id) { }
    // 组合使用
    [Route("users/{id:int:min(1)}")]
    public User GetUserById(int id) { }

    框架内部已经提供了一些约束,如下所示:

    约束 示例 匹配项示例 说明
    int {id:int} 123456789, -123456789 匹配任何整数
    bool {active:bool} true, FALSE 匹配 true或 false(区分大小写)
    datetime {dob:datetime} 2016-12-31, 2016-12-31 7:32pm 匹配有效的 DateTime 值(位于固定区域性中 - 查看警告)
    decimal {price:decimal} 49.99, -1,000.01 匹配有效的 decimal 值(位于固定区域性中 - 查看警告)
    double {weight:double} 1.234, -1,001.01e8 匹配有效的 double 值(位于固定区域性中 - 查看警告)
    float {weight:float} 1.234, -1,001.01e8 匹配有效的 float 值(位于固定区域性中 - 查看警告)
    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 个字符
    maxlength(value) {filename:maxlength(8)} Richard 字符串不得超过 8 个字符
    length(length) {filename:length(12)} somefile.txt 字符串必须正好为 12 个字符
    length(min,max) {filename:length(8,16)} somefile.txt 字符串必须至少为 8 个字符,且不得超过 16 个字符
    min(value) {age:min(18)} 19 整数值必须至少为 18
    max(value) {age:max(120)} 91 整数值不得超过 120
    range(min,max) {age:range(18,120)} 91 整数值必须至少为 18,且不得超过 120
    alpha {name:alpha} Rick 字符串必须由一个或多个字母字符(a-z,区分大小写)组成
    regex(expression) {ssn:regex(^\d{{3}}-\d{{2}}-\d{{4}}$)} 123-45-6789 字符串必须匹配正则表达式(参见有关定义正则表达式的提示)
    required {name:required} Rick 用于强制在 URL 生成过程中存在非参数值

    内置的约束能够适用于大部分常见的应用场景,但是有时候我们还是需要去自定义我们想要的效果。

    自定义路由约束

    自定义约束是要实现 IRouteConstraint 接口,然后重载 Match 方法,该方法有四个参数。

    第一个参数 httpContext 是当前请求的上下文

    第二个参数 route 是当前约束所属的路由

    第三个参数 routeKey 是当前检查的变量名,例如文章开头示例中的 id

    第四个参数 values 是当前Url匹配的?#20540;?#20540;,例如文章开头的示例的路由,如果Url是 users/1 ,那么就有一个?#20540;洌?#20854; key = id , value = 1 。当然还有其他的变量的值,比如 controller , action 等。

    第五个参数 routeDirection 是一个枚举值,代表是web请求的还是用 Url.Action 等方法生成Url。

    举一个实例,我们想要定义一个约束,指定路由传过来的参数必须是指定的枚举值。

    我们先定义一个枚举:

    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 是当前的 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) ,否则对于 id = 0 或 id = 1 会有冲突。

    运行程序,当路由是 api/Test/0 、 api/Test/1 、 api/Test/True 和 api/Test/False 的时候,匹配我们的自定义约束。

    当路由是 api/Test/{大于2的整数} 的时候,匹配第二个路由。

    其他情况匹配第三个路由。

    结论

    路由约束在某些场景下是非常有用的功能,可?#32422;?#23569; controller 中校验参数,将部分参数校验的功能使用声明式的 attruibute 来实现,某些重复的校验可以通过抽取成约束公共使用。

    constraint 的构造函数可以使用注入,所以可以扩展性十分强,可以通过查询数据库做一些参数校验。

    官网上对于路由约束只是简单的提了一下,本文对路由约束的使用提供了具体的示例。

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    相关文章

    最新评论

    山东群英会开奖查询
      1. 江苏快三开奖视频 快乐赛车投注网 宁夏十一选五开将结果 海南4十1最新开奖结果查询 山东群英会2019年 nba2kol2战术 组三组六稳赚技巧 安徽快三开奖结果着 合单数有哪些号码 14场胜负彩专家预测 超级体彩大乐透走势图 搜索广西新快3开奖结果 金盾黑龙江时时彩 广西快三遗漏图 曾道人一肖一码中特平