【问题标题】:Content-based action selection Web API using FiveLevelsOfMediaType (5LMT) not working使用 FiveLevelsOfMediaType (5LMT) 的基于内容的操作选择 Web API 不起作用
【发布时间】:2015-07-15 12:36:38
【问题描述】:

我正在尝试实现一个 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()"
}

任何想法为什么这不起作用?

【问题讨论】:

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


    【解决方案1】:

    对于两个仅在参数类型上有所不同的Put 方法,Web API 正在尝试根据传入参数的类型解析为正确的操作。

    除非默认模型绑定器可以将传入的 JSON 映射到您已实现的复杂类型,并且该类型与您的 Put 方法之一的参数类型匹配,否则 Web API 将响应 "Ambiguous Match" 异常您是看到是因为它无法确定调用哪个方法。请注意,默认情况下,Web API 不会在操作解析中使用您的 Content-Type 标头。

    我建议阅读Routing and Action Selection in ASP.NET Web API,以便了解路由在内部是如何工作的。然后,您可能希望创建自己的 IHttpActionSelector 实现,在其中检查您的 Content-Type,您可以将请求路由到您选择的操作。你可以找到一个示例实现here

    您还可以阅读有关模型绑定here 的更多信息,了解如何将传入的 JSON 解析为您的一种类型。

    【讨论】:

      猜你喜欢
      • 2013-08-28
      • 2017-10-24
      • 1970-01-01
      • 2013-12-12
      • 2021-04-12
      • 1970-01-01
      • 2018-01-01
      • 1970-01-01
      相关资源
      最近更新 更多