WebApi深入学习--特性路由

特性路由

WebApi2默认的路由规则我们称作基于约定路由,很多时候我们使用RESTful风格的URI.简单的路由是没问题的,如 api/Products/{id},但有些事很难处理的,如资源之间存在嵌套关系:客户包含订单,书有作者属性等等。对于这种Uri,我们希望的路由是这样的:/costomers/{customerid}/orders 或 /costomers/{customerid}/orders/{orderid}

考虑到这只是某个Controller的路由格式,而我们会有很多个Controller,用基于约定路由显然不合适(要配置很多的路由)

使用特性路由就简单了,在action上加一个特性即可

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

通过使用特性路由,我们还可以做API的版本控制

/api/v1/products
/api/v2/products

启用特性路由需要在配置过程中调用System.Web.HttpConfigurationExtensions类的MapHttpAttributeRoutes方法

using System.Web.Http;

namespace WebApplication
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();

            // Other Web API configuration not shown.
        }
    }
}

在WebApi1中  项目模板是这样的

protected void Application_Start()
{
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    //。。。
}

如果要启用特性路由,需要改成如下代码

protected void Application_Start()
{
    GlobalConfiguration.Configure(WebApiConfig.Register);
    //。。。
}

:特性路由和基于约定路由是可以结合使用大的。

HttpMethod

默认情况,WebApi会根据action的方法名前缀查找action(不区分大小写),比如GetUsers,会匹配Get。通过在action上添加HttpMethod特性,可以覆盖action需要映射的Http Method。

可使用的特性包括:[HttpDelete],[HttpPost],[HttpHead],[HttpOptions],[HttpPatch],[HttpGet],[HttpPut]

通过AcceptVerbs特性,我们还可以指定非标准方法以及多个方法,如 [AcceptVerbs("MKCOL","GET","POST")]

路由前缀

通常情况下,一个Controller下的action会使用相似的路由模板,如

  • [Route("api/books")]
  • [Route("api/books/{id:int}")]
  • [Route("api/books/{bookid}/authors")]

这时候可以为整个controller指定[RoutePrefix]特性,以使用共同的前缀,把[RoutePrefix("/api/books")]加到controller上,action的路由特性就变成这样:

  • [Route("")]
  • [Route("{id:int}")]
  • [Route("{bookid}/authors")]

此外,路由前缀中也可以包含参数,如[RoutePrefix("api/{userid}/books")]

路由约束

路由约束让我们可以限制模板参数的匹配方式。一般的语法是 "{参数:约束类型}":

[Route("users/{id:int}"]
public User GetUserById(int id) { ... }

[Route("users/{name}"]
public User GetUserByName(string name) { ... }

如果参数int,则选中第一个GetUserById,否则是GetUserByName。(跟方法定义的顺序无关)

下面的表格列出了支持的约束

约束 介绍 示例
alpha 匹配大写或小写字母 (a-z, A-Z) {x:alpha}
bool   {x:bool}
datetime   {x:datetime}
decimal   {x:decimal}
double   {x:double}
float 匹配一个 32位浮点数 {x:float}
guid   {x:guid}
int   {x:int}
length 匹配一个长度在指定范围内的字符串 {x:length(6)}
{x:length(1,20)}
long   {x:long}
max 匹配指定了最大值的整数 {x:max(10)}
maxlength 匹配指定了最大长度字符串 {x:maxlength(10)}
min 匹配指定了最小值的整数 {x:min(10)}
minlength 匹配指定了最小长度字符串 {x:minlength(10)}
range 匹配指定了大小区间的整数 {x:range(10,50)}
regex 匹配一个正则表达式 {x:regex(^\d{3}-\d{3}-\d{4}$)}

如果要指定多个约束,需要用冒号间隔 [Route("users/{id:int:min(1)}")]

通过实现IHttpRouteConstraint接口,还可以创建自定义路由约束。(不过一般正则就可以搞定了)

还可以通过实现IInlineConstraintResolver接口替换整个DefaultInlineConstraintResolver类。这样做将取代所有的内置的约束,除非实现IInlineConstraintResolver的类将它们添加进去。

public class NonZeroConstraint : IHttpRouteConstraint
{
    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
        IDictionary<string, object> values, HttpRouteDirection routeDirection)
    {
        object value;
        if (values.TryGetValue(parameterName, out value) && value != null)
        {
            long longValue;
            if (value is long)
            {
                longValue = (long)value;
                return longValue != 0;
            }
        }
        return false;
    }
}

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

        config.MapHttpAttributeRoutes(constraintResolver);
    }
}

[Route("{id:nonzero}")]
public HttpResponseMessage GetNonZero(int id) { ... }

自定义路由约束Demo

可选URI参数,默认值

通过在参数约束后面添加一个问号,可以设定URI参数是可选的;也可以像普通方法那样指定默认值:

[Route("api/books/locale/{lcid:int?}")]
public IEnumerable<Book> GetBooksByLocale(int lcid = 1033) { ... }
[Route("api/books/locale/{lcid:int=1033}")]
public IEnumerable<Book> GetBooksByLocale(int lcid) { ... }

这两者是等价的

路由名称

WebApi中,每一个路由都有一个名字,用于生成链接,并在放入Http响应中。(应该是用于重定向吧)

