Web API (四) 特性路由(Attribute Route)

特性路由 是Web API 2 中提出的一种新的类型的路由,正如其名称那样,它是通过特性(Attribute) 来定义路由的,相比之前的基于模式(Convertion Based)的路由,特性路由 能够提供更为灵活和更多的控制。更好的方式是,灵活的组合使用这两种方式。

为什么需要特性路由

  在 特性路由 之前 的 基于模式 的路由,我们需要定义一些包含一些参数化字符串的模板,例如,api/{congroller}/{action}/{id},当接受到请求后,会将请求的 URI 与这些模板进行匹配,这种方式有一个优点那就是所有的路由定义都可以在同一个地方进行配置,这些规则将被应用到所有的 Controller,这也造成也其对一些特定的 URI 的匹配不够灵活,例如,请求的一些资源(Resource) 包含一些子资源,例如顾客具有订单,电影包含演员,书籍具有作者等,这时自然而然的会创建如下的 URI 来映射这种关系:/customers/1/orders。此时如果使用 基于模式 的方式来定义路由规则便会极为的困难,即使能够处理,在具有较多 Controller 和 资源类型时,也并不能达到很好的效果。
  使用特性路由 就可以很好的解决这样的问题,像上面的例子,使用 特性路由 可以很方便的定义满足条件的路由规则,如下所示:

[Route("customers/{customerId}/orders")]
public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }

特性路由的使用

