找到了与Web Api中的请求匹配的多个操作

问题描述 投票:219回答:17

当我尝试使用2个“Get”方法时,我不断收到此错误

找到了与请求匹配的多个操作:webapi

我一直在寻找关于堆栈的其他类似问题,但我不明白。

我有2个不同的名称,并使用“HttpGet”属性

[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}
c# .net asp.net-web-api asp.net-web-api-routing
17个回答
451
投票

您的路线图可能是这样的:

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });

但是为了使用相同的http方法进行多个操作,您需要通过路由为webapi提供更多信息,如下所示:

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional });

请注意,routeTemplate现在包含一个操作。这里有更多信息:http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

更新:

好吧,既然我认为我明白你的意思,那么另外就是:

也许你不需要动作url参数,并且应该以另一种方式描述你所追求的内容。既然你说方法是从同一个实体返回数据,那么就让参数为你做描述。

例如,您的两种方法可以变成:

public HttpResponseMessage Get()
{
    return null;
}

public HttpResponseMessage Get(MyVm vm)
{
    return null;
}

你在MyVm对象中传递了什么样的数据?如果你能够通过URI传递变量,我建议去那条路线。否则,您需要在请求正文中发送对象,并且在执行GET时不是非常HTTP(它可以工作,只需使用MyVm前面的[FromBody])。

希望这说明您可以在单个控制器中使用多个GET方法,而无需使用操作名称甚至[HttpGet]属性。


2
投票

请检查您有两种方法,它们具有不同的名称和相同的参数。

如果是这样,请删除任何方法并尝试。


2
投票

在尝试使用额外操作扩充我的WebAPI控制器时,我偶然发现了这个问题。

假设你有

public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

[HttpGet]
public void ReSeed()
{
    // Your custom action here
}

现在有两种方法满足/ api / controller的请求,它触发了TS描述的问题。

我不想在我的其他操作中添加“虚拟”参数,因此我查看了默认操作并提出了:

[ActionName("builtin")]
public IEnumerable<string> Get()
{
    return this.Repository.GetAll();
}

对于与“双重”路径绑定相结合的第一种方法:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { action = "builtin", id = RouteParameter.Optional },
    constraints: new { id = @"\d+" });

config.Routes.MapHttpRoute(
    name: "CustomActionApi",
    routeTemplate: "api/{controller}/{action}");

请注意,即使第一个路径模板中没有“action”参数,显然您仍然可以配置一个默认操作,允许我们将“正常”WebAPI调用的路由与对额外操作的调用分开。


2
投票

这是每个知道一切都正确并且检查了50次的人的答案.....

确保你不要反复看RouteConfig.cs

您要编辑的文件名为WebApiConfig.cs

此外,它应该看起来像这样:

using System.Web.Http;

namespace My.Epic.Website
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
          config.MapHttpAttributeRoutes();

          // api/Country/WithStates
          config.Routes.MapHttpRoute(
            name: "ControllerAndActionOnly",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { },
            constraints: new { action = @"^[a-zA-Z]+([\s][a-zA-Z]+)*$" });

          config.Routes.MapHttpRoute(
            name: "DefaultActionApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
          );
    }
    }
}

我本可以节省约3个小时。


1
投票

在我的案例中,一切都是正确的

1)Web配置正确配置2)路由前缀和路由属性正确

我还是得到了错误。在我的案例“路由”属性(通过按F12)指向System.Web.MVc但不是System.Web.Http导致该问题。


0
投票

我知道这是一个老问题,但有时,当您使用AngularJS等服务资源连接到WebAPI时,请确保使用正确的路由,否则会发生此错误。


0
投票

确保不使用[HttpPost / Put / Get / Delete]属性为默认的GET | PUT | POST | DELETE操作修饰Controller方法。我已将此属性添加到我的vanilla Post控制器操作中,它导致了404。

希望这可以帮助某人,因为它可能非常令人沮丧,并使进展停止。


0
投票

例如=> TestController

        [HttpGet]
        public string TestMethod(int arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod2(string arg0)
        {
            return "";
        }

        [HttpGet]
        public string TestMethod3(int arg0,string arg1)
        {
            return "";
        }

如果只能更改WebApiConfig.cs文件。

 config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/",
                defaults: null
            );

