1

我有一个 ASP.NET MVC Web API 控制器:

[HttpPost]
public async Task<HttpResponseMessage> Post(HttpRequestMessage req, CancellationToken cancellationToken) {...}

我创建了一个自定义消息处理程序:

public class MyMessageHandler : DelegatingHandler
{
     protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
     {
         // ...

         var response = await base.SendAsync(request, cancellationToken);

         // ...

        return response;
      }
  }

WebConfigApi.cs我将消息处理程序路由特定于控制器操作方法:

configuration.Routes.MapHttpRoute(
   name: "UpdateStuffAPI",
   routeTemplate: "api/updatestuff/post/{stuffid}",
   defaults: new { feedid = RouteParameter.Optional },
   constraints: null,
   handler: new MyMessageHandler()
);

当我发布到控制器操作方法时,例如:

http://hostname/api/updatestuff/post?stuffid=12345

消息处理程序按预期拦截请求。但是在单步执行中:

var response = await base.SendAsync(request, cancellationToken);

控制器操作方法永远不会被击中。

作为测试,我删除了特定于路由的布线并使消息处理程序全局化:

configuration.MessageHandlers.Add(new MyMessageHandler());

SendAsync正确调用我的控制器的操作方法。

所以我的想法是路线定义有问题。但是,消息处理程序通过特定于路由的接线调用的,并且Route Debugger显示当我 POST 到我的控制器 ( ) 时,正在http://hostname/api/updatestuff/post?stuffid=12345使用该路由。

当我以特定于路由的方式连接消息处理程序时,为什么没有调用我的操作方法?

4

2 回答 2

1

我错过了将消息处理程序与接下来应该调用的路由/控制器联系起来的代码。

特定于路由的消息处理程序必须明确告知 Web Api 应用程序的HttpConfiguration. 我所拥有的WebConfigApi.cs是:

configuration.Routes.MapHttpRoute(
   name: "UpdateStuffAPI",
   routeTemplate: "api/updatestuff/post/{stuffid}",
   defaults: new { feedid = RouteParameter.Optional },
   constraints: null,
   handler: new MyMessageHandler()
);

我需要的是:

configuration.Routes.MapHttpRoute(
   name: "UpdateStuffAPI",
   routeTemplate: "api/updatestuff/post/{stuffid}",
   defaults: new { feedid = RouteParameter.Optional },
   constraints: null,
   handler: new MyMessageHandler(configuration)
);

换句话说,配置对象需要在构造时传递给消息处理程序。所以消息处理程序需要一个构造函数:

public MyMessageHandler(HttpConfiguration httpConfiguration)
{
   InnerHandler = new HttpControllerDispatcher(httpConfiguration);
}

我天真地假设handler: new MyMessageHandler()路由映射中的设置足以将消息处理程序绑定到路由映射到的控制器。

虽然这个问题已经解决,但我承认我还不明白为什么需要这样做(为什么我的假设不正确),所以我将继续阅读。

于 2017-04-23T16:36:21.393 回答
0

您是否尝试过使用以下方法启用属性路由:

configuration.Routes.MapMvcAttributeRoutes();

路由还取决于您映射属性路由和普通 http 路由的顺序。

于 2017-04-20T07:10:22.520 回答