[c#] HttpResponseException फेंको या वापसी अनुरोध। CreateErrorResponse?



Answers

यदि आप HttpResponseMessage को वापस नहीं कर रहे हैं और इसके बजाय इकाई / मॉडल कक्षाओं को सीधे लौट रहे हैं, तो एक दृष्टिकोण जिसे मैंने उपयोगी पाया है, मेरे नियंत्रक को निम्न उपयोगिता फ़ंक्शन जोड़ना है

private void ThrowResponseException(HttpStatusCode statusCode, string message)
{
    var errorResponse = Request.CreateErrorResponse(statusCode, message);
    throw new HttpResponseException(errorResponse);
}

और इसे उचित स्थिति कोड और संदेश के साथ बस कॉल करें

Question

एएसपी.नेट वेब एपीआई में एक लेख अपवाद हैंडलिंग की समीक्षा करने के बाद, मैं एक अपवाद फेंकने के लिए एक त्रुटि प्रतिक्रिया वापस करने के लिए थोड़ा उलझन में हूँ। मैं यह भी सोच रहा हूं कि क्या आपकी विधि प्रतिक्रिया को संशोधित करना संभव है जब आपकी विधि HttpResponseMessage बजाय डोमेन विशिष्ट मॉडल लौटाती है ...

तो, यहां रिकॉर्प करने के लिए मेरे प्रश्न कुछ कोड के साथ # कोड के साथ हैं:

प्रशन

केस # 1 के संबंध में प्रश्न

  1. क्या मुझे हमेशा एक ठोस डोमेन मॉडल की बजाय HttpResponseMessage उपयोग करना चाहिए, ताकि संदेश को अनुकूलित किया जा सके?
  2. यदि आप कंक्रीट डोमेन मॉडल लौट रहे हैं तो संदेश को अनुकूलित किया जा सकता है?

केस # 2,3,4 के बारे में प्रश्न

  1. क्या मुझे अपवाद फेंकना चाहिए या त्रुटि प्रतिक्रिया वापस करनी चाहिए? अगर उत्तर "यह निर्भर करता है", तो आप एक बनाम दूसरे का उपयोग करने के लिए स्थितियों / उदाहरण दे सकते हैं।
  2. HttpResponseException बनाम Request.CreateErrorResponse फेंकने के बीच क्या अंतर है? क्लाइंट के लिए आउटपुट समान लगता है ...
  3. क्या मुझे हमेशा त्रुटियों में प्रतिक्रिया संदेशों को "लपेटने" के लिए HttpError का उपयोग करना चाहिए (चाहे अपवाद फेंक दिया गया हो या त्रुटि प्रतिक्रिया लौटाई गई हो)?

केस नमूने

// CASE #1
public Customer Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var notFoundResponse = new HttpResponseMessage(HttpStatusCode.NotFound);
        throw new HttpResponseException(notFoundResponse);
    }
    //var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    //response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return customer;
}        

// CASE #2
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var notFoundResponse = new HttpResponseMessage(HttpStatusCode.NotFound);
        throw new HttpResponseException(notFoundResponse);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

// CASE #3
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var message = String.Format("customer with id: {0} was not found", id);
        var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
        throw new HttpResponseException(errorResponse);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

// CASE #4
public HttpResponseMessage Get(string id)
{
    var customer = _customerService.GetById(id);
    if (customer == null)
    {
        var message = String.Format("customer with id: {0} was not found", id);
        var httpError = new HttpError(message);
        return Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
    }
    var response = Request.CreateResponse(HttpStatusCode.OK, customer);
    response.Content.Headers.Expires = new DateTimeOffset(DateTime.Now.AddSeconds(300));
    return response;
}

अद्यतन करें

मामलों का प्रदर्शन करने में सहायता के लिए # 2,3,4 निम्नलिखित कोड स्निपेट कई विकल्पों को हाइलाइट करता है जो "हो सकता है" जब ग्राहक नहीं मिलता है ...

if (customer == null)
{
    // which of these 4 options is the best strategy for Web API?

    // option 1 (throw)
    var notFoundMessage = new HttpResponseMessage(HttpStatusCode.NotFound);
    throw new HttpResponseException(notFoundMessage);

    // option 2 (throw w/ HttpError)
    var message = String.Format("Customer with id: {0} was not found", id);
    var httpError = new HttpError(message);
    var errorResponse = Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
    throw new HttpResponseException(errorResponse);

    // option 3 (return)
    var message = String.Format("Customer with id: {0} was not found", id);
    return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
    // option 4 (return w/ HttpError)
    var message = String.Format("Customer with id: {0} was not found", id);
    var httpError = new HttpError(message);
    return Request.CreateErrorResponse(HttpStatusCode.NotFound, httpError);
}



