EnsureSuccessStatusCode का उपयोग और HttpRequestException की हैंडलिंग यह फेंकता है


105

का उपयोग पैटर्न क्या है HttpResponseMessage.EnsureSuccessStatusCode()? यह संदेश की सामग्री का निपटान करता है और फेंकता है HttpRequestException, लेकिन मैं यह देखने में विफल रहता हूं कि प्रोग्रामेटिक रूप से इसे सामान्य से अलग कैसे हैंडल किया जाए Exception। उदाहरण के लिए, इसमें वह शामिल नहीं है HttpStatusCode, जो आसान होता।

क्या इससे अधिक जानकारी प्राप्त करने का कोई तरीका है? किसी को भी EnsureSuccessStatusCode()और HttpRequestException दोनों के प्रासंगिक उपयोग पैटर्न दिखा सकते हैं ?

जवाबों:


157

EnsureSuccessStatusCodeजब आप किसी विशिष्ट तरीके से विफलता के मामलों को संभालना नहीं चाहते हैं, तो मुहावरेदार उपयोग एक अनुरोध की सफलता को छिपाना है। यह विशेष रूप से तब उपयोगी होता है जब आप किसी क्लाइंट को जल्दी से प्रोटोटाइप बनाना चाहते हैं।

जब आप तय करते हैं कि आप एक विशिष्ट तरीके से विफलता के मामलों को संभालना चाहते हैं, तो निम्न कार्य न करें।

var response = await client.GetAsync(...);
try
{
    response.EnsureSuccessStatusCode();
    // Handle success
}
catch (HttpRequestException)
{
    // Handle failure
}

यह केवल एक अपवाद को तुरंत पकड़ लेता है, जिसका कोई मतलब नहीं है। की IsSuccessStatusCodeसंपत्ति HttpResponseMessageइस उद्देश्य के लिए है। इसके बजाय निम्नलिखित करें।

var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)
{
    // Handle success
}
else
{
    // Handle failure
}

1
क्या वास्तविक पूर्णांक स्थिति कोड प्राप्त करने का कोई तरीका है ? जब मैं यह कोशिश करता हूं तो मुझे 404 स्टेटस कोड के बजाय "NotFound" जैसे स्ट्रिंग मिलते हैं।
NickG

12
@NickG (int)response.StatusCode(देखें msdn.microsoft.com/en-us/library/… )
टिमोथी शील्ड

1
ध्यान दें, EnsureSuccessStatusCode () द्वारा फेंके गए डिफ़ॉल्ट HttpRequestException के कारण वाक्यांश होगा। लेकिन आप प्रतिक्रिया में वैसे भी उस संपत्ति तक पहुंच सकते हैं यदि यह सफल नहीं है।
स्टीफन ज्वोनर

@StefanZvonar मुझे आपके द्वारा लिखे गए कारण के कारण वाक्यांश नहीं मिल सकते।
कांसईरोबोट

1
@NickG आप (int) response का उपयोग कर सकते हैं। HTTP स्टेटस कोड के लिए संख्यात्मक मान प्राप्त करने के लिए
टैटसकोड

95

मुझे EnsureSuccessStatusCode पसंद नहीं है क्योंकि यह कुछ भी नहीं लौटाता है। यही कारण है कि मैंने अपना खुद का एक्सटेंशन बनाया है:

public static class HttpResponseMessageExtensions
{
    public static async Task EnsureSuccessStatusCodeAsync(this HttpResponseMessage response)
    {
        if (response.IsSuccessStatusCode)
        {
            return;
        }

        var content = await response.Content.ReadAsStringAsync();

        if (response.Content != null)
            response.Content.Dispose();

        throw new SimpleHttpResponseException(response.StatusCode, content);
    }
}

public class SimpleHttpResponseException : Exception
{
    public HttpStatusCode StatusCode { get; private set; }

    public SimpleHttpResponseException(HttpStatusCode statusCode, string content) : base(content)
    {
        StatusCode = statusCode;
    }
}

Microsoft के EnsureSuccessStatusCode का स्रोत कोड यहां पाया जा सकता है

एसओ लिंक पर आधारित तुल्यकालिक संस्करण :

public static void EnsureSuccessStatusCode(this HttpResponseMessage response)
{
    if (response.IsSuccessStatusCode)
    {
        return;
    }

    var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

    if (response.Content != null)
        response.Content.Dispose();

    throw new SimpleHttpResponseException(response.StatusCode, content);
}

मैं IsSuccessStatusCode के बारे में क्या पसंद नहीं करता है कि यह "अच्छी तरह से" पुन: प्रयोज्य नहीं है। उदाहरण के लिए आप नेटवर्क समस्या के मामले में अनुरोध दोहराने के लिए लाइब्रेरी जैसे पोली का उपयोग कर सकते हैं । उस स्थिति में आपको अपवाद जुटाने के लिए अपने कोड की आवश्यकता होती है ताकि पोली या कोई अन्य लाइब्रेरी इसे संभाल सके ...


1
सहमति दें, डिफ़ॉल्ट कोड ने वापसी से एक सार्थक संदेश प्राप्त करने के लिए सुविधा को याद किया।
LT

