Как реализовать HttpMessageHandler в веб-API?

В проекте 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: Я уже прочитал это: qaru.site/info/114613/..., не помогает мне.

Ответы

Ответ 1

Здесь вы создаете HttpMessageHandler, который замыкает запрос и не пропускает запрос через остальную часть конвейера. Вместо этого вы должны создать DelegatingHandler.

Также есть два типа конвейеров обработчиков сообщений в Web API. Один из них является регулярным конвейером, в котором все запросы для всех маршрутов проходят через и другие, где могут быть обработчики сообщений, специфичные только для определенных маршрутов.

  • Попробуйте создать DelegatingHandler и добавьте его в список обработчиков сообщений HttpConfiguration:

    config.MessageHandlers.Add(new HandlerA())
    
  • Если вы хотите добавить обработчик сообщений, специфичных для маршрута, вы можете сделать следующее:

    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()})
                );
    

Этот веб-сайт Api показывает поток трубопровода.

Ответ 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, чтобы отправить запрос внутреннему обработчику.