Http स्थिति कोड 400 (खराब अनुरोध) वापस आने पर .Net HttpWebRequest.GetResponse () अपवाद को उठाता है


205

मैं ऐसी स्थिति में हूं जब मुझे सर्वर से HTTP 400 कोड मिलता है, यह सर्वर का पूरी तरह से कानूनी तरीका है जो मुझे बता रहा है कि मेरे अनुरोध में क्या गलत था (HTTP प्रतिक्रिया सामग्री में एक संदेश का उपयोग करके)

हालाँकि, .NET HttpWebRequest एक अपवाद उठाता है जब स्थिति कोड 400 होता है।

इससे मैं कैसे निपटूं? मेरे लिए एक 400 पूरी तरह से कानूनी है, और मददगार नहीं है। HTTP सामग्री में कुछ महत्वपूर्ण जानकारी है, लेकिन अपवाद मुझे मेरे रास्ते से निकाल देता है।


6
मैं एक ही बात का अनुभव कर रहा था। मैंने .NET फ्रेमवर्क टीम को एक सुझाव प्रस्तुत किया। इसके लिए मतदान करने के लिए स्वतंत्र महसूस करें: connect.microsoft.com/VisualStudio/feedback/details/575075/…
जोनास स्टॉवस्की

जवाबों:


344

यह अच्छा होगा यदि "गैर-सफलता कोड पर फेंक" को बंद करने के कुछ तरीके थे, लेकिन यदि आप WebException को पकड़ते हैं तो आप कम से कम प्रतिक्रिया का उपयोग कर सकते हैं:

using System;
using System.IO;
using System.Web;
using System.Net;

public class Test
{
    static void Main()
    {
        WebRequest request = WebRequest.Create("http://csharpindepth.com/asd");
        try
        {
            using (WebResponse response = request.GetResponse())
            {
                Console.WriteLine("Won't get here");
            }
        }
        catch (WebException e)
        {
            using (WebResponse response = e.Response)
            {
                HttpWebResponse httpResponse = (HttpWebResponse) response;
                Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
                using (Stream data = response.GetResponseStream())
                using (var reader = new StreamReader(data))
                {
                    string text = reader.ReadToEnd();
                    Console.WriteLine(text);
                }
            }
        }
    }
}

आप "मुझे एक प्रतिक्रिया प्राप्त करना चाहते हैं, भले ही यह एक अलग तरीके से बिट" एक प्रतिक्रिया प्राप्त करने के लिए इनकैप्सुलेट करना हो। (मेरा सुझाव है कि यदि आप कोई प्रतिक्रिया नहीं दे सकते हैं, तो यदि आप कनेक्ट नहीं कर सकते, तो आप अभी भी फेंक देंगे।)

यदि त्रुटि प्रतिक्रिया बड़ी हो सकती है (जो कि असामान्य है) तो आप HttpWebRequest.DefaultMaximumErrorResponseLengthयह सुनिश्चित करना चाहते हैं कि आपको पूरी त्रुटि मिल जाए।


5
वेबएक्ससेप्शन से जुड़ी प्रतिक्रिया पर GetResponseStream () द्वारा लौटाए गए स्ट्रीम की सामग्री केवल स्थिति कोड का नाम है (उदाहरण के लिए "खराब अनुरोध") वास्तव में सर्वर द्वारा वापस की गई प्रतिक्रिया के बजाय। क्या यह जानकारी प्राप्त करने का कोई तरीका है?
मार्क वाट

@MarkWatts: यह जो कुछ भी सर्वर द्वारा लौटाया जाना चाहिए था, और हर स्थिति में मैंने देखा है। क्या आप इसे किसी विशेष बाहरी URL के साथ पुन: उत्पन्न कर सकते हैं? मेरा सुझाव है कि आप एक नया प्रश्न पूछें (इस एक का जिक्र) और दिखा रहा है कि क्या चल रहा है।
जॉन स्कीट

यह पता चला है कि यह केवल तब करता है जब प्रतिक्रिया की सामग्री लंबाई शून्य होती है; यह HTTP स्थिति कोड का एक शाब्दिक विवरण जोड़ता है - 400 केवल "खराब अनुरोध" है, लेकिन कुछ अन्य अधिक वर्णनात्मक हैं।
मार्क वाट्स

