重写RoutePrefix
[RoutePrefix("api/orders")] public class OrdersController : ApiController { [Route("")] [HttpGet] public async Task<IHttpActionResult> GetOrders() { return Ok(); } [Route("{customerId}")] [HttpGet] public async Task<IHttpActionResult> GetOrders(int customerId) { return Ok(); } [Route("~/api/customers/{customerId}/orders")] [HttpGet] public async Task<IHttpActionResult> GetOrders2(int customerId) { return Ok(); } }
上面的代码中获取某个用户的订单有两种路由方式,第一种显然是不好的,因为订单详情的路由有可能和这个一样,第二种方式就比较好了,通过url就可以清晰地知道请求的资源。
路由约束
ASP.NET Web API内置约束有下面这些
{x:alpha} 约束大小写英文字母 {x:bool} {x:datetime} {x:decimal} {x:double} {x:float} {x:guid} {x:int} {x:length(6)} {x:length(1,20)} 约束长度范围 {x:long} {x:maxlength(10)} {x:min(10)} {x:range(10,50)} {x:regex(正则表达式)}
可以设置多个约束
[Route("api/orders/{id:int:min(1)}")]
还可以自定义约束,实现IHttpRouteConstraint接口
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; } }
注册自定义约束
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}")]
路由顺序
Route特性设置的路由优先顺序是根据惯例和RouteOrder属性来确定的
惯例是:
- 静态片段变量
- 带约束的片段变量
- 不带约束的片段变量
- 带约束的通配符片段变量
- 不带约束的通配符片段变量
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