例如对某个action A指定Name,[Route("api/books/{id}", Name="GetBookById")]

那么其他action B在需要返回这个action A的链接时,就可以这样使用

public HttpResponseMessage Post(Book book)
{
    var response = Request.CreateResponse(HttpStatusCode.Created);
    string uri = Url.Link("GetBookById", new { id = book.BookId });
    response.Headers.Location = new Uri(uri);
    return response;
}

路由顺序

通过设定特性[Route("xxx",RouteOrder=n)]可以指定路由的查找顺序

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

不过意义不大,通过顺序来控制,还不如设定更好的路由来的实际,而且不至于让开发人员觉得混乱。

http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#order

翻译:http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

时间: 2024-10-10 04:46:52

WebApi深入学习--特性路由的相关文章

[Web API] Web API 2 深入系列(5) 特性路由

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 目录 1. 特性路由注册 2. 路由解析 - 生成DataTokens - 选择HttpController - 选择Action 特性路由的目的在于更好的提供restful架构的接口,最近好忙(懒),所以更新速度慢. 特性路由注册 [Rout

AngularJS学习---Routing(路由) &amp; Multiple Views(多个视图) step 7

1.切换分支到step7,并启动项目 git checkout step-7 npm start 2.需求: 在步骤7之前,应用只给我们的用户提供了一个简单的界面(一张所有手机的列表),并且所有的模板代码位于index.html文件中.下一步是增加一个能够显示我们列表中每一部手机详细信息的页面.可以先看一下step6和7的代码区别 . 为了增加详细信息视图,我们可以拓展index.html来同时包含两个视图的模板代码,但是这样会很快给我们带来巨大的麻烦.相反,我们要把index.html模板转变

Mvc-WebAPI特性路由(自定义路由)Demo

Demo由VS2017编写. 1.先建一个WebApi项目 2.WebApiConfig.cs需要注册特性路由,config.MapHttpAttributeRoutes(); 3.项目默认有2个Controller,我暂时不动默认的了,新建一个WebApiController:TestController 4.在TestController 类名上加上RoutePrefix特性,api前缀:在下面写一个测试的User类,后面会用到: 在TestController 写两个方法GetUser .

SPA学习之 - 路由插件(crossroads.js)

Crossroads.js是一个受Rails, Pyramid, Django, CakePHP等基于路由/分发(Route/Dispatch)方式处理路由的后端MVC框架启发的一套js专业路由库.它能够直接解析传入的字符串并根据相应的规则来过滤和验证路由,然后再执行下一步的操作. A duck can walk, fly and swim, but he can’t do any of these things well… crossroads.js是一个独立的库功能十分强大和灵活,而且职责单

webapi的学习资料

猿教程_-webapi教程-WebAPI教程 猿教程_-webapi教程-Web API概述 猿教程_-webapi教程-新建Web Api项目 猿教程_-webapi教程-测试Web API 猿教程_-webapi教程-Web API Controller 这里列举一下webapi的学习资料,大家可以在这里好好学习web api

MVC笔记--特性路由

物性路由:将路由和控制器放在一起,这样更简单方便,还可以处理复杂的路由场景 传统路由:集中.强制.基于代码风格来定义的. 每个MVC应用程序都需要路由来定义自己的处理请求方式,路由是MVC是应用程序的入口点.我们先了解一下路由涉及的主要概念:路由定义是从URL模板开始的,因为它指定了与路由相匹配的模式.路由定义可以做为控制器类或操作方法的特性.路由可以指定的它的URL及其默认值,此外,它还可以约束URL的各个部分,提供关于路由如何及何时与传入的URL相匹配的严格控制. 创建一个MVC程序后,我们

ASP.NET MVC学习之路由篇(1)

原文:ASP.NET MVC学习之路由篇(1) 一.前言 作为一个从ASP.NET转入到ASP.NET MVC的开发人员而言,可能在开发ASP.NET网站的时候就已经开始在使用路由了. 只不过在ASP.NET MVC中路由是关键部分,而在ASP.NET中需要自行加进去.下面我们将学习ASP.NET MVC中的路由 系统. 二.准备工作 1.新建一个ASP.NET MVC4项目 2.模板选择空 3.在Controllers中添加一个Home控制器 4.打开App_Start中的RouteConfi

MVC特性路由的提供机制

回顾:传统路由是如何提供的? 我们知道最终匹配的路由数据是保存在RouteData中的,而RouteData通常又是封装在RequestContext中的,他们是在哪里被创建的呢?没错,回到了UrlRoutingModule,我们知道UrlRoutingModule通过注册HttpApplication的PostResolveRequestCache方法来分发IHttpHandler决定ASP.NET请求最终交给哪个IHttpHandler去处理的.其实在这之前,首先会通过当前请求的HttpCo

ASP.NET MVC学习之路由篇(3)

根据路由输出链接 既然是网站开发自然少不了链接,我们已经学会了强大的路由,但是还缺少一步就是能够将这些路由的路径输出到页面,下面我们就开始学习如何输出路由路径. 首先我们的路由注册部分如下所示: 1 namespace MvcStudy 2 { 3 public class RouteConfig 4 { 5 public static void RegisterRoutes(RouteCollection routes) 6 { 7 routes.Add(new Route("MyTest&q