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("~api/otherbooks")]
有时候需要几个路由片段结合起作用,如日期 /api/books/date/2013/06/17
这时候就需要使用字符* ,[Route("date/{*date:datetime:regex(\\d{4}/\\d{2}/\\d{2})}")],不过这种参数只能用作路由的最后一个参数
路由约束
路由约束让我们可以限制模板参数的匹配方式。一般的语法是 "{参数:约束类型}":
[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 != ;
}
}
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 = ) { ... }
[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 = )]
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
WebApi深入学习--特性路由的更多相关文章
- C# WebApi使用AttributeRoutes特性路由
1.在创建WebApi中默认的路由规则,只能满足一般简单的RESTful风格,如 api/Products/{id}. 但是在实际运用中很难严格满足RESTful要求的WebApi.因此需要使用高版本 ...
- WebApi深入学习--概述+路由查找
如何创建Controller这里就不说了,只写一些可能是高阶知识的内容 关于WebApi的官方介绍及示例 http://www.asp.net/web-api/ 1.跨域 Asp.NET有专门的跨域扩 ...
- [Web API] Web API 2 深入系列(5) 特性路由
目录 1. 特性路由注册 2. 路由解析 - 生成DataTokens - 选择HttpController - 选择Action 特性路由的目的在于更好的提供restful架构的接口,最近好忙(懒) ...
- ASP.NET Web API 2 中的特性路由
ASP.NET MVC 5.1 开始已经支持基于特性的路由(http://attributerouting.net),ASP.NET WEB API 2 同时也支持了这一特性. 启用特性路 由只需要在 ...
- asp.net mvc 特性路由(MapMvcAttributeRoutes)的应用
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u012835032/article/details/51160824asp.net mvc 特性路由 ...
- Mvc-WebAPI特性路由(自定义路由)Demo
Demo由VS2017编写. 1.先建一个WebApi项目 2.WebApiConfig.cs需要注册特性路由,config.MapHttpAttributeRoutes(); 3.项目默认有2个Co ...
- webapi的学习资料
猿教程_-webapi教程-WebAPI教程 猿教程_-webapi教程-Web API概述 猿教程_-webapi教程-新建Web Api项目 猿教程_-webapi教程-测试Web API 猿教程 ...
- ASP.NET WEB API必知必会:特性路由
一.什么是特性路由? 特性路由是指将RouteAttribute或自定义继承自RouteAttribute的特性类标记在控制器或ACTION上,同时指定路由Url字符串,从而实现路由映射,相比之前的通 ...
- MVC特性路由的提供机制
回顾:传统路由是如何提供的? 我们知道最终匹配的路由数据是保存在RouteData中的,而RouteData通常又是封装在RequestContext中的,他们是在哪里被创建的呢?没错,回到了UrlR ...
随机推荐
- ActionSupport与action区别
action是接口,只有一个execute方法需要实现.ActionSupport是action接口的一个实现类.这个类除了实现action接口还实现了Validateable(用于验证)等接口,开发 ...
- JAVA实现的微信扫描二维码支付
吐槽一下 支付项目采用springMvc+Dubbo架构实现,只对外提供接口. 话说,为什么微信支付比支付宝来的晚了那么一点,一句话,那一阵挺忙的,然后就没有时间整理,最近做完支付宝支付,顺便也把微信 ...
- Statement和PreparedStatement的区别; 什么是SQL注入,怎么防止SQL注入?
问题一:Statement和PreparedStatement的区别 先来说说,什么是java中的Statement:Statement是java执行数据库操作的一个重要方法,用于在已经建立数据库连接 ...
- 【Effective Java】7、优先考虑泛型方法
package cn.xf.cp.ch02.item27; import java.util.HashSet; import java.util.Set; public class Union { / ...
- PHP 导出Excel 文档
下面是总结的几个使用方法 include 'PHPExcel.php'; include 'PHPExcel/Writer/Excel2007.php'; //或者include 'PHPExcel/ ...
- jinfo命令的使用
jinfo命令 该命令可以打印出java进程的配置信息:包括jvm参数,系统属性等用法: jinfo [ option ] pid jinfo [ option ] executable core j ...
- tomcat 5.5、6、7各版本的web-app标准
刚把上周说的公司内各工程的web.xml给统一了,顺便看了下每个tomcat版本对应的标准servlet版本,如下: The XSD version is preferred since JSP 2. ...
- Hibernate(五)__hql语句
hql(hibernate query language)功能强大. 首先回忆下之前我们接触的对数据对象的操作: ①删除session.delete(对象) ②保存session.save(对象) ...
- 解决MVC4发布在IIS7后,路径无法访问.apk文件的解决方法
随着智能手机的普及,越来越多的人使用手机上网,很多网站也应手机上网的需要推出了网站客户端,.apk文件就是安卓(Android)的应用程序后缀名,默认情况下,使用IIS作为Web服务器的无法下载此文件 ...
- 【经验之谈】前端面试知识点总结(CSS相关)——附答案
目录 二.CSS部分 1.解释一下CSS的盒子模型? 2.请你说说CSS选择器的类型有哪些,并举几个例子说明其用法? 3.请你说说CSS有什么特殊性?(优先级.计算特殊值) 4.要动态改变层中内容可以 ...