【问题标题】:WebApi 'Multiple actions were found that match the request' error after making call in angular以角度调用后,WebApi“发现与请求匹配的多个操作”错误
【发布时间】:2014-09-28 11:02:39
【问题描述】:

我觉得我的路由、控制器和调用都是正确的,但仍然无法弄清楚为什么我会收到“多项操作”错误。控制器本身调用服务总线,但我无法让它达到 GetJob 的断点。有什么想法吗?

路线:

public class WebApiInitializer : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {    
            RouteTable.Routes.MapHttpRoute(
                "webapimethodroutes",
                "api/msi/{controller}/{action}",
                defaults: new {}
                );
        }
    }

我的工作控制器:

public class SBJobController : ApiController, IJobsController
    {
        [HttpPost]
        public CreateJobResponse CreateJob(CreateJobRequest request)
        {
            return BusProxy.Call<CreateJobRequest, CreateJobResponse>(request);
        }

        [HttpPost]
        public GetJobResponse GetJob(GetJobRequest request)
        {
            return BusProxy.Call<GetJobRequest, GetJobResponse>(request);
        }
    }

我的角度服务调用:

function getJobs(pRequest) {
            var request = pRequest || {
                'Ids': [],
                'JobNumbers': [],
                'PageNumber': 1,
                'PageSize': 20,
            };
            return $http.post('/api/msi/SBJob/GetJob', request).error(function (data, status, headers, config) {
                //logError(data);
            });
        }

请求对象:

public class CreateJobRequest : RequestBase
    {
        public JobEntity Job { get; set; }
        public AddressEntity Address { set; get; }
    }

public class GetJobRequest: RequestBase, IPageable
    {
        public int PageNumber { set; get; }
        public int PageSize { set; get; }
        public List<Guid> Ids { set; get; }
        public List<string> JobNumbers { set; get; }
        public Guid ChildOfCustomer { set; get; }
        public Guid ChildOfContact { set; get; }
        public JobTypeEnum JobType { get; set; }
    }

我得到的确切错误:

{
    "Message": "An error has occurred.",
    "ExceptionMessage": "Multiple actions were found that match the request: \r\nCreateJob on type MSI.ServiceBus.ServiceControllers.SBJobController\r\nGetJob on type MSI.ServiceBus.ServiceControllers.SBJobController",
    "ExceptionType": "System.InvalidOperationException",
    "StackTrace": "   at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n   at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)\r\n   at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}

【问题讨论】:

  • GetJobRequestCreateJobRequest 对象是什么样的?我认为也许它们都符合您的请求对象
  • 为什么是GetJob HttpPost?
  • 不,它们是不同的。它必须是 Post,因为我们使用的服务总线不接受 GET 请求中的参数
  • 我们仍然缺少一些信息。只有一条路线和一项操作,您不会收到“多项操作...”错误。仅针对您想要执行的操作发布代码并不能帮助我们了解为什么它会针对您未发布的其他操作之一。
  • 我发布了两个操作对吗? GetJob 和 CreateJob。至于路线,是的,这是我唯一的路线。

标签: c# .net asp.net-web-api asp.net-web-api-routing


【解决方案1】:

web api 上的路由就是这样工作的

  • 为了找到控制器,Web API 将“Controller”添加到 {controller} 变量的值中。

  • 为查找操作,Web API 会查看 HTTP 方法,然后查找名称以该 HTTP 方法名称开头的操作。例如,对于 GET 请求,Web API 会查找以“Get...”开头的操作,例如“GetContact”或“GetAllContacts”。此约定仅适用于 GET、POST、PUT 和 DELETE 方法。您可以通过使用控制器上的属性来启用其他 HTTP 方法。我们稍后会看到一个例子。 路由模板中的其他占位符变量,例如 {id},映射到操作参数。

  • 您可以通过使用 HttpGet、HttpPut、HttpPost 或 HttpDelete 属性装饰操作方法来显式指定操作的 HTTP 方法,而不是使用 HTTP 方法的命名约定。

这就是匹配 2 个动作的原因,“默认情况下”不使用方法名称来匹配一个动作。你可能有这样的东西让它工作

public class WebApiInitializer : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {    
        RouteTable.Routes.MapHttpRoute(
            "CreateJob",
            "api/msi/SBJob/CreateJob",
            defaults: new {Controller = "SBKob", Action = "CreateJob"}
            );

        RouteTable.Routes.MapHttpRoute(
            "GetJob",
            "api/msi/SBJob/GetJob",
            defaults: new {Controller = "SBKob", Action = "GetJob"}
            );              
    }
}

【讨论】:

  • 两条路由的默认动作相同,对吗?默认值:新 {Controller = "SBKob", Action = "CreateJob"}
【解决方案2】:

当控制器真的是一个 Get 时,为什么不使用 RESTful 而不是两个 Post?

    public CreateJobResponse Post(CreateJobRequest request)
    {
        return BusProxy.Call<CreateJobRequest, CreateJobResponse>(request);
    }

    public GetJobResponse Get(int id)
    {
        return BusProxy.Call<GetJobRequest, GetJobResponse>(id);
    }

【讨论】:

    【解决方案3】:

    我有一个类似的问题,这不是路由定义问题 - 问题是调用的签名似乎相同,因此是多操作问题。错误消息的其余部分实际上非常有用,因为它专门标识了它无法解决的多个操作。就我而言,我的帖子返回了一个复杂类型:

    // POST: api/Transfer
    [ResponseType(typeof(Transfer))]
    public IHttpActionResult PostTransfer(Transfer transfer)
    

    而且它与同一文件中具有相似签名的方法混淆了:

    public TransferResponse doTransfer(Transfer transfer)
    

    路由匹配这个不以“Post”开头的例程,我有点震惊。我尝试改变路线。我尝试更改方法的名称,但没有任何区别。 所做的 工作是将调用签名更改为略有不同 - 在这种情况下,添加了一个垃圾 bool 值:

    public TransferResponse doTransfer(Transfer transfer, bool foo)
    

    然后路由很开心,又开始工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 2017-10-26
      • 2016-10-18
      • 2016-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多