asp.net - Web API 路由 - api/{controller}/{action}/{id} "dysfunctions"api/{controller}/{id}

标签 asp.net routes controller asp.net-web-api action

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

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

我希望能够针对特定功能,因此我创建了另一条路线:

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

所以,在我的 Controller 中,我有:

    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 会给我错误

Multiple actions were found that match the request: ...

我明白为什么 - 路由只是定义哪些 URL 是有效的,但是当涉及到函数匹配时,Get(int id)ByCategoryId(int id) code> 匹配 api/{controller}/{id},这就是混淆框架的原因。

我需要做什么才能让默认 API 路由再次工作,并保留带有 {action} 的路由?我想创建一个名为 RecordByCategoryIdController 的不同 Controller 来匹配默认 API 路由,为此我将请求 .../api/recordbycategoryid/5。然而,我发现这是一个“肮脏”(因此不令人满意)的解决方案。我已经寻找过这方面的答案,但没有任何关于使用带有 {action} 的路线的教程甚至提到这个问题。

最佳答案

路由引擎使用与您添加规则相同的顺序。一旦它获得第一个匹配的规则,它将停止检查其他规则并以此来搜索 Controller 和操作。

所以,你应该:

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

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

  3. 将命名操作添加到“DefaultApi”中,以告诉路由引擎要输入哪个操作。否则,一旦 Controller 中有多个操作,引擎将不知道要使用哪一个,并抛出“发现多个与请求匹配的操作:...”。然后,为了使其与您的 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 }
);

还有你的 Controller :

[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" };
}

关于asp.net - Web API 路由 - api/{controller}/{action}/{id} "dysfunctions"api/{controller}/{id},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13596391/

相关文章:

c# - "too much"什么时候异步等待?所有方法都应该返回 Task 吗?

c# - 当 DropDownList Filter 的值不是 ALL 时,如何删除 GridView 中的整个第一列?

javascript - ASP.NET 独立的 javascript 目录结构

grails - 单选按钮,真或假

asp.net - 缺少ASP.NET 5模板

ruby-on-rails - 将特定格式的请求路由到 Rails 中的不同 Controller

ruby - 我可以从范围访问一个参数吗?

node.js - 如何将代码与请求处理程序分离(node.js 和express.js)

asp.net-mvc - 如何从 Controller 为存储库的构造函数指定参数?

Magento 表单对自定义 Controller 的发布操作不起作用 - 路由错误,但为什么呢?