找到了与请求匹配的多个操作:WebAPI 2
问题描述:
我读过几个SO posts,它们都没有覆盖我的场景,因此我要在此处发帖。找到了与请求匹配的多个操作:WebAPI 2
给出下面的航线配置报名:
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正确选择路线,但不幸的是它不是。
所以我的问题是“有没有办法使这段代码正常工作,并保持在同一控制器?
谢谢 斯蒂芬
答
您可以使用attribute routing这个。
定义为在路径字符串中的路由属性ontop的方法,因为这
[Route("api/controller/Post1")]
[HttpPost]
public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request)
{
}
[Route("api/controller/Post2")]
[HttpPost]
public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request)
{
}
答
添加路由属性装饰你的Web API函数,这将assit选择选择路线:
[Route("Post1")]
public GetDocumentsResponse Post([FromBody]GetDocumentsRequest request)
{
}
[Route("Post2")]
public FinishDocumentsResponse Post([FromBody] FinishDocumentsRequest request)
{
}
我还建议将HTTP方法装饰等如[HttpPost]
或[HttpGet]
答
该请求路由管道是不够的智能,以确定该请求的主体中的参数类型相匹配(又名超载)。 (编译器是足够聪明,这就是为什么这个编译和你有运行时问题。)
你有几个不同的选项。
- 您可以在两个帖子上添加
[Route(<ActionName>)]
属性。 - 使两个控制器,一个用于
GetDocuments
,一个用于FinishDocuments
- 使一个
Post
方法是不明确的。 (我会避免)
如果您选择选项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,愿上帝怜悯你的灵魂你将有一个坏的时间来维护它。
您是否打算为两者进行相同的URL调用? – Nkosi