特定于路由的ASP.NET MVC Web API消息处理程序不调用控制器操作

时间:2017-04-19 15:54:56

标签: asp.net-mvc asp.net-web-api asp.net-web-api2 asp.net-web-api-routing message-handlers

我有一个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()
);

当我POST到控制器动作方法时,例如:

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)时,该路线正在使用

当我以路径特定的方式连接消息处理程序时,为什么不调用我的动作方法?

2 个答案:

答案 0 :(得分: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()足以将消息处理程序绑定回路由映射到的控制器。

虽然这已经解决了,但我还是不明白为什么要这样做(为什么我的假设是不正确的)所以我要去读它。

答案 1 :(得分:0)

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

configuration.Routes.MapMvcAttributeRoutes();

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