एक HttpResponseException को फेंक न दें या त्रुटियों के लिए HttpResponesMessage को वापस न करें - सिवाय इसके कि अगर उस सटीक परिणाम के साथ अनुरोध समाप्त करना है

HttpResponseException को अन्य अपवादों के समान नहीं माना जाता है । वे अपवाद फ़िल्टर में पकड़े नहीं जाते हैं। वे अपवाद हैंडलर में पकड़े नहीं जाते हैं। मौजूदा कोड के निष्पादन प्रवाह को समाप्त करते समय वे एक HttpResponseMessage में पर्ची करने के लिए एक स्लीप तरीका हैं।

जब तक कोड इस विशेष अन-हैंडलिंग पर निर्भर बुनियादी ढांचा कोड नहीं है, तो HttpResponseException प्रकार का उपयोग करने से बचें !

HttpResponseMessage अपवाद नहीं हैं। वे वर्तमान कोड के निष्पादन प्रवाह को समाप्त नहीं करते हैं। उन्हें अपवाद के रूप में फ़िल्टर नहीं किया जा सकता है। उन्हें अपवाद के रूप में लॉग इन नहीं किया जा सकता है। वे एक वैध परिणाम का प्रतिनिधित्व करते हैं - यहां तक ​​कि 500 ​​प्रतिक्रिया भी "एक वैध अपवाद प्रतिक्रिया" है!

जीवन को आसान बनाएं:

जब कोई असाधारण / त्रुटि मामला होता है, तो आगे बढ़ें और सामान्य अपवाद के अनुसार वांछित 'http त्रुटि / प्रतिक्रिया' गुणों के साथ एक सामान्य .NET अपवाद - या एक अनुकूलित अनुप्रयोग अपवाद प्रकार (HttpResponseException से प्राप्त नहीं ) फेंक दें। हैंडलिंग

इन असाधारण मामलों के साथ कुछ उचित करने के लिए अपवाद फ़िल्टर / अपवाद हैंडलर / अपवाद लॉगर्स का उपयोग करें: स्थिति कोड बदलें / जोड़ें? ट्रैकिंग पहचानकर्ता जोड़ें? स्टैक निशान शामिल हैं? लॉग इन करें?

HttpResponseException से परहेज करके 'असाधारण मामला' हैंडलिंग एक समान बना दिया गया है और उजागर पाइपलाइन के हिस्से के रूप में संभाला जा सकता है! उदाहरण के लिए कोई एक 404 में 'नोटफॉउंड' और 400 में 'ArgumentException' को चालू कर सकता है और एक 500 में 'नल रिफरेंस' को आसानी से और समान रूप से एप्लिकेशन-स्तरीय अपवादों के साथ-साथ "मूलभूत" जैसे त्रुटि लॉगिंग प्रदान करने की अनुमति देता है।




मैं यह इंगित करना चाहता हूं कि यह मेरा अनुभव रहा है कि यदि एक वेबपै 2 विधि में एक HttpResponseMessage को वापस करने के बजाय एक HttpResponseException फेंकना है, तो यदि आईआईएस एक्सप्रेस को तुरंत कॉल किया जाता है तो यह टाइमआउट करेगा या 200 लौटाएगा लेकिन एक HTML त्रुटि के साथ प्रतिक्रिया। इसका परीक्षण करने का सबसे आसान तरीका $ .ajax को एक विधि को कॉल करना है जो एक HttpResponseException फेंकता है और त्रुटि में AJAX में कॉलबैक किसी अन्य विधि या यहां तक ​​कि एक साधारण http पृष्ठ पर तत्काल कॉल करता है। आप देखेंगे कि imediate कॉल विफल हो जाएगा। यदि आप त्रुटि कॉल में ब्रेक पॉइंट या सेटटाउटआउट () जोड़ते हैं तो दूसरी कॉल में देरी करने के लिए सर्वर को दो या दो बार ठीक करने के लिए यह सही तरीके से काम करता है। यह तब से नहीं बनाता है, लेकिन इसके लगभग फेंकने की तरह HttpResponseException सर्वर साइड श्रोता थ्रेड को बाहर निकलने और कनेक्शन को स्वीकार करने वाले किसी भी सर्वर के विभाजित दूसरे कारण को पुनरारंभ करने का कारण बनता है।

