DelegatingHandler用于WebApi中的响应

时间:2012-08-15 13:39:44

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

我目前正在使用多个委派处理程序(派生自DelegatingHandler的类)在发送之前处理请求,例如验证签名等。这一切都非常好,因为我没有在所有调用上复制签名验证(例如)。

我想对来自同一网络请求的响应使用相同的原则。是否有类似于DelegatingHandler的响应?一种在回复方法之前捕获响应的方法吗?

其他信息: 我使用HttpClient.PutAsync(...)

呼叫网络API

2 个答案:

答案 0 :(得分:43)

是。您可以在继续任务中执行此操作。

我解释一下here

例如,此代码(来自上面的博客)跟踪请求URI并向响应添加虚拟标头。

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

       var response = await base.SendAsync(request, cancellationToken);
       response.Headers.Add("X-Dummy-Header", Guid.NewGuid().ToString());
       return response;
    }
}

答案 1 :(得分:17)

以下是拦截请求和响应的示例。重写方法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());
        }
    }
}