ДелегированиеHandler для ответа в WebApi
В настоящее время я использую несколько обработчиков делегирования (классы, полученные из DelegatingHandler
) для работы над запросом до его отправки, например, для проверки подписи и т.д. Это все очень хорошо, потому что мне не нужно дублировать подтверждение подписи для всех вызовов (например).
Я хотел бы использовать тот же принцип для ответа от одного и того же веб-запроса. Есть ли что-то похожее на DelegatingHandler для ответа? Способ уловить ответ до того, как он вернется к методу?
Дополнительная информация:
Я вызываю web api, используя HttpClient.PutAsync(...)
Ответы
Ответ 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());
}
}
}