作者 GitiJun 2018.01.09 16:54:34 写了58篇文章,回复33人, Webapi 路由规则备忘 阅读:2235· 评论:0· 喜欢:1 ## 路由优先级 Route特性设置的路由优先顺序是根据惯例和RouteOrder属性来确定的。 惯例是: 1、静态片段变量 2、带约束的片段变量 3、不带约束的片段变量 4、带约束的通配符片段变量 5、不带约束的通配符片段变量 RouteOrder属性的默认值是0,属性值越小,排在越前面。 当框架会尝试匹配与路由的 URI 时,它会评估按特定顺序的路由。 若要指定的顺序,将设置RouteOrder路由属性上的属性。 较低的值都将先评估。 默认顺序值为零。 下面是如何确定总排序: 比较RouteOrder路由特性属性。 查看在路由模板中每个 URI 段。 对于每个段,排序,如下所示: 文本段。 具有约束的路由参数。 不受限制的路由参数。 具有约束的通配符参数段。 通配符参数不受限制的段。 对于一次,路由排序使用的不区分大小写的序号字符串比较 (OrdinalIgnoreCase) 的路由模板。 ## 路由顺序 通过设定特性[Route("xxx",RouteOrder=n)]可以指定路由的查找顺序. ``` [Route("pending", RouteOrder = 1)] public HttpResponseMessage GetPending() { ... } ``` 通过顺序来控制,还不如设定更好的路由来的实际,而且不至于让开发人员觉得混乱。 ## 路由名称 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; } ## 路由规则配置 public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Department", action = "Index", id = UrlParameter.Optional } ); } } public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API 路由 config.MapHttpAttributeRoutes(); //1.默认路由 config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); //2.自定义路由一:匹配到action config.Routes.MapHttpRoute( name: "ActionApi", routeTemplate: "actionapi/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); //3.自定义路由二 config.Routes.MapHttpRoute( name: "TestApi", routeTemplate: "testapi/{controller}/{ordertype}/{id}", defaults: new { ordertype="aa", id = RouteParameter.Optional } ); } } ## 方法特性标记属性 因为routeTemplate中有了{controller} 所以针对api的请求可以自动映射到指定的controller类 针对api的请求可以自动映射到指定的controller类 系统根据请求的方式来判断,控制器方法中以动词开头+方法名称,如 GET,POST,PUT,DELETE 等。 使用的特性包括:[HttpDelete],[HttpPost],[HttpHead],[HttpOptions],[HttpPatch],[HttpGet],[HttpPut] 通过AcceptVerbs特性,我们还可以指定非标准方法以及多个方法,如 [AcceptVerbs("MKCOL","GET","POST")] 通过特性ActionName来实现 [ActionName("TestActionName")] 可以使用方法特性区分,如 [AcceptVerbs("GET")]、[AcceptVerbs("GET", "HEAD")] 如果public的方法不需要被路由访问,则可标记忽略掉。如 [NonAction] 在控制器上指定 [RoutePrefix("api")] [RoutePrefix("api/{customerId}")] public class OrdersController : ApiController 在控制器方法上指定 [Route("customers/{customerId}/orders")] [Route("~/myapi/customers/{customerId:int}/orders")] [HttpGet] public IEnumerable FindOrdersByCustomer(int customerId) 可以通过"{参数变量名称:约束}"来约束路由中的参数变量。 [Route("users/{id:int}"] public User GetUserById(int id) { ... } [Route("users/{name}"] public User GetUserByName(string name) { ... } 以上,如果片段变量id为int类型,就路由到第一个Action,如果不是,路由到第二个Action。 ## 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/{id:int:min(1)}")] 如果一个路由参数变量是可选的,同时必须给该参数一个默认值。 [Route("api/{id:int?}")] public IEnumerable Get(int id = 8){} 在约束后面加?,表示可选,在方法参数中给id设置默认值。 实现IHttpRouteConstraint接口,可自定义约束规则。实现一个不能为0的约束。 public class NonZeroConstraint : IHttpRouteConstraint { public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary 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}")] ## 其他样例 [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 public class OrderController : ApiController { [HttpGet] public IHttpActionResult GetAll() { return Ok("Success"); } [HttpGet] public IHttpActionResult GetById(int id) { return Ok("Success" + id ); } [HttpPost] public HttpResponseMessage PostData(int id) { return Request.CreateResponse(); } [HttpPost] public HttpResponseMessage SavaData(ORDER order) { return Request.CreateResponse(); } [HttpPut] public IHttpActionResult Put(int id) { return Ok(); } [HttpDelete] public IHttpActionResult DeleteById(int id) { return Ok(); } } 匹配action的结果 url http方法 参数 结果 http://localhost:21528/api/Order get none 匹配GetAll方法 http://localhost:21528/api/Order get id 匹配GetById方法 http://localhost:21528/api/Order post order 匹配SavaData方法 http://localhost:21528/api/Order put id 匹配Put方法 http://localhost:21528/api/Order delete id 匹配DeleteById方法 WebApi还提供了一个action同时支持多个http方法的请求,使用AcceptVerbs特性去标记。但博主觉得实际使用并不多,有兴趣的可以了解下。 [AcceptVerbs("GET", "POST")] public IHttpActionResult GetById(int id) { return Ok("Success" + id ); } [Route("api/order/{id:int=3}/ordertype")] [HttpGet] public IHttpActionResult GetById(int id) { return Ok("Success" + id ); } [Route("ordertype/{id}/order")] [HttpGet] public IHttpActionResult GetById(int id) { return Ok("Success" + id ); } [Route("Order/SaveData")] [HttpPost] public HttpResponseMessage SavaData(ORDER order) { return Request.CreateResponse(); } 赞 | 1 赏 标签:none