启用特性路由

  为了启用特性路由,需要调用 System.Web.Http.HttpConfigurationExtensions 的扩展方法 MapHttpAttributeRoutes 进行配置。在 App_Start 目录的 WebApiConfig 类中进行配置。

     public static void Register(HttpConfiguration config)
        {
            // Web API 路由
            config.MapHttpAttributeRoutes();

            //Convention-based Route
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
使用特性路由

  下面有一些使用 特性路由 的技巧

  1. 指定 API 版本,下面的两个路由规则分别匹配不同版本的 API 方法
  • api/v1/products
  • api/v2/products
  1. 重载 URI 片段
        /// <summary>
        /// 根据商品名称获取商品
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        [Route("product/{name}")]
        public IHttpActionResult GetProduct(string name)
        {
            if (string.IsNullOrEmpty(name))
                return Ok(products);
            
            var product = products.Where(p =>
            {
                if (p.Name == name)
                    return true;
                return false;
            }).FirstOrDefault();

            if(product != null){
                return Ok(product);
            }
            else
            {
                return NotFound();
            }
        }
        /// <summary>
        /// 返回商品列表
        /// </summary>
        /// <returns></returns>
        [Route("product")]
        public IHttpActionResult GetProduct()
        {
            return Ok(products);
        }
  1. 使用多种类型的参数
        /// <summary>
        /// 根据商品Id获取商品信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [Route("api/product/{id:int}")]
        public IHttpActionResult GetProduct(int id)
        {
            
        }

         /// <summary>
        /// 根据上市时间获取商品
        /// </summary>
        /// <param name="marketdate">上市时间</param>
        /// <returns></returns>
        [Route("api/product/{*marketdate:datetime}")]
        public IHttpActionResult GetProduct(DateTime marketdate)
        {
            
        }
路由前缀

  仔细观察,上面配置的特性路由都具有相同的前缀 api/product/, 使用路由前缀(Route Prefix)我们可以在 Controller 进行统一设置,例如前面的例子,我们就可以改为下面的样子:

    [RoutePrefix("api/product")]
    public class DefaultController : ApiController {
        [Route("{id:int}")]
        public IHttpActionResult GetProduct(int id){
        }
    }
    

  我们还可以使用 ~ 符号对使用了路由前缀的 Controller 中的方法进行路由重写,例如:

    [RoutePrefix("api/product")]
    public class DefaultController : ApiController {
        [Route("~/api/discount/product/{id:int}")]
        public IHttpActionResult GetProduct(int id){
        }       

  上面的例子使用 ~ 对路由进行了重写,新的路由规则将覆盖 Controller 定义的路由前缀,现在该方法所匹配的规则为 api/discount/product/{id:int},而非原来的 api/product/{id:int}
  在定义路由前缀时,还可以包含一些参数,例如:

    [RoutePrefix(api/{customerid})]
    public class DefaultController : ApiController{
       [Route("order")]
       public IEnumerable<Order> GetOrders(int customerid){
       }
   }
可选路由参数和参数默认值

  我们可以使用 ? 将一个路由参数标记为 可选参数(optional parameter),如果一个路由参数被标记为可选的,则必须为其设置默认值。

    [Route("api/product/{id:int?}")]
    public IHttpActionResult GetProduct(int id =1){
    }

  此时,对于 /api/product/id/1/api/product 将返回相同的结果。
  我们不仅可以在方法中设置参数的默认值,还可以在路由特性中进行设置。如下所示,

    [Route("api/product/{id:int=1}")]
    public IHttpActionResult GetProduct(int id){
    }

  上面设置默认值的方法基本完全相同,但是在应用该值时还是有细微的区别,如下所示:
  

  • 对于第一种方式,默认值 1 是直接分配给方法的参数的,因此其总是具有确定的值
  • 对于第二种方式,默认值通过了 模型绑定(Model- Binding) 的过程,在绑定过程中,它会从 "1" 被转换为 System.Int32 类型的 1,然而,我们可以定义自己的模型绑定器,因此,最终参数 id 的默认值并不是确定的,因为其在自定义的模型绑定器中可能被转换为其它的结果。

  通常情况下,使用两种形式给予参数默认值的形式的结果是相同的。

路由参数约束(Constraint)

  通过路由参数约束我们可以将路由模板中的参数限制为指定的类型,通用的语法如下所示:{parameter:costraint},例如前面的例子,将 id的类型限制为 System.Int32

[Route("api/product/{id:int}")]     
public IHttpActionResult GetProduct(int id){}

[Route("api/product/name")]
public IHttpActionResult GetProduct(string name){}

  只有请求的参数为 Int 类型时才会匹配第一个路由规则,否则匹配第二个。
  下表罗列了可用的约束,

  

约束描述例子
alpha将参数约束为大写或者小写的拉丁字母(a-z,A-Z){x:alpha}
bool将参数限制为 bool 类型{x:bool}
datetime将参数限制为 date{x:date}
decimal将参数限制为 decimal 类型{x:decimal}
float将参数限制为 32 位浮点数类型{x:float}
double将参数限制为 64 位浮点数类型{x:double}
int将参数限制为 32 整形{x:int}
long将参数限制为 64位整形{x:long}
guid将参数类型限制为 guid 类型{x:guid}
length将参数的长度限制为指定长度或指定范围的长度{x:length(5)/{x:length(1,10)}
min/max限制参数(整形)最大或最小值{x:min(10)}/{x:max(10)}
minlength/maxlength限制参数的最小长度或最大长度{x:minlength(1)}/{x:maxlength}
range限制参数(整形) 的范围,包含两端{x:range(1,3)}
regex限制参数必须匹配指定的正则表达式{x:regex(\expression)}

  可以同时使用多个约束条件,每个条件之间通过 进行分割,例如

    [Route("api/product/{id:int:min(1)}")]
    public IHttpActionResult GetProduct(int id){}

  除了 内置的约束条件,我们还可以定制自己的约束条件,方法是实现 IHttpConstraint 接口,重写其 public bool Match(   HttpRequestMessage request,   IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection ) 方法
然后通过如下的方式注册自定义的约束后,便可像使用内置约束那样的使用自定义约束了

    public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var constraintResolver = new DefaultInlineConstraintResolver();
        constraintResolver.ConstraintMap.Add(identity, typeof(CustomConstrainType));

        config.MapHttpAttributeRoutes(constraintResolver);
    }
}
Http 方法

  Web API 在选择 Action 时还会基于请求的 Http 方法进行判断, Web Api 默认会匹配控制器方法的开端(匹配不区分大小写),例如,GetProduct 便会被识别为一个 Http Get 方法。我们可以使用内置的一些 Http Method 特性来覆盖默认的实现。

  • HttGet
  • HttpPost
  • HttpHead
  • HttpOptions
  • HttpDelete
  • HttpPacth
  • HttpPut

下面的方法,使用 HttpPost 特性将其标记为 POST 方法

[HttpPost]
[Route("api/product/{id}")]
public IHttpActionResult CreateProduct(){}

  除此之外,还可以使用AcceptVerbs 特性来实现,其接受一个上述特性的列表(方法名字符串列表)

路由名称

  在 Web Api 中每个路由都有自己的名称,这个名称在产生链接是十分的有用。

    [Route("{id:int}",Name ="GetProductById")]
        public Product Get(int id)
        {
            var product = products.Where(p =>
            {
                if (p.Id == id)
                    return true;
                return false;
            }).FirstOrDefault();
            return product;
        }
        [Route("~/api/products/{id:int}")]
        [HttpGet]
        public HttpResponseMessage Find(int id)
        {
            var response = Request.CreateResponse(HttpStatusCode.Created);
            string uri = Url.Link("GetProductById", new { id = });///api/product/id

            //response.Headers.Location = new Uri(uri);
            response.Content = new StringContent(uri);
            return response;
        }
路由的顺序

  当使用一个 Route 去匹配一个 URI 时,会以一个特定的顺序去分析路由,我们可以设置 Route 的 RouteOrder 来指定一个路由的顺序,RouteOrder 是一个整形数字,默认值为0,其值越小,顺序越靠前。
  当接受到一个请求后,会以如下的顺序去匹配路由

  1. 比较路由表中各路由的 RouteOrder
  2. 查看各路由模板中的 URI 片段,对于每个片段按照下面的顺序排列
    1. 字面值(Literal )片段
    2. 具有约束条件的路由参数
    3. 没有约束条件的路由参数
    4. 具有约束条件的通配符参数片段
    5. 没有约束条件的通配符参数片段
  3. 最后,这些路由会按照不区分大小写、独立于语言的排序方式进行排序
      总的来说,就是条件越具体的匹配时的顺序越靠前。
    [RoutePrefix("orders")]
    public class OrdersController : ApiController
    {
    [Route("{id:int}")] // 具有约束的参数
    public HttpResponseMessage Get(int id) { ... }

    [Route("details")]  // 字面值
    public HttpResponseMessage GetDetails() { ... }

    [Route("pending", RouteOrder = 1)]
    public HttpResponseMessage GetPending() { ... }

    [Route("{customerName}")]  // 无约束条件的参数
    public HttpResponseMessage GetByCustomer(string customerName) { ... }

    [Route("{*date:datetime}")]  // 通配符
    public HttpResponseMessage Get(DateTime date) { ... }

}

 按照上面的规则,可以得出下面的顺序:

  1. orders/details
  2. order/{id:int}
  3. order/{customerName}
  4. order/{*date:datetime}
  5. order/penddig

转载于:https://www.cnblogs.com/ITusk/p/7677001.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录 C#进阶系列——WebApi 路由机制剖析:你准备好了吗? ................................................................................................... 3 一、MVC和WebApi路由机制比较 ........................................................................................................................................ 5 1、MVC里面的路由 ......................................................................................................................................................... 5 2、WebApi里面的路由 ................................................................................................................................................... 5 二、WebApi路由基础 ............................................................................................................................................................. 7 1、默认路由 ..................................................................................................................................................................... 7 2、自定义路由 ............................................................................................................................................................... 10 2.1、自定义路由一:匹配到action ................................................................................................................. 11 2.2、自定义路由二 ............................................................................................................................................... 12 3、路由原理 ................................................................................................................................................................... 12 三、WebApi路由过程 ........................................................................................................................................................... 13 1、根据请求的url匹配路由模板 .............................................................................................................................. 13 2、找到控制器 ............................................................................................................................................................... 13 3、找到action ............................................................................................................................................................. 15 WebApi特性路由 ........................................................................................................................................................... 16 1、启动特性路由 ........................................................................................................................................................... 17 2、最简单的特性路由 ................................................................................................................................................... 17 3、带参数的特性路由 ................................................................................................................................................... 19 4、参数的约束和默认值 ............................................................................................................................................... 20 5、路由前缀 ................................................................................................................................................................... 20 五、第一个Restful风格的WebApi服务 ......................................................................................................................... 21 六、总结 ................................................................................................................................................................................. 22 C#进阶系列——WebApi 异常处理解决方案 ......................................................................................................................... 23 一、使用异常筛选器捕获所有异常 ..................................................................................................................................... 24 1、接口级别 ........................................................................................................................................................... 31 2、控制器级别 ....................................................................................................................................................... 33 3、全局配置 ........................................................................................................................................................... 34 二、HttpResponseException自定义异常信息 .............................................................................................................. 35 三、返回HttpError ............................................................................................................................................................ 37 、总结 ................................................................................................................................................................................. 38 C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解 ......................................................................................... 39 一、void无返回值 ............................................................................................................................................................... 40 二、IHttpActionResult .................................................................................................................................................... 42 1、Json(T content) ........................................................................................................................................... 42 2、Ok()、 Ok(T content) ................................................................................................................................. 45 3、NotFound() ............................................................................................................................................................. 47 4、其他 ........................................................................................................................................................................... 49 4.1、Content(HttpStatusCode statusCode, T value) .................................................................. 49 4.2、BadRequest() ............................................................................................................................................ 49 4.3、Redirect(string location) ................................................................................................................ 50 5、自定义IHttpActionResult接口的实现 ............................................................................................................ 50 三、HttpResponseMessage ............................................................................................................................................... 53 、自定义类型 ..................................................................................................................................................................... 54 五、总结 ................................................................................................................................................................................. 55 C#进阶系列——WebApi 接口参数不再困惑:传参详解 ..................................................................................................... 56 一、get请求 ......................................................................................................................................................................... 57 1、基础类型参数 ........................................................................................................................................................... 57 2、实体作为参数 ........................................................................................................................................................... 58 3、数组作为参数 ........................................................................................................................................................... 62 4、“怪异”的get请求 .................................................................................................................................................. 62 (1)WebApi的方法名称以get开头 ................................................................................................................ 62 (2)WebApi的方法名称不以get开头 ............................................................................................................ 64 二、post请求 ....................................................................................................................................................................... 66 1、基础类型参数 ........................................................................................................................................................... 66 (1)错误的写法 ................................................................................................................................................... 66 (2)正确的用法 ................................................................................................................................................... 67 (1)错误写法 ....................................................................................................................................................... 68 (2)正确用法 ....................................................................................................................................................... 69 (3)推荐用法 ....................................................................................................................................................... 70 2、实体作为参数 ........................................................................................................................................................... 70 (1)单个实体作为参数 ....................................................................................................................................... 70 (2)实体和基础类型一起作为参数传递 ........................................................................................................... 73 3、数组作为参数 ........................................................................................................................................................... 74 (1)基础类型数组 ............................................................................................................................................... 74 (2)实体集合 ....................................................................................................................................................... 74 4、后台发送请求参数的传递 ....................................................................................................................................... 75 三、put请求 ......................................................................................................................................................................... 77 1、基础类型参数 ........................................................................................................................................................... 77 2、实体作为参数 ........................................................................................................................................................... 77 3、数组作为参数 ........................................................................................................................................................... 78 、delete请求 ................................................................................................................................................................... 78 五、总结 ................................................................................................................................................................................. 79 C#进阶系列——WebApi 身份认证解决方案:Basic基础认证.......................................................................................... 80 一、为什么需要身份认证 ..................................................................................................................................................... 81 1、我们不加身份认证,匿名用户可以直接通过url随意访问接口: ........................................................... 81 2、增加了身份认证之后,只有带了我们访问票据的请求才能访问我们的接口。 ....................................... 82 二、Basic基础认证的原理解析 ......................................................................................................................................... 84 1、常见的认证方式 ....................................................................................................................................................... 84 2、Basic基础认证原理 ............................................................................................................................................... 85 三、Basic基础认证的代码示例 ......................................................................................................................................... 85 1、登录过程 ................................................................................................................................................................... 85 1.1、Web前端 ....................................................................................................................................................... 85 1.2、登录的API接口 .......................................................................................................................................... 86 2、/Home/Index主界面 .............................................................................................................................................. 88 3、WebApiCORS验证部分(重点) ............................................................................................................................ 90 3.1、在WebApiCORS项目里面自定义一个类RequestAuthorizeAttribute,去继承我们的AuthorizeAttribute这个类。然后重写OnAuthorization方法,在这个方法里面取到请求头的Ticket信息,然后校验用户名密码是否合理。 ............................................................................................................. 90 3.2、在具体的Api接口增加我们上面自定义类的特性 .................................................................................. 91 、优化 ................................................................................................................................................................................. 92 1、解决API的问题 ...................................................................................................................................................... 92 2、解决ajax的问题 .................................................................................................................................................... 93 3、解决特殊不想使用验证的方法 ............................................................................................................................... 94 五、总结 ................................................................................................................................................................................. 95 C#进阶系列——WebApi 跨域问题解决方案:CORS ............................................................................................................. 95 一、跨域问题的由来 ............................................................................................................................................................. 96 二、跨域问题解决原理 ......................................................................................................................................................... 96 三、跨域问题解决细节 ......................................................................................................................................................... 96 1、场景描述 ................................................................................................................................................................... 97 2、场景测试 ................................................................................................................................................................... 99 1)我们不做任何的处理,直接将两个项目运行起来。看效果如何 ............................................................... 99 2)使用CORS跨域 ................................................................................................................................................ 99 3)CORS的具体参数设置。 ............................................................................................................................... 103 、总结 ............................................................................................................................................................................... 104 C#进阶系列——WebApi 接口测试工具:WebApiTestClient ........................................................................................ 105 一、WebApiTestClient介绍 ........................................................................................................................................... 106 二、WebApiTestClient展示 ........................................................................................................................................... 106 三、WebApiTestClient使用 ........................................................................................................................................... 116 1、如何引入组件 ......................................................................................................................................................... 116 2、如何使用组件 ......................................................................................................................................................... 118 1、修改Api.cshtml文件 ................................................................................................................................. 118 2、配置读取注释的xml路径 ............................................................................................................................ 119 3、测试接口 ......................................................................................................................................................... 121 、总结 ............................................................................................................................................................................... 123
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值