2013-03-04 25 views
16

在ASP.NET 4.5 MVC 4 Web API项目中,我想添加一个自定义HttpMessageHandler。我已经改变了WebApiConfig类(在\ App_Satrt \ WebApiConfig.cs),具体如下:如何在Web API中实现HttpMessageHandler?

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional }, 
      constraints: null, 
      handler: new MyCustomizedHttpMessageHandler() 
     ); 
    } 
} 

然后我开发MyCustomizedHttpMessageHandler

public class MyCustomizedHttpMessageHandler : HttpMessageHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     IPrincipal principal = new GenericPrincipal(
      new GenericIdentity("myuser"), new string[] { "myrole" }); 
     Thread.CurrentPrincipal = principal; 
     HttpContext.Current.User = principal; 

     return Task<HttpResponseMessage>.Factory.StartNew(() => request.CreateResponse()); 
    } 
} 

然而,请求API(假设http://mylocalhost.com/api/values) ,总是返回状态码200,没有任何数据。我的意思是它永远不会去ValuesController.cs的'GET()'方法。

我错过了什么?我如何正确实施HttpMessageHandler

PS:已经看过这个:https://stackoverflow.com/a/12030785/538387,不帮我。

回答

22

在这里,您正在创建一个HttpMessageHandler,它将请求短路并且不让请求通过管道的其余部分。相反,您应该创建一个DelegatingHandler

在Web API中还有2种消息处理程序管道。一个是所有路由的所有请求都经过的常规管道,另一个可能只有特定路由的消息处理程序。

  1. 尝试创建一个DelegatingHandler并将其添加到您的HttpConfiguration的消息处理程序的列表:

    config.MessageHandlers.Add(new HandlerA()) 
    
  2. 如果你想添加路由特定的消息处理程序,那么你可以做以下:

    config.Routes.MapHttpRoute(
          name: "DefaultApi", 
          routeTemplate: "api/{controller}/{id}", 
          defaults: new { id = RouteParameter.Optional }, 
          constraints: null, 
          handler: 
            HttpClientFactory.CreatePipeline(
              new HttpControllerDispatcher(config), 
              new DelegatingHandler[]{new HandlerA()}) 
          ); 
    

This Web Api Poster显示pipeli ne流动。

+0

谢谢。解决方案(1)运行良好。但数字2,'新HttpControllerDispatcher()'说:** System.Web.Http.Dispatcher.HttpControllerDispatcher不包含一个构造函数,它需要0个参数** - 更新:我修复了您的代码。谢谢。 – Tohid 2013-03-04 17:43:28

+0

我更新了我的上述帖子too.thanks。 – 2013-03-04 18:25:29

+0

请将Cuong Le的回答添加到回答中:**要编写自定义消息处理程序,您应该从'System.Net.Http.DelegatingHandler'派生** – Tohid 2013-03-04 18:37:43

11

要编写自定义消息处理程序,您应该从System.Net.Http.DelegatingHandler

class CustomMessageHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> 
     SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     IPrincipal principal = new GenericPrincipal(
      new GenericIdentity("myuser"), new string[] { "myrole" }); 
     Thread.CurrentPrincipal = principal; 
     HttpContext.Current.User = principal; 

     return base.SendAsync(request, cancellationToken); 
    } 
} 

派生并呼吁base.SendAsync发送请求到内部处理程序。

+2

@Cuonge Le - 谢谢你的回答。在我用你的代码替换了'CustomMessageHandler'后,它在'return base.SendAsync(request,cancellationToken);'上说错误:**内部处理程序没有被赋值。我又错过了什么? – Tohid 2013-03-04 17:27:16

+0

@Counge Le - 你的答案和Kirran Chall's的结合已经解决了这个问题。再次感谢你。 – Tohid 2013-03-04 17:57:34

+0

@Cong Le .NET 4.0的等价物是什么?我无法找到.NET .4的DelegatingHandler ...如何在4.0中执行消息处理。谢谢你的帮助。 – jaxxbo 2013-05-22 15:06:05