Подтвердить что ты не робот

ДелегированиеHandler для ответа в WebApi

В настоящее время я использую несколько обработчиков делегирования (классы, полученные из DelegatingHandler) для работы над запросом до его отправки, например, для проверки подписи и т.д. Это все очень хорошо, потому что мне не нужно дублировать подтверждение подписи для всех вызовов (например).

Я хотел бы использовать тот же принцип для ответа от одного и того же веб-запроса. Есть ли что-то похожее на DelegatingHandler для ответа? Способ уловить ответ до того, как он вернется к методу?

Дополнительная информация: Я вызываю web api, используя HttpClient.PutAsync(...)

4b9b3361

Ответ 1

Да. Вы можете сделать это в задаче продолжения.

Я объясню это здесь.

Например, этот код (из вышеприведенного блога) отслеживает URI запроса запросов и добавляет фиктивный заголовок к ответу.

public class DummyHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // work on the request 
       Trace.WriteLine(request.RequestUri.ToString());

       return base.SendAsync(request, cancellationToken)
           .ContinueWith(task =>
           {
               // work on the response
               var response = task.Result;
               response.Headers.Add("X-Dummy-Header", Guid.NewGuid().ToString());
              return response;
           });
    }
}

Ответ 2

Вот пример перехвата запроса и ответа. переопределенный метод SendAsync используется для захвата исходного запроса, тогда как метод ResponseHandler используется для захвата ответа.

Пример для захвата исходного запроса и ответа

using System.Net.Http;
using System.Threading.Tasks;
namespace webAPI_Test
{
    public class MessageInterceptor : DelegatingHandler
    {
        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            // CATCH THE REQUEST BEFORE SENDING TO THE ROUTING HANDLER
            var headers = request.ToString();
            var body = request.Content.ReadAsStringAsync().Result;
            var fullRequest = headers + "\n" + body;

            // SETUP A CALLBACK FOR CATCHING THE RESPONSE - AFTER ROUTING HANDLER, AND AFTER CONTROLLER ACTIVITY
            return base.SendAsync(request, cancellationToken).ContinueWith(
                        task =>
                        {
                            // GET THE COPY OF THE TASK, AND PASS TO A CUSTOM ROUTINE
                            ResponseHandler(task);

                            // RETURN THE ORIGINAL RESULT
                            var response = task.Result;
                            return response;
                        }
            );
        }

        public void ResponseHandler(Task<HttpResponseMessage> task)
        {
            var headers = task.Result.ToString();
            var body = task.Result.Content.ReadAsStringAsync().Result;

            var fullResponse = headers + "\n" + body;
        }
    }
}

Чтобы использовать этот метод, класс необходимо идентифицировать и зарегистрировать как MessageHandler. Я добавил следующую строку в свой файл Global.asax...

Пример того, как зарегистрировать новый класс MessageInterceptor

GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageInterceptor());

Вот мой полный файл Global.asax. Обратите внимание, как ссылается MessageInterceptor...

Полная версия Global.asax, показывающая интеграцию MessageInterceptor

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace webAPI_Test
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageInterceptor());
        }
    }
}