2
आपका संस्करण मूल कार्यान्वयन से भिन्न कार्य करता है EnsureSuccessStatusCode। आप हमेशा निपटते हैं response.Content(क्योंकि अंततः return;कथन के बाद भी हमेशा कहा जाता है ) और यह फ़्यूचर पढ़ने के लिए सामग्री को नष्ट कर देता है। मूल कार्यान्वयन केवल सामग्री का निपटान करता है जब स्थिति कोड सफल परिणाम का संकेत नहीं देता है।
लुकास। नवरातिल

4
मुझे नहीं मिलता कि आप पहले क्यों await response.Content.ReadAsStringAsync()और फिर जाँचते हैंif (response.Content != null)
mafu

3
पोली अब रिटर्न परिणामों के साथ-साथ अपवादों को भी संभालती है, ठीक इसी तरह के परिदृश्य के साथ सहायता करने के लिए। आप HttpRequestकॉल की सुरक्षा के लिए पोली को कॉन्फ़िगर कर सकते हैं, और कुछ अपवादों को संभालने के लिए नीति को कॉन्फ़िगर कर सकते हैं, और कुछ HttpResponseCodeएस। यहां पोली रेडीम में उदाहरण
पहाड़ यात्री

2
यह कैसे response.Contentशून्य हो सकता है जब इस पर सिर्फ एक विधि का आह्वान किया गया हो?
इयान वॉर्बर्टन

1

जब मैं एक ही विधि पर अपवाद को संभालना नहीं चाहता, तो मैं EnsureSuccessStatusCode का उपयोग करता हूं।

public async Task DoSomethingAsync(User user)
{
    try
    {
        ...
        var userId = await GetUserIdAsync(user)
        ...
    }
    catch(Exception e)
    {
        throw;
    }
}

public async Task GetUserIdAsync(User user)
{
    using(var client = new HttpClient())
    {
        ...
        response = await client.PostAsync(_url, context);

        response.EnsureSuccesStatusCode();
        ...
    }
}

GetUserIdAsync पर फेंका गया अपवाद DoSomethingAsync पर संभाला जाएगा।


0

नीचे मेरा प्रस्तावित समाधान है। एकमात्र दोष यह है कि चूंकि ASP.NET कोर फ्रेमवर्क संसाधन प्रबंधक फ्रेमवर्क के लिए आंतरिक है, इसलिए मैं Microsoft के अंतर्राष्ट्रीय संदेश स्ट्रिंग्स का सीधे उपयोग नहीं कर सकता, इसलिए मैं यहां केवल शब्दशः अंग्रेजी संदेश शाब्दिक का उपयोग कर रहा हूं।

पेशेवरों

  • 5xx सर्वर त्रुटि के लिए सामग्री लॉग करता है
    • कभी-कभी, एक सर्वर त्रुटि वास्तव में भेस में एक क्लाइंट त्रुटि होती है, जैसे कि एक क्लाइंट एक पदावनत समापन बिंदु का उपयोग करके जो अंततः बंद हो गया।
  • एकीकरण परीक्षणों का उपयोग करते समय त्रुटियों को उजागर करना आसान बनाता है ConfigureTestContainer<T>

विपक्ष

  • अक्षम।
    • यदि आप प्रतिक्रिया सामग्री पढ़ते हैं, और सामग्री बहुत लंबी है, तो आप ग्राहक को धीमा कर देंगे। कुछ ग्राहकों के लिए, नरम वास्तविक समय की प्रतिक्रिया आवश्यकताओं के साथ, यह घबराना अस्वीकार्य हो सकता है।
  • त्रुटि लॉगिंग और निगरानी के लिए गलत जिम्मेदारी।
    • यदि यह 5xx सर्वर त्रुटि है, तो क्लाइंट क्यों परवाह करता है, क्योंकि क्लाइंट ने कुछ भी गलत नहीं किया है? बस कॉल करें response.EnsureSuccessStatusCode();और सर्वर को इससे निपटने दें।
    • आंतरिक सर्वर त्रुटि होने पर सिर्फ सर्वर त्रुटि लॉग की जांच क्यों न करें?
  • Contentस्थिति की जांच करने से पहले संपत्ति को पढ़ने की आवश्यकता है । ऐसी परिस्थितियां हो सकती हैं जहां यह वांछनीय नहीं है, जिनमें से एक अक्षमता है।

प्रयोग

using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, "controller/action"))
{
  using (var response = await HttpClient.SendAsync(requestMessage))
  {
    var content = await response.Content.ReadAsStringAsync();
    response.EnsureSuccessStatusCode2(content);
    var result = JsonConvert.DeserializeObject<ResponseClass>(content);
  }
}

एपीआई

    public static class HttpResponseMessageExtensions
    {
        public static void EnsureSuccessStatusCode2(this HttpResponseMessage message, string content = null)
        {
            if (message.IsSuccessStatusCode)
                return;
            var contentMessage = string.IsNullOrWhiteSpace(content) ? string.Empty : $"Content: {content}";
            throw new HttpRequestException(string.Format(
                System.Globalization.CultureInfo.InvariantCulture,
                "Response status code does not indicate success: {0} ({1}).{2}",
                (int)message.StatusCode,
                message.ReasonPhrase,
                contentMessage)
                );
        }
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.