Web Api通过Route、RoutePrefix等特性设置路由
[Route("customers/{customerId}/orders")] [HttpGet] public IEnumerable<Order> FindOrdersByCustomer(int customerId) { return Database.GetOrdersByCustomerId(customerId); }
比如我们希望是这样的格式:http://localhost/api/customers/1/orders
[RoutePrefix("api")] public class OrdersController : ApiController { [Route("customers/{customerId}/orders")] [HttpGet] public IEnumerable<Order> FindOrdersByCustomer(int customerId) { return Database.GetOrdersByCustomerId(customerId); } }
在Route特性中使用~来重写Action的前缀规则
[RoutePrefix("api")] public class OrdersController : ApiController { [Route("~/myapi/customers/{customerId:int}/orders")] [HttpGet] public IEnumerable<Order> FindOrdersByCustomer(int customerId) { return Database.GetOrdersByCustomerId(customerId); } }
RoutePrefix特性定义的前缀还可以带参数变量:
[RoutePrefix("api/{customerId}")] public class OrdersController : ApiController
路由约束
可以通过"{参数变量名称:约束}"来约束路由中的参数变量。
[Route("users/{id:int}"] public User GetUserById(int id) { ... } [Route("users/{name}"] public User GetUserByName(string name) { ... }
以上,如果片段变量id为int类型,就路由到第一个Action,如果不是,路由到第二个Action。
ASP.NET Web API内置约束包括:
alpha,必须为大小写字母(a-z,A-Z),如:{x:alpha}; bool,必须为布尔值,如:{x:bool} datetime,必须为DateTime(时间和日期)类型,如:{x:datetime} decimal,必须为decimal类型,如:{x:decimal} double,必须为64bit浮点数,如:{x:double} float,必须为32bit浮点数,如:{x:float} guid,必须为GUID,如:{x:guid} int,必须为32bit整数,如:{x:int} length,字符串长度必须为指定值或者在指定范围内,如:{x:length(6)} {x:length(1,20)} long,必须为64bit整数,如:{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:(^\d{3}-\d{3}-\d{4}$)}
可以为一个参数变量同时设置多个约束:
[Route("api/{id:int:min(1)}")]
实现IHttpRouteConstraint接口,可自定义约束规则。实现一个不能为0的约束。
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; } string valueString = Convert.ToString(value, CultureInfo.InvariantCulture); if (Int64.TryParse(valueString, NumberStyles.Integer, CultureInfo.InvariantCulture, out longValue)) { return longValue != 0; } } return false; } }
在App_Start文件夹中的WebApiConfig中注册自定义约束。
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}")]
可选参数及其默认值
第— 种方式:将对应的参数定义成可缺省参数 ,那么它将直接使用可缺省参数的默认值作为路由变量的默认值。
采用这种定义方式的可缺省 由变量名需要添加 “?” 后缀 ,在方法接的地方设置默认值。
另一种方式就是将默认值直接定义在路由模板中,语法
1:可缺省路由变量后加“=”,即默认为空
给路由设置名称
public class BooksController : ApiController { [Route("api/books/{id}", Name="GetBookById")] public BookDto GetBook(int id) { // Implementation not shown... } [Route("api/books")] public HttpResponseMessage Post(Book book) { // Validate and add book to database (not shown) var response = Request.CreateResponse(HttpStatusCode.Created); // Generate a link to the new book and set the Location header in the response. string uri = Url.Link("GetBookById", new { id = book.BookId }); response.Headers.Location = new Uri(uri); return response; } }
[Route("menu", Name = "mainmenu")] public ActionResult MainMenu() { ... } //你可以使用 Url.RouteUrl 来生成相应的 URL: <a href="@Url.RouteUrl("mainmenu")">Main menu</a>
路由优先顺序
Route特性设置的路由优先顺序是根据惯例和RouteOrder属性来确定的。
惯例是:
1、静态片段变量
2、带约束的片段变量
3、不带约束的片段变量
4、带约束的通配符片段变量
5、不带约束的通配符片段变量
RouteOrder属性的默认值是0,属性值越小,排在越前面。
[RoutePrefix("orders")] public class OrdersController : ApiController { [Route("{id:int}")] // constrained parameter public HttpResponseMessage Get(int id) { ... } [Route("details")] // literal public HttpResponseMessage GetDetails() { ... } [Route("pending", RouteOrder = 1)] public HttpResponseMessage GetPending() { ... } [Route("{customerName}")] // unconstrained parameter public HttpResponseMessage GetByCustomer(string customerName) { ... } [Route("{*date:datetime}")] // wildcard public HttpResponseMessage Get(DateTime date) { ... } }
以上,路由的优先顺序是:
orders/details 静态片段变量,RouteOrder属性值为0
orders/{id} 带约束的片段变量,RouteOrder属性值为0
orders/{customerName} 不带约束的片段变量,RouteOrder属性值为0
orders/{*date} 带约束的通配符片段变量,RouteOrder属性值为0
orders/pending RouteOrder属性值为1
参考:http://www.th7.cn/Program/net/201410/302571.shtml