Web API路由 – api / {controller} / {action} / {id}“function障碍”api / {controller} / {id}

我有Global.asax中的默认路由:

RouteTable.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = System.Web.Http.RouteParameter.Optional } ); 

我想能够定位一个特定的function,所以我创build了另一条路线:

 RouteTable.Routes.MapHttpRoute( name: "WithActionApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = System.Web.Http.RouteParameter.Optional } ); 

所以,在我的控制器中,我有:

  public string Get(int id) { return "object of id id"; } [HttpGet] public IEnumerable<string> ByCategoryId(int id) { return new string[] { "byCategory1", "byCategory2" }; } 

调用.../api/records/bycategoryid/5会给我想要的。 但是,调用.../api/records/1会给我错误

发现多个匹配请求的操作:…

我明白这是为什么 – 路由只是定义什么url是有效的,但是当涉及到函数匹配时, Get(int id)ByCategoryId(int id)匹配api/{controller}/{id} ,这是什么混淆该框架。

我需要做些什么才能让默认的APIpath再次运行,并保留{action} ? 我想创build一个名为RecordByCategoryIdController的不同的控制器来匹配默认的API路由,为此我会请求.../api/recordbycategoryid/5 。 但是,我发现这是一个“肮脏”(因此不令人满意)的解决scheme。 我已经find了这方面的答案,并没有任何教程在使用{action}的路线甚至提到这个问题。

路由引擎使用与添加规则相同的顺序。 一旦获得第一个匹配的规则,它将停止检查其他规则,并采取这个search控制器和行动。

所以,你应该:

  1. 把你的特定规则放在你的一般规则之前(比如默认),这意味着使用RouteTable.Routes.MapHttpRoute先映射“WithActionApi”,然后映射“DefaultApi”。

  2. 删除“WithActionApi”规则的defaults: new { id = System.Web.Http.RouteParameter.Optional }参数,因为一旦id是可选的,像“/ api / {part1} / {part2}”这样的url永远不会进入“ DefaultApi”。

  3. 将一个已命名的动作添加到“DefaultApi”中,以告知路由引擎要input哪个动作。 否则,一旦在控制器中有多个操作,引擎将不知道要使用哪个操作,并抛出“find与请求匹配的多个操作:…”。 然后为了使它匹配你的Get方法,使用一个ActionNameAttribute 。

所以你的路线应该是这样的:

 // Map this rule first RouteTable.Routes.MapRoute( "WithActionApi", "api/{controller}/{action}/{id}" ); RouteTable.Routes.MapRoute( "DefaultApi", "api/{controller}/{id}", new { action="DefaultAction", id = System.Web.Http.RouteParameter.Optional } ); 

和你的控制器:

 [ActionName("DefaultAction")] //Map Action and you can name your method with any text public string Get(int id) { return "object of id id"; } [HttpGet] public IEnumerable<string> ByCategoryId(int id) { return new string[] { "byCategory1", "byCategory2" }; } 

你可以通过属性路由来解决你的问题

调节器

 [Route("api/category/{categoryId}")] public IEnumerable<Order> GetCategoryId(int categoryId) { ... } 

在jQuery中的URI

 api/category/1 

路由configuration

 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. } } } 

而您的默认路由作为默认的基于约定的路由

调节器

 public string Get(int id) { return "object of id id"; } 

在JQuery中的URI

 /api/records/1 

路由configuration

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Attribute routing. config.MapHttpAttributeRoutes(); // Convention-based routing. config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } 

评论文章获取更多信息属性路由和基于发现的路由在这里和这个