重写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
