Web API路由
2016-05-18 11:14
127 查看
原文地址
本文讲解ASP.NET Web API如何将HTTP请求路由至控制器。
如果你熟悉ASP.NET MVC,Web API路由与MVC路由非常相似。主要差别是Web API使用HTTP方法,而不是URI路径来选择Action。你也可以按照之前配置MVC路由的方式来配置Web API路由。本文不需要任何ASP.NET MVC知识。
Routing Tables路由表
在Asp.Net Web API中,一个控制器就是一个处理HTTP请求的类,控制器的public 方法被叫做action方法或者简单的Aciton。当Web API接收到一个请求的时候,它将这个请求路由到一个Action。为了确定那个Action被调用,这个框架使用了一个路由表。Visual Studio中Web API的项目模板会创建一个默认路由:
routes.MapHttpRoute( name: "API Default", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } );
这个路由是在WebApiConfig.cs文件中定义的,该文件位于App_Start目录。
关于WebApiConfig类的更多信息参阅“配置ASP.NET Web API”
如果你要自己托管(self-host )Web API,你必须直接在HttpSelfHostConfiguration对象上设置路由表。更多信息参阅“自托管Web API“。
路由表中的每一个条目都包含一个路由模板。这个Web API默认的路由模版是”api/{controller}/{id}”。在这个模版中,“api”是一个文字式路径片段(literal path segment),而{controller}和{id}则是占位符变量。
当Web API框架接收一个HTTP请求时,它会试图根据路由表中的一个路由模板来匹配其URI。如果无路由匹配,客户端会接收到一个404(未找到)错误。例如,以下URI与这个默认路由的匹配:
/api/contacts /api/contacts/1 /api/products/gizmo1
然而,以下URI不匹配,因为它缺少“api”片段:
/contacts/1
小注:
在路由中使用“api”的原因是为了避免与ASP.NET MVC的路由冲突。通过这种方式,可以用“/contacts”进入一个MVC控制器,而“/api/contacts”进入一个Web API控制器。当然,如果你不喜欢这种约定,你也可以修改这个默认路由表。
一旦一个匹配的路由被发现,Web API便会选择相应的Controller和Action:
为了找到Controller,Web API会把“控制器”加到{controller}变量的值。
为了找到Action,Web API会查找HTTP方法,然后寻找一个名称以HTTP方法名开头的方法。例如,对于一个Get请求,Web API会查找一个以“Get…”开头的动作,如“GetContact”或“GetAllContacts”等。这种约定只应用于GET、POST、PUT和DELETE方法。通过在你的Controller上使用attributes,你可以启用其他的HTTP方法。稍后我们就会看到一个例子。
路由模版中其他的占位变量,例如{id},将被映射成Action的参数。
让我们来看一个简单的例子,假设你定义了以下控制器:
public class ProductsController : ApiController { public void GetAllProducts() { } public IEnumerable<Product> GetProductById(int id) { } public HttpResponseMessage DeleteProduct(int id){ } }
以下是一些可能的HTTP请求,以及要被调用的每个动作:
HTTP Method | URI Path | Action | Parameter |
---|---|---|---|
GET | api/products | GetAllProducts | (none) |
GET | api/products/4 | GetProductById | 4 |
DELETE | api/products/4 | DeleteProduct | 4 |
POST | api/products | (no match) |
另外要注意,POST请求是失败的,因为该控制器未定义“Post…”方法。
Routing Variations路由变化
上一节描述了ASP.NET Web API基本的路由机制。本小节描述一些变化。HTTP方法
替代使用HTTP方法的命名约定,你可以明确的为一个Action指定HTTP方法,通过以HttpGet、HttpPost、HttpPut或者HttpDelete属性来对Action方法进行修饰。在下列示例中,FindProduct方法被映射到GET请求:
public class ProductsController : ApiController { [HttpGet] public Product FindProduct(id) {} }
允许一个Action对应多个HTTP方法,或者允许除了Get、Put、Post、Delete方法之外的HTTP方法,需要使用AcceptVerbs注解属性,它以HTTP方法列表作为参数。
public class ProductsController : ApiController { [AcceptVerbs("GET", "HEAD")] public Product FindProduct(id) { } // WebDAV method [AcceptVerbs("MKCOL")] public void MakeCollection() { } }
通过Action名称路由
在默认的路由模版中,这个Web API使用HTTP方法去选择Action。然而,你也可以在URI中创建包含动作名的路由:routes.MapHttpRoute( name: "ActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } );
在这个路由模板中,{action}参数命名了控制器上的动作方法。采用这种风格的路由,需要使用注解属性来指明所允许的HTTP方法。例如,假设你的控制器已有如下方法:
public class ProductsController : ApiController { [HttpGet] public string Details(int id); }
在这种情况下,一个Get请求”api/Products/Details/1”将会映射到这个这个Details方法。这种风格的路由类似于Asp.Net MVC,而且可能与RPC式的API相接近。
你也可以通过使用ActionName注解属性来覆盖动作名。在以下例子中,有两个动作映射到“api/products/thumbnail/id”。一个支持GET,而另一个支持POST:
public class ProductsController : ApiController { [HttpGet] [ActionName("Thumbnail")] public HttpResponseMessage GetThumbnailImage(int id); [HttpPost] [ActionName("Thumbnail")] public void AddThumbnailImage(int id); }
Non-Actions
为了防止一个方法被作为一个动作所请求,可以使用NonAction注解属性。它对框架发出信号:这个方法不是一个动作,,即使它可能与路由规则匹配。// Not an action method. [NonAction] public string GetPrivateData() { ... }
小注:本文部分内容参考网络资料。
相关文章推荐
- LRU算法
- 进击的Android注入术《五》
- Android之高德地图定位及附近搜索
- CopyOnWriteArrayList源码原理分析
- multipartResolver
- 内核笔记1-Linux内核体系结构
- 什么是Zookeeper,Zookeeper的作用是什么,在Hadoop及hbase中具体作用是什么
- unity network组件的使用
- 在java代码中获取JVM参数
- MySQL安装Write configuration file 提示:configuration file template my.ini Error code-1
- stm32芯片的焊接
- apache通过.htaccess(rewrite)判断手机电脑跳转-手机用户重定向到手机版
- SaltStack 使用pillar安装配置管理zabbix
- 对Spring 数据访问的理解
- FMS/AMS服务本地录制在线视频碰到的问题解决方案
- 谁来讲讲Rxjava、rxandroid中的操作符的作用?
- appium for windows 的安装及环境搭配
- 安卓开发通用框架
- 用JS实现倒计时(日期字符串作为参数)
- 使用rsync 的 --delete参数删除目标目录比源目录多余的文件