而已 :)

结果:enter image description here


0
投票

你试过像:

[HttpGet("Summary")]
public HttpResponseMessage Summary(MyVm vm)
{
    return null;
}

[HttpGet("FullDetails")]
public HttpResponseMessage FullDetails()
{
    return null;
}

0
投票

您可以将[Route("api/[controller]/[action]")]添加到控制器类。

[Route("api/[controller]/[action]")]
[ApiController]
public class MySuperController : ControllerBase
{
 ...
}

60
投票

从Web API 2开始更新。

在WebApiConfig.cs文件中使用此API配置:

public static void Register(HttpConfiguration config)
{
    //// Web API routes
    config.MapHttpAttributeRoutes(); //Don't miss this

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

您可以像这样路由我们的控制器:

[Route("api/ControllerName/Summary")]
[HttpGet]
public HttpResponseMessage Summary(MyVm vm)
{
    rturn null;
}

[Route("api/ControllerName/FullDetails")]
[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}

其中ControllerName是控制器的名称(没有“控制器”)。这将允许您使用上面详述的路线获取每个操作。

进一步阅读:http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2


15
投票

在Web API中(默认情况下),基于HTTP方法和路由值的组合选择方法。

MyVm看起来像一个复杂的对象,由格式化程序从正文中读取,因此您在路径数据方面有两个相同的方法(因为它们都没有路由中的任何参数) - 这使得调度程序(IHttpActionSelector)无法匹配适当的。

您需要通过查询字符串或路由参数来区分它们以解决歧义。


13
投票

经过大量搜索网络并尝试找到最适合路由地图的表格,如果找到了以下内容

config.Routes.MapHttpRoute("DefaultApiWithId", "Api/{controller}/{id}", new { id =RouteParameter.Optional }, new { id = @"\d+" });
config.Routes.MapHttpRoute("DefaultApiWithAction", "Api/{controller}/{action}");

这些映射适用于动作名称映射和基本http约定(GET,POST,PUT,DELETE)


5
投票

您的web方法可能会被解析为相同的URL。看看以下链接: -

http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

因此,您可能需要将您的方法名称添加到路由表中。


5
投票

不使用操作,选项将是:

  1. 将其中一个方法移动到另一个控制器,以便它们不会发生冲突。
  2. 只使用一个接受param的方法,如果是null,则从代码中调用另一个方法。

4
投票

这个解决方案对我有用。

请将Route2放在WebApiConfig中。还要在每个方法之前添加HttpGet和HttpPost,并在URL中包含控制器名称和方法名称。

WebApiConfig =>

config.Routes.MapHttpRoute(
           name: "MapByAction",
           routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional });
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional });

控制器=>

public class ValuesController : ApiController
{

    [HttpPost]
    public string GetCustomer([FromBody] RequestModel req)
    {
        return "Customer";
    }

    [HttpPost]
    public string GetCustomerList([FromBody] RequestModel req)
    {
        return "Customer List";
    }
}

网址=>

http://localhost:7050/api/Values/GetCustomer

http://localhost:7050/api/Values/GetCustomerList

3
投票

我发现,当我有两个Get方法,一个无参数和一个复杂类型作为参数,我得到了相同的错误。我通过添加一个名为Id的int类型的伪参数作为我的第一个参数,然后是我的复杂类型参数来解决这个问题。然后我将复杂类型参数添加到路由模板中。以下对我有用。

首先得到:

public IEnumerable<SearchItem> Get()
{
...
}

第二个得到:

public IEnumerable<SearchItem> Get(int id, [FromUri] List<string> layers)
{
...
}

WebApiConfig:

config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}/{layers}",
    defaults: new { id = RouteParameter.Optional, layers RouteParameter.Optional }
);

3
投票

由于使用MVC控制器而不是Web API控制器,因此可能。检查Web API控制器中的命名空间,它应如下所示

using System.Net;
using System.Net.Http;
using System.Web.Http;

如果命名空间如下,则在web api控制器方法调用中给出上述错误

using System.Web;
using System.Web.Mvc;
© www.soinside.com 2019 - 2024. All rights reserved.