अगर किसी को इस वर्ग के लिए एक अच्छे रैपर के बारे में पता है तो वह यहां एक लिंक छोड़ देता है। System.Net.WebClient अपवाद हैंडलिंग सिस्टम को लागू करके उसी तरह व्यवहार करता है।
जॉन के

1
@ अनकुशजैन: मेरा मानना ​​है कि यह 2XX के लिए सामान्य रूप से वापस आ जाएगा; पुनर्निर्देशन कॉन्फ़िगरेशन के आधार पर 3XX के लिए हो सकता है - मैं अपवाद के कारण कुछ और की अपेक्षा करूंगा, हालांकि मैं गलत हो सकता हूं। (4XX के लिए, यह संभव है कि यह तब सूचना को लागू करेगा यदि यह है लेकिन यह पहले से ही इसका इस्तेमाल नहीं किया है।)
जॉन स्कीट

48

मुझे पता है कि यह पहले से ही एक लंबे समय से पहले उत्तर दिया गया है, लेकिन मैंने इस सवाल पर आने वाले अन्य लोगों की उम्मीद में मदद करने के लिए एक विस्तार विधि बनाई।

कोड:

public static class WebRequestExtensions
{
    public static WebResponse GetResponseWithoutException(this WebRequest request)
    {
        if (request == null)
        {
            throw new ArgumentNullException("request");
        }

        try
        {
            return request.GetResponse();
        }
        catch (WebException e)
        {
            if (e.Response == null)
            {
                throw;
            }

            return e.Response;
        }
    }
}

उपयोग:

var request = (HttpWebRequest)WebRequest.CreateHttp("http://invalidurl.com");

//... (initialize more fields)

using (var response = (HttpWebResponse)request.GetResponseWithoutException())
{
    Console.WriteLine("I got Http Status Code: {0}", response.StatusCode);
}

2
WebException.Responseहो सकता है और हो सकता है null। यदि ऐसा है तो आपको पुनर्विचार करना चाहिए।
इयान केम्प

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

अनुरोध के लिए जाँच कर रहा है == नल वास्तव में आवश्यक है? चूंकि यह एक विस्तार विधि है, इसलिए इसे अशक्त ऑब्जेक्ट पर उपयोग करने का प्रयास करने से पहले एक शून्य संदर्भ अपवाद को फेंक देना चाहिए इससे पहले कि वह एक्सटेंशन विधि कोड को हिट करे ...... सही?
kwill

@kwill एक्सटेंशन विधियां केवल स्थिर विधियां हैं, भ्रम से बचने के लिए उचित इनपुट सत्यापन करना चाहिए, खासकर जब वे एक्सटेंशन विधि सिंटैक्स के साथ लागू नहीं होते हैं। इसके अलावा, यह .NET टीमों द्वारा किया गया सुसंगत दृष्टिकोण है: github.com/dotnet/corefx/blob/…
मैथ्यू

1
क्षमा करें, मैंने आपके दूसरे प्रश्न को गलत समझा। ((WebRequest) null).GetResponseWithoutException()वास्तव में इसका कारण नहीं होगा NullReferenceException, क्योंकि यह इसके समकक्ष संकलित है WebRequestExtensions.GetResponseWithoutException(null), जिसके परिणामस्वरूप परिणाम नहीं होगा NullReferenceException, इसलिए इनपुट सत्यापन की आवश्यकता है।
मैथ्यू

13

दिलचस्प बात यह है HttpWebResponse.GetResponseStream()कि जो आपको मिलता है , वह उस WebException.Responseप्रतिक्रिया स्ट्रीम के समान नहीं है जो आपको सर्वर से मिली होगी। हमारे वातावरण में, जब हम एक 400 HTTP स्टेटस कोड HttpWebRequest/HttpWebResponseवस्तुओं का उपयोग करके क्लाइंट को वापस लौटाते हैं, तो हम वास्तविक सर्वर प्रतिक्रियाओं को खो देते हैं । हमने जो देखा है, उससे WebException's HttpWebResponseक्लाइंट के साथ जुड़े रिस्पांस स्ट्रीम जेनरेट होता है और सर्वर से कोई भी रिस्पॉन्स बॉडी शामिल नहीं होती है। बहुत निराशा होती है, क्योंकि हम ग्राहक को खराब अनुरोध के कारण वापस संदेश देना चाहते हैं।


