【问题标题】:How to implement HttpMessageHandler in Web API?如何在 Web API 中实现 HttpMessageHandler?
【发布时间】:2013-02-18 16:48:39
【问题描述】:

在一个 ASP.NET 4.5 MVC 4 Web API 项目中,我想添加一个自定义的HttpMessageHandler。我更改了WebApiConfig 类(在\App_Satrt\WebApiConfig.cs 中),如下:

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,对我没有帮助。

【问题讨论】:

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


    【解决方案1】:

    在这里,您正在创建一个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 显示流水线。

    【讨论】:

    • 谢谢。解决方案(1)效果很好。但是第 2 号 new HttpControllerDispatcher() 说:System.Web.Http.Dispatcher.HttpControllerDispatcher 不包含采用 0 个参数的构造函数 - 更新:我修复了你的代码。谢谢。
    • 请将 Cuong Le 回答的这一部分添加到您的回答中:要编写自定义消息处理程序,您应该派生自 System.Net.Http.DelegatingHandler。
    • 海报的链接坏了。
    • 我们需要在哪个文件中添加代码:config.MessageHandlers.Add(new HandlerA())
    【解决方案2】:

    要编写自定义消息处理程序,您应该派生自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 将请求发送到内部处理程序。

    【讨论】:

    • @Cuonge Le - 谢谢你的回答。在我用您的代码替换 CustomMessageHandler 后,它会在 return base.SendAsync(request, cancellationToken); 上引发错误,说:尚未分配内部处理程序。。我又错过了什么?
    • @Counge Le - 您的答案和 Kirran Chall 的结合解决了这个问题。再次感谢您。
    • @Cuong Le .NET 4.0 的等价物是什么?我找不到 .NET .4 的 DelegatingHandler ......如何在 4.0 中进行消息处理。感谢您的帮助。
    【解决方案3】:

    我使用@cuongle 回答来解决我的问题。只需添加一个。所以我没有得到“内部处理程序尚未分配。”。谢谢@coungle。

    public class CustomMessageHandler : DelegatingHandler
    {
            public CustomMessageHandler ()
            {
                  //add this to solve "The inner handler has not been assigned"
                   InnerHandler = new HttpClientHandler();
            }
        
            protected override async Task<HttpResponseMessage> 
              SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                // Before request 
                IPrincipal principal = new GenericPrincipal(
                    new GenericIdentity("myuser"), new string[] { "myrole" });
                Thread.CurrentPrincipal = principal;
                HttpContext.Current.User = principal;
        
                var result = await base.SendAsync(request, cancellationToken);
        
                // After request when response arrives
                
                return result;
            }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-10-22
      • 1970-01-01
      • 1970-01-01
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多