我试图实现一个使用命令来改变系统状态的RESTful API(基于CQRS策略)。默认情况下,Web API的路由将难以与基于检查对象参数类型的操作匹配。为了解决这个问题,我一直在使用以下指南: Content Based Action Selection Using Five Levels of Media Type
按照说明操作后,它仍会导致模糊的匹配异常,这是由我的控制器中重载的Put方法引起的。
我的WebApiConfig如下:
public static class WebApiConfig
{
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 }
);
config.AddFiveLevelsOfMediaType();
}
}
我的控制器如下:
public class ProductsController : ApiController
{
public ProductDTO Get(int id)
{
var query = new ProductByIdQuery { Id = id };
ProductDTO product = _queryBus.Dispatch(query);
return product;
}
public void Put(ChangeProductCodeCommand command)
{
_commandBus.Dispatch(command);
}
public void Put(SetProductParentCommand command)
{
_commandBus.Dispatch(command);
}
public ProductsController(IQueryBus queryBus, ICommandBus commandBus)
{
_queryBus = queryBus;
_commandBus = commandBus;
}
IQueryBus _queryBus;
ICommandBus _commandBus;
}
在客户端,我发送的http标头是:
PUT /api/products HTTP/1.1
Content-Type: application/json;domain-model=ChangeProductCodeCommand
JSON:
{
ProductId: 758,
ProductCode: "TEST"
}
结果:
{
"Message": "An error has occurred.",
"ExceptionMessage": "Ambiguous Match",
"ExceptionType": "System.InvalidOperationException",
"StackTrace": " at ApiActionSelection.System.Web.Http.Controllers.ApiActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)\r\n at ApiActionSelection.System.Web.Http.Controllers.ApiActionSelector.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()"
}
为什么这不起作用的任何想法?
答案 0 :(得分:2)
有两个Put
方法只有参数类型不同,Web API会尝试根据传入参数的类型解析为正确的操作。
除非默认模型绑定器可以将传入的JSON映射到您已实现的复杂类型,并且该类型与您的Put
方法之一的参数类型匹配,否则Web API将使用{{1}进行响应您看到的异常,因为它无法确定要调用的方法。请注意,默认情况下,Web API不会在行动解决方案中使用您的"Ambiguous Match"
标题。
我建议您阅读Routing and Action Selection in ASP.NET Web API,以便了解路由在内部的运作方式。然后,您可能希望创建自己的Content-Type
实现,在其中检查IHttpActionSelector
,并将请求路由到您选择的操作。您可以找到示例实现here。
您还可以阅读有关模型绑定here的更多信息,以了解如何将传入的JSON解析为您的某个类型。