अद्यतन: विचित्र अजाक्स कनेक्शन का मूल कारण टाइमआउट यह है कि अगर एक AJAX कॉल पर्याप्त तेज़ी से बनाया जाता है तो उसी टीसीपी कनेक्शन का उपयोग किया जाता है। मैं एक HttpResonseMessage लौटकर या HTTPResponseException को फेंक कर 401 त्रुटि ईथर उठा रहा था जिसे ब्राउज़र AJAX कॉल में वापस कर दिया गया था। लेकिन उस कॉल के साथ एमएस ऑब्जेक्ट नहीं मिला त्रुटि में लौट रहा था क्योंकि Startup.Auth.vb app.UserCookie प्रमाणीकरण सक्षम किया गया था, इसलिए यह प्रतिक्रिया को अवरुद्ध करने और रीडायरेक्ट जोड़ने की कोशिश कर रहा था, लेकिन ऑब्जेक्ट के ऑब्जेक्ट नॉट ऑब्जेक्ट के साथ इसे अनदेखा कर दिया गया। यह त्रुटि एचटीएमएल थी लेकिन तथ्य के बाद प्रतिक्रिया में जोड़ा गया था, इसलिए केवल अगर अजाक्स कॉल पर्याप्त तेज़ी से बनाया गया हो और उसी टीसीपी कनेक्शन का उपयोग किया गया तो यह ब्राउज़र पर वापस आ गया और फिर इसे अगली कॉल के सामने जोड़ा गया। किसी कारण से क्रोम बस टाइमआउट, फिडलर जेसन और एचटीएम के मिश्रण के कारण फंस गया लेकिन फ़ायरफ़ॉक्स ने वास्तविक त्रुटि को उलट दिया। तो डरावना लेकिन पैकेट स्निफर या फ़ायरफ़ॉक्स इस ट्रैक को ट्रैक करने का एकमात्र तरीका था।

यह भी ध्यान दिया जाना चाहिए कि यदि आप स्वचालित सहायता उत्पन्न करने के लिए वेब एपीआई सहायता का उपयोग कर रहे हैं और आप HttpResponseMessage को वापस कर देते हैं तो आपको एक जोड़ना चाहिए

[System.Web.Http.Description.ResponseType(typeof(CustomReturnedType))] 

विधि में विशेषता है ताकि मदद सही ढंग से उत्पन्न हो। फिर

return Request.CreateResponse<CustomReturnedType>(objCustomeReturnedType) 

या त्रुटि पर

return Request.CreateErrorResponse( System.Net.HttpStatusCode.InternalServerError, new Exception("An Error Ocurred"));

उम्मीद है कि यह किसी और को मदद करता है जो HttpResponseException फेंकने के तुरंत बाद यादृच्छिक टाइमआउट या सर्वर उपलब्ध नहीं हो सकता है।

एक HttpResponseException को लौटने के बाद भी विजुअल स्टूडियो को एक अन-हैंडल अपवाद को तोड़ने के कारण उपयोगी लाभ नहीं होता है जब त्रुटि लौटाई जाती है तो ऑथोकन को एक पृष्ठ ऐप में रीफ्रेश करने की आवश्यकता होती है।

अपडेट करें: मैं आईआईएस एक्सप्रेस टाइमिंग के बारे में अपना बयान वापस ले रहा हूं, यह मेरे क्लाइंट साइड में एक गलती हुई है, अजाक्स कॉल वापस आ गया है क्योंकि अजाक्स 1.8 $ .ajax () लौटा रहा है और $ .ajax लौटा रहा है। ()। तब () दोनों वापसी का वादा करते हैं लेकिन वही बंधे वादे नहीं करते हैं () एक नया वादा देता है जिसके कारण निष्पादन का आदेश गलत हो जाता है। तो जब तब () वादा पूरा हुआ यह एक स्क्रिप्ट टाइमआउट था। अजीब गेटचा लेकिन आईआईएस एक्सप्रेस को कीबोर्ड और कुर्सी के बीच कोई समस्या नहीं है।




त्रुटि स्थितियों में, मैं एक विशिष्ट त्रुटि विवरण वर्ग वापस करना चाहता था, क्लाइंट ने जो भी प्रारूप को खुश पथ ऑब्जेक्ट के बजाय अनुरोध किया था।

मैं अपने नियंत्रक विधियों को डोमेन विशिष्ट खुश पथ ऑब्जेक्ट वापस करना चाहता हूं और अन्यथा अपवाद फेंकना चाहता हूं।

मेरी समस्या यह थी कि HttpResponseException रचनाकार डोमेन ऑब्जेक्ट्स की अनुमति नहीं देते हैं।

अंततः मैं इसके साथ आया था

public ProviderCollection GetProviders(string providerName)
{
   try
   {
      return _providerPresenter.GetProviders(providerName);
   }
   catch (BadInputValidationException badInputValidationException)
   {
     throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.BadRequest,
                                          badInputValidationException.Result));
   }
}

Result एक वर्ग है जिसमें त्रुटि विवरण शामिल हैं, जबकि ProviderCollection मेरा खुश पथ परिणाम है।




Links