2012-04-20 14 views
5

क्या कस्टम संदेश हैंडलर के निष्पादन आदेश को नियंत्रित करना संभव है?एएसपी.नेट वेब एपीआई संदेश हैंडलर

उदाहरण के तौर पर, मैं एक लॉगिंग हैंडलर को पहले निष्पादित करना चाहता हूं, इसलिए मैं हमेशा एक अनुरोध लॉग करता हूं।

आखिरकार लॉगिंग हैंडलर जोड़ने के अलावा, मैं यह देखने में असफल रहा हूं कि इसे कैसे प्राप्त किया जाए।

config.MessageHandlers.Add(new CustomHandlerOne()); 
config.MessageHandlers.Add(new CustomHandlerTwo()); 
config.MessageHandlers.Add(new LoggingHandler()); 

उत्तर

7

जिस आदेश में आप हैंडलर पंजीकृत करते हैं, यह निर्धारित करता है कि उन्हें कब बुलाया जाता है लेकिन जैसा कि अलीस्टाड बताता है कि वे रूसी गुड़िया मॉडल में काम करते हैं, इसलिए पहले व्यक्ति को अंतिम और बाहर भी कहा जाता है।

पंजीकृत हैंडलर आने वाले पथ में नीचे-नीचे फैशन में और आउटगोइंग में टॉप-डाउन में शामिल किए जाते हैं। यही है, अंतिम प्रविष्टि को आने वाले अनुरोध संदेश के लिए पहले कहा जाता है लेकिन आउटगोइंग प्रतिक्रिया संदेश के लिए अंतिम बार बुलाया जाता है।

3

नहीं - AFAIK।

यह रूसी गुड़िया मॉडल है, जिसमें एक हैंडलर दूसरे के अंदर काम कर रहा है। यह आंतरिक वर्ग HttpPipelineFactory में बनाया गया है (के रूप में यह जारी किया गया था जब आप स्रोत कोड देख सकते हैं):

public static HttpMessageHandler Create(IEnumerable<DelegatingHandler> handlers, HttpMessageHandler innerChannel) 
    { 
     if (innerChannel == null) 
     { 
      throw Error.ArgumentNull("innerChannel"); 
     } 

     if (handlers == null) 
     { 
      return innerChannel; 
     } 

     // Wire handlers up 
     HttpMessageHandler pipeline = innerChannel; 
     foreach (DelegatingHandler handler in handlers) 
     { 
      if (handler == null) 
      { 
       throw Error.Argument("handlers", SRResources.DelegatingHandlerArrayContainsNullItem, typeof(DelegatingHandler).Name); 
      } 

      if (handler.InnerHandler != null) 
      { 
       throw Error.Argument("handlers", SRResources.DelegatingHandlerArrayHasNonNullInnerHandler, typeof(DelegatingHandler).Name, "InnerHandler", handler.GetType().Name); 
      } 

      handler.InnerHandler = pipeline; 
      pipeline = handler; 
     } 

     return pipeline; 
    } 

तो क्या कोड करता है एक सूची प्राप्त है और फिर इसे एक रूसी गुड़िया में बदलने के लिए है।

+0

यही मैंने सोचा था। मुझे नहीं लगता कि यह प्रदाताओं की अवधारणा का समर्थन करता है। एमवीसी में IFilterprovider इंटरफ़ेस की तरह। – Darren

+0

मैं मानता हूं कि 'Async/ContinueWith' सामान इसे घोंसले की गुड़िया की तरह महसूस करता है। यह मेरी राय में, एमएस के रूप में आदेश के रूप में वर्णन करने के लिए, यह अधिक सटीक है। प्रत्येक हैंडलर को दो बार बुलाया जाता है - एक बार रास्ते में (क्रम में क्रम में) और एक बार रिवर्स ऑर्डर में बाहर निकलने पर। निम्नलिखित आलेख में तीसरा आरेख यह स्पष्ट करता है .. http://www.asp.net/web-api/overview/working-with-http/http-message-handlers – EBarr

3

मैं यहां नवीनतम बिट्स के आधार पर बात कर रहा हूं जो कोडप्लेक्स एएसपी.नेट वेब स्टैक रेपो पर उपलब्ध हैं।

आदेश उपयोगकर्ता द्वारा नियंत्रित किया जाता है और यहां कोई मनमाना आदेश नहीं है। मुझे समझाएं:

मान लें कि हमारे पास दो संदेश हैंडलर हैं: MyMessageHandler और MyMessageHandler2। यह मानते हुए कि हम उन्हें नीचे के रूप में रजिस्टर:

