30

私は現在DelegatingHandler、署名の検証などのために、送信前に要求を処理するためにいくつかの委任ハンドラー(から派生したクラス)を使用しています。すべての呼び出しで署名の検証を複製する必要がないため、これはすべて非常に便利です(例えば)。

同じWebリクエストからの応答にも同じ原則を使用したいと思います。応答のDelegatingHandlerに似たものはありますか?ある意味で、メソッドに戻る前に応答をキャッチする方法はありますか?

追加情報:私はを使用してWebAPIを呼び出していますHttpClient.PutAsync(...)

4

2 に答える 2

50

はい。継続タスクでそれを行うことができます。

ここで説明します

たとえば、このコード(上記のブログから)はリクエスト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;
    }
}
于 2012-08-15T14:01:21.213 に答える
21

リクエストとレスポンスをインターセプトする例を次に示します。オーバーライドされたメソッド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がどのように参照されているかに注目してください...

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());
        }
    }
}
于 2013-07-29T01:23:05.677 に答える