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

cho*_*bo2 229 .net c# asp.net-web-api asp.net-web-api-routing

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

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

我一直在寻找关于堆栈的其他类似问题,但我没有得到它.

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

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

[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}
Run Code Online (Sandbox Code Playgroud)

Jed*_*Jed 461

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

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

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

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

请注意,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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 一个人是否优势胜过另一个人取决于你的项目.如果您正在构建RESTful api,那么您将需要使用HTTP约定(GET,POST,PUT,DELETE ...).在这种情况下,第一个路由代码块是要走的路,但是你需要为通过api公开的每个实体使用不同的控制器.根据您的方法名称,我猜这不是这种情况所以使用更具描述性的路由.当您的路由包含操作时,您需要在每个方法上显式放置http属性. (3认同)

Mar*_*son 64

从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 }
    );
}
Run Code Online (Sandbox Code Playgroud)

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

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

[Route("api/ControllerName/FullDetails")]
[HttpGet]
public HttpResponseMessage FullDetails()
{
    return null;
}
Run Code Online (Sandbox Code Playgroud)

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

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


Fil*_*p W 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}");
Run Code Online (Sandbox Code Playgroud)

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

  • 对我来说,这是有效的,但只有在改变路线配置中的路线顺序后才能首先出现有动作的路线 (8认同)

Car*_*omp 7

这是所有知道一切正确并检查了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 }
          );
    }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 谢谢,你节省了我大约 3 个小时 (3认同)

Max*_*Max 5

您的网络方法可能被解析为相同的URL。看看下面的链接:

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

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


Joa*_*rks 5

不使用操作,选项将是:

  1. 将其中一个方法移动到另一个控制器,以便它们不会发生冲突.

  2. 只使用一个接受param的方法,如果是null,则从代码中调用另一个方法.