मैसेज हैंडलर में, मैसेज हैंडलर्स की एक श्रृंखला एक साथ जुड़ी होती है। पहला हैंडलर HTTP रिक्वेस्ट प्राप्त करता है, कुछ प्रोसेसिंग करता है, और रिक्वेस्ट को अगले हैंडलर को देता है। किसी बिंदु पर, रिस्पॉन्स बनाया जाता है और चेन के ऊपर वापस जाता है। इस पैटर्न को डेलिगेटिंग हैंडलर कहा जाता है।
DelegatingHandler अवलोकन
बिल्ट-इन सर्वर-साइड मैसेज हैंडलर्स के साथ, हम अपने स्वयं के सर्वर-साइड HTTP मैसेज हैंडलर्स भी बना सकते हैं। ASP.NET Web API में कस्टम सर्वर-साइड HTTP मैसेज हैंडलर बनाने के लिए, हम DelegatingHandler का उपयोग करते हैं। हमें System.Net.Http.DelegatingHandler से डेराइव एक क्लास बनानी होगी। उस कस्टम क्लास को फिर SendAsync मेथड को ओवरराइड करना चाहिए।
SendAsync मेथड सिग्नेचर
Task SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
मेथड HttpRequestMessage को इनपुट के रूप में लेता है और असिंक्रोनसली HttpResponseMessage लौटाता है।
विशिष्ट इम्प्लीमेंटेशन पैटर्न
- रिक्वेस्ट मैसेज प्रोसेस करें (इनर हैंडलर से पहले)
- base.SendAsync कॉल करें रिक्वेस्ट को इनर हैंडलर को भेजने के लिए
- इनर हैंडलर रिस्पॉन्स मैसेज लौटाता है (यह चरण असिंक्रोनस है)
- रिस्पॉन्स प्रोसेस करें और कॉलर को लौटाएं
उदाहरण 1: रिक्वेस्ट/रिस्पॉन्स लॉगिंग (पास-थ्रू)
public class CustomMessageHandler : DelegatingHandler
{
protected async override Task SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
Debug.WriteLine("CustomMessageHandler रिक्वेस्ट प्रोसेस कर रहा है");
// इनर हैंडलर को कॉल करें (पाइपलाइन जारी रखें)
var response = await base.SendAsync(request, cancellationToken);
Debug.WriteLine("CustomMessageHandler रिस्पॉन्स प्रोसेस कर रहा है");
return response;
}
}
उदाहरण 2: इनर हैंडलर को स्किप करें (शॉर्ट-सर्किट)
एक डेलिगेटिंग हैंडलर इनर हैंडलर को स्किप करके सीधे रिस्पॉन्स भी बना सकता है।
public class CustomMessageHandler : DelegatingHandler
{
protected override Task SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// सीधे रिस्पॉन्स बनाएं - इनर हैंडलर को कॉल नहीं किया जाता
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent("Skipping the inner handler")
};
// TaskCompletionSource एक टास्क बनाता है जिसमें डेलीगेट नहीं होता
var taskCompletion = new TaskCompletionSource();
taskCompletion.SetResult(response);
return taskCompletion.Task;
}
}
उदाहरण 3: रिक्वेस्ट/रिस्पॉन्स मॉडिफिकेशन
public class CustomHeaderHandler : DelegatingHandler
{
protected override async Task SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// रिक्वेस्ट हेडर जोड़ें
request.Headers.Add("X-Custom-Request-Header", "CustomValue");
// पाइपलाइन जारी रखें
var response = await base.SendAsync(request, cancellationToken);
// रिस्पॉन्स हेडर जोड़ें
response.Headers.Add("X-Custom-Response-Header", "ProcessedByCustomHandler");
response.Headers.Add("X-Response-Time", DateTime.UtcNow.ToString("O"));
return response;
}
}
उदाहरण 4: एरर हैंडलिंग और रीट्राई लॉजिक
public class RetryHandler : DelegatingHandler
{
private readonly int _maxRetries;
public RetryHandler(int maxRetries = 3)
{
_maxRetries = maxRetries;
}
protected override async Task SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
for (int i = 0; i <= _maxRetries; i++)
{
response = await base.SendAsync(request, cancellationToken);
// सफलता या नॉन-रीट्रायबल एरर पर ब्रेक करें
if (response.IsSuccessStatusCode || !IsRetriable(response.StatusCode))
break;
// रीट्राई से पहले वेट करें (एक्सपोनेंशियल बैकऑफ)
await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, i)), cancellationToken);
}
return response;
}
private bool IsRetriable(HttpStatusCode statusCode)
{
return statusCode == HttpStatusCode.RequestTimeout ||
statusCode == HttpStatusCode.InternalServerError ||
statusCode == HttpStatusCode.BadGateway ||
statusCode == HttpStatusCode.ServiceUnavailable ||
statusCode == HttpStatusCode.GatewayTimeout;
}
}
उदाहरण 5: कंप्रेशन हैंडलर
public class CompressionHandler : DelegatingHandler
{
protected override async Task SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
// क्लाइंट gzip स्वीकार करता है?
if (request.Headers.AcceptEncoding.Any(e => e.Value == "gzip"))
{
var content = response.Content;
var compressedContent = new CompressedContent(content);
response.Content = compressedContent;
response.Content.Headers.ContentEncoding.Add("gzip");
}
return response;
}
}
Global.asax में रजिस्ट्रेशन
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
// ऑर्डर मायने रखता है!
GlobalConfiguration.Configuration.MessageHandlers.Add(new LoggingHandler());
GlobalConfiguration.Configuration.MessageHandlers.Add(new ApiKeyHandler("secret"));
GlobalConfiguration.Configuration.MessageHandlers.Add(new CustomHeaderHandler());
}
}
DelegatingHandler vs ASP.NET Core Middleware
| पहलू | DelegatingHandler (Web API) | Middleware (ASP.NET Core) |
|---|---|---|
| बेस क्लास | DelegatingHandler | कोई बेस क्लास नहीं (कन्वेंशन) |
| मेथड | SendAsync | Invoke/InvokeAsync |
| रजिस्ट्रेशन | app.UseMiddleware() | |
| स्कोप | केवल Web API पाइपलाइन | पूरा ASP.NET Core पाइपलाइन |
| DI सपोर्ट | सीमित | पूर्ण DI सपोर्ट |
मुख्य अंतर्दृष्टि: DelegatingHandler रूसी गुड़िया (Russian Doll) मॉडल का पालन करता है - प्रत्येक हैंडलर अगले को रैप करता है, रिक्वेस्ट के लिए अंदर और रिस्पॉन्स के लिए बाहर दोनों दिशाओं में प्रोसेसिंग सक्षम करता है।