protected void Application_Start(object sender, EventArgs e) { 

    RouteConfig.RegisterRoutes(GlobalConfiguration.Configuration.Routes); 
    GlobalConfiguration.Configuration.MessageHandlers.Add(new MyMessageHandler()); 
    GlobalConfiguration.Configuration.MessageHandlers.Add(new MyMessageHandler2()); 
} 

क्या तुम यहाँ उम्मीद MyMessageHandler दूसरे शब्दों फीफो में एक दूसरे के रूप में पहली और MyMessageHandler2 को चलाने के लिए, है।

अगर हम ढांचे के अंदर हुड के नीचे एक छोटा सा देखो, हम उस HttpServer उदाहरण के Initialize विधि System.Net.Http.HttpClientFactory की CreatePipeline विधि लागू होने पर देखेंगे (जो पहले HttpPipelineFactory.Create पद्धति के रूप में जाना जाता था के रूप में अली का संकेत मिला।) CreatePipeline विधि स्वीकार करता है दो पैरामीटर: HttpMessageHandler और IEnumerable<DelegatingHandler>HttpServer.Initialize विधि System.Web.Http.Dispatcher.HttpControllerDispatcherHttpMessageHandler पैरामीटर के लिए पिछले HttpMessageHandler श्रृंखला और HttpConfiguration.MessageHandlers के लिए IEnumerable<DelegatingHandler> पैरामीटर के लिए पास हो रही है।

क्या CreatePipeline विधि के अंदर होता है IMO बहुत चालाक है:

public static HttpMessageHandler CreatePipeline(HttpMessageHandler innerHandler, IEnumerable<DelegatingHandler> handlers) 
{ 
    if (innerHandler == null) 
    { 
     throw Error.ArgumentNull("innerHandler"); 
    } 

    if (handlers == null) 
    { 
     return innerHandler; 
    } 

    // Wire handlers up in reverse order starting with the inner handler 
    HttpMessageHandler pipeline = innerHandler; 
    IEnumerable<DelegatingHandler> reversedHandlers = handlers.Reverse(); 
    foreach (DelegatingHandler handler in reversedHandlers) 
    { 
     if (handler == null) 
     { 
      throw Error.Argument("handlers", Properties.Resources.DelegatingHandlerArrayContainsNullItem, typeof(DelegatingHandler).Name); 
     } 

     if (handler.InnerHandler != null) 
     { 
      throw Error.Argument("handlers", Properties.Resources.DelegatingHandlerArrayHasNonNullInnerHandler, typeof(DelegatingHandler).Name, "InnerHandler", handler.GetType().Name); 
     } 

     handler.InnerHandler = pipeline; 
     pipeline = handler; 
    } 

    return pipeline; 
} 

आप देख सकते हैं, संदेश हैंडलर क्रम उलट है और Matryoshka doll बनाया है, लेकिन यहाँ सावधान रहना है: यह सुनिश्चित किया जाता है HttpControllerDispatcher है कि चेन के अंदर चलाने के लिए अंतिम संदेश हैंडलर।

दो बार कॉल करने के लिए, यह वास्तव में काफी सच नहीं है। संदेश हैंडलर को दो बार नहीं कहा जाएगा, दूसरी तरफ जारी रखने वाली निरंतरता विधि होगी। ऐसा करने के लिए आप पर निर्भर है। यदि आप कॉलबैक प्रदान करते हैं (दूसरे शब्दों में निरंतरता में), तो आपके संदेश हैंडलर को क्लाइंट को वापस जेनरेट किए गए प्रतिक्रिया संदेश के साथ कॉल किया जाएगा, जिसके साथ आप खेल सकते हैं।

उदाहरण के लिए, मान लेते हैं कि निम्न दो संदेश संचालकों हम ऊपर पंजीकृत किया है हैं:

public class MyMessageHandler : DelegatingHandler { 

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { 

     //inspect request here 

     return base.SendAsync(request, cancellationToken).ContinueWith(task => { 

      //inspect the generated response 
      var response = task.Result; 

      return response; 
     }); 
    } 
} 

और यह अन्य एक है:

public class MyMessageHandler2 : DelegatingHandler { 

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { 

     //inspect request here 

     return base.SendAsync(request, cancellationToken).ContinueWith(task => { 

      //inspect the generated response 
      var response = task.Result; 

      return response; 
     }); 
    } 
} 

हम निरंतरता प्रदान की है, हमारे संदेश हैंडलर को फिलो ऑर्डर में क्लाइंट के रास्ते पर वापस बुलाया जाएगा। इसलिए, MyMessageHandler2 के अंदर निरंतरता विधि पहले रास्ते पर आने वाली होगी और MyMessageHandler के अंदर एक दूसरा होगा।

संबंधित मुद्दे