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

时间:2017-05-25 18:19:30

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

我已经阅读了一些SO posts并且没有一个完全覆盖我的情景,所以我将在这里发帖。

给出以下路由配置注册:

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services

    // Web API routes
    config.MapHttpAttributeRoutes();

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

以及从ApiController继承的控制器中的这些控制器操作:

public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request)
{

}

public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request)
{

}


public class GetDocumentsRequest
{
    public string CorrelationId { get; set; }
    public int Id { get; set; }
    public string ObjectId { get; set; }
    public string BusinessArea { get; set; }
    public string UserId { get; set; }
    public string SystemName { get; set; }
    public string SystemToken { get; set; }
    public Letter LetterDetails { get; set; }
    public List<KeyValuePair<string, string>> KeyValue { get; set; }
}

public class FinishDocumentsRequest
{
    public string CorrelationId { get; set; }
    public string[] Documents { get; set; }
}

我认为这样做就足以消除IHttpActionSelector正确选择路线的歧义,但遗憾的是它不是。

所以我的问题是&#34;有没有办法让这段代码正常工作,并将它保存在同一个控制器中?&#34;

谢谢你, 斯蒂芬

3 个答案:

答案 0 :(得分:1)

您可以使用attribute routing

将路径定义为方法中的Route属性的字符串,如此

[Route("api/controller/Post1")]
[HttpPost]
public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request)
{

}
[Route("api/controller/Post2")]
[HttpPost]
public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request)
{

}

答案 1 :(得分:1)

请求路由管道不够智能,无法确定请求的主体是否与参数类型(也称为重载)匹配。 (编译器 足够智能,这就是为什么编译并且你有运行时问题。)

您有几种不同的选择。

  1. 您可以在两个帖子上添加[Route(<ActionName>)]属性。
  2. 制作两个控制器,一个用于GetDocuments,另一个用于FinishDocuments
  3. 制作一个含糊不清的Post方法。 (我避免这样做)
  4. 如果您选择选项1,则您的API uri必须是.../api/MyController/MyActionName而不是.../api/MyController/。建议您在方法中添加[HttpGet][HttpPost]属性。

    样品:

    public class DocumentController : ApiController 
    {
        // POST /api/Document/GetDocuments
        [HttpPost]
        [Route("GetDocuments")]
        public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request) { ... }
    
        // POST /api/Document/FinishDocuments
        [HttpPost]
        [Route("FinishDocuments")]
        public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request){ ...}
    }
    

    如果选择选项2,则必须维护一个额外的代码文件。

    public class GetDocumentsController : ApiController
    {
        // POST /api/GetDocuments
        [HttpPost]
        public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request) { ... }
    }
    
    public class FinishDocumentsController : ApiController 
    {
        // POST /api/FinishDocuments/
        [HttpPost]
        public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request){ ...}
    }
    

    如果你选择选项3,愿上帝怜悯你的灵魂你将不会有时间维持它。

答案 2 :(得分:0)

将Route属性修饰添加到您的web api函数中,这将有助于选择器选择路径:

[Route("Post1")]
public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request)
{

}

[Route("Post2")]
public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request)
{

}

我还建议添加http方法修饰,例如[HttpPost][HttpGet]