मैं विधि हेड का उपयोग करता हूं और इस अपवाद का कारण बनता हूं लेकिन जब जीईटी का उपयोग करता है तो कोई समस्या नहीं होती है। क्या वास्तव में HEAD विधि के साथ समस्या है?
मोहम्मद अफ़राशते

12

Google की OAuth2 सेवा से जुड़ने का प्रयास करते समय मेरे पास समान मुद्दे थे।

मैंने इस तरह से, WebRequest का उपयोग न करके मैन्युअल रूप से POST लिखना समाप्त कर दिया:

TcpClient client = new TcpClient("accounts.google.com", 443);
Stream netStream = client.GetStream();
SslStream sslStream = new SslStream(netStream);
sslStream.AuthenticateAsClient("accounts.google.com");

{
    byte[] contentAsBytes = Encoding.ASCII.GetBytes(content.ToString());

    StringBuilder msg = new StringBuilder();
    msg.AppendLine("POST /o/oauth2/token HTTP/1.1");
    msg.AppendLine("Host: accounts.google.com");
    msg.AppendLine("Content-Type: application/x-www-form-urlencoded");
    msg.AppendLine("Content-Length: " + contentAsBytes.Length.ToString());
    msg.AppendLine("");
    Debug.WriteLine("Request");
    Debug.WriteLine(msg.ToString());
    Debug.WriteLine(content.ToString());

    byte[] headerAsBytes = Encoding.ASCII.GetBytes(msg.ToString());
    sslStream.Write(headerAsBytes);
    sslStream.Write(contentAsBytes);
}

Debug.WriteLine("Response");

StreamReader reader = new StreamReader(sslStream);
while (true)
{  // Print the response line by line to the debug stream for inspection.
    string line = reader.ReadLine();
    if (line == null) break;
    Debug.WriteLine(line);
}

प्रतिक्रिया स्ट्रीम को लिखी जाने वाली प्रतिक्रिया में विशिष्ट त्रुटि पाठ होता है जो आपके बाद होता है।

विशेष रूप से, मेरी समस्या यह थी कि मैं url- एन्कोडेड डेटा टुकड़ों के बीच एंडलाइंस डाल रहा था। जब मैंने उन्हें बाहर निकाला, तो सब कुछ काम कर गया। आप अपनी सेवा से जुड़ने और वास्तविक प्रतिक्रिया त्रुटि पाठ को पढ़ने के लिए एक समान तकनीक का उपयोग करने में सक्षम हो सकते हैं।


2
HttpWebRequest इतना गड़बड़ है। यहां तक ​​कि सॉकेट आसान हैं (coz वे त्रुटियों को आपसे दूर नहीं छिपाते हैं)।
Agent_L

6

इसे आज़माएं (यह VB- कोड :-) है:

Try

Catch exp As WebException
  Dim sResponse As String = New StreamReader(exp.Response.GetResponseStream()).ReadToEnd
End Try

3

विस्तार समारोह का एक अतुल्यकालिक संस्करण:

    public static async Task<WebResponse> GetResponseAsyncNoEx(this WebRequest request)
    {
        try
        {
            return await request.GetResponseAsync();
        }
        catch(WebException ex)
        {
            return ex.Response;
        }
    }

0

इसने मेरे लिए इसे हल किया:
https://gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77

टी एल; डॉ:
समस्या:
स्थानीय होस्ट रिटर्न की उम्मीद सामग्री, दूरदराज के आईपी बदलती जाती है "गलत अनुरोध" करने के लिए 400 सामग्री
समाधान:
जोड़ने <httpErrors existingResponse="PassThrough"></httpErrors>के लिए web.config/configuration/system.webServerमेरे लिए यह हल; अब सभी सर्वर (स्थानीय और दूरस्थ) आईपी पते और / या HTTP कोड की परवाह किए बिना सटीक एक ही सामग्री (मेरे द्वारा उत्पन्न) लौटाते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.