C# 用于 WebApi 中响应的 DelegatingHandler

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11970313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 19:54:31  来源:igfitidea点击:

DelegatingHandler for response in WebApi

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

提问by Halvard

I am currently using several delegation handlers (classes derived from DelegatingHandler) to work on the request before it is sent, for things like validating a signature etc. This is all very nice, because I don't have to duplicate signature validation on all calls (for example).

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

I would like to use the same principle on the response from the same web request. Is there something similar to the DelegatingHandler for the response? A way to catch the response before it has returned to the method, in a way?

我想对来自同一网络请求的响应使用相同的原则。响应中是否有类似于 DelegatingHandler 的东西?以某种方式在响应返回到方法之前捕获响应的方法?

Additional information: I am calling a web api using HttpClient.PutAsync(...)

附加信息:我正在使用 HttpClient.PutAsync(...)

采纳答案by Aliostad

Yes. You can do that in the continuation task.

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

I explain it here.

在这里解释一下

For example, this code (from the blog above) traces request URI and adds a dummy header to response.

例如,此代码(来自上面的博客)跟踪请求 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;
    }
}

回答by barrypicker

Here is an example for intercepting the request, and the response. the overridden method SendAsync is used to capture the original request, whereas the method called ResponseHandler is used to capture the response.

这是拦截请求和响应的示例。重写的方法 SendAsync 用于捕获原始请求,而称为 ResponseHandler 的方法用于捕获响应。

Example to capture original request and response

捕获原始请求和响应的示例

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

To use this method, the class needs to be identified and registered as a MessageHandler. I added the following line to my Global.asax file...

要使用此方法,需要将该类标识并注册为 MessageHandler。我将以下行添加到我的 Global.asax 文件中...

Example how to register the new MessageInterceptor class

示例如何注册新的 MessageInterceptor 类

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

Here is my complete Global.asax file. Notice how the MessageInterceptor is referenced...

这是我完整的 Global.asax 文件。注意 MessageInterceptor 是如何被引用的...

Full version of Global.asax showing MessageInterceptor integration

显示 MessageInterceptor 集成的 Global.asax 完整版

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