.Net HttpWebRequest.GetResponse() يثير الاستثناء عند إرجاع رمز حالة http 400 (طلب غير صالح)

StackOverflow https://stackoverflow.com/questions/692342

  •  22-08-2019
  •  | 
  •  

سؤال

أنا في موقف عندما أحصل على رمز HTTP 400 من الخادم، فهي طريقة قانونية تمامًا يخبرني بها الخادم عن الخطأ في طلبي (باستخدام رسالة في محتوى استجابة HTTP)

ومع ذلك، يثير .NET HttpWebRequest استثناءً عندما يكون رمز الحالة 400.

كيف أتعامل مع هذا؟بالنسبة لي، يعتبر 400 قانونيًا تمامًا ومفيدًا إلى حد ما.يحتوي محتوى HTTP على بعض المعلومات المهمة ولكن الاستثناء أبعدني عن المسار.

هل كانت مفيدة؟

المحلول

وسيكون من الجميل لو كانت هناك طريقة لإيقاف "رمي على كود عدم نجاح" ولكن إذا قبض 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);
                }
            }
        }
    }
}

وربما ترغب لتغليف "يحصل لي ردا حتى لو انها ليست مدونة النجاح" بت في طريقة منفصل. (فما استقاموا لكم فاستقيموا أقترح عليك لا يزال رمي إذا لم يكن هناك استجابة، على سبيل المثال، إذا كنت لا تستطيع الاتصال.)

إذا الاستجابة خطأ قد تكون كبيرة (وهو أمر غير معتاد) قد ترغب في قرص <لأ href = "https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.defaultmaximumerrorresponselength" يختلط = "noreferrer"> HttpWebRequest.DefaultMaximumErrorResponseLength للتأكد من أنك تحصل على الخطأ كله.

نصائح أخرى

أعلم أنه تمت الإجابة على هذا السؤال منذ وقت طويل، لكنني قمت بإنشاء طريقة تمديد على أمل مساعدة الأشخاص الآخرين الذين يأتون إلى هذا السؤال.

شفرة:

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);
}

ومن المثير للاهتمام أن HttpWebResponse.GetResponseStream() التي تحصل عليها من WebException.Response ليس هو نفس دفق الاستجابة الذي كنت ستتلقاه من الخادم.في بيئتنا، نفقد استجابات الخادم الفعلية عندما يكون a 400 حالة HTTP يتم إرجاع الرمز مرة أخرى إلى العميل باستخدام HttpWebRequest/HttpWebResponse أشياء.مما رأيناه، فإن تدفق الاستجابة المرتبط بـ WebException's HttpWebResponse يتم إنشاؤه لدى العميل ولا يتضمن أيًا من نص الاستجابة من الخادم.محبط للغاية، لأننا نريد أن نعيد رسالة إلى العميل عن سبب الطلب السيئ.

وكان لي قضايا مماثلة عند محاولة الاتصال لخدمة في OAuth2 جوجل.

وانتهى بي الأمر كتابة ما بعد يدويا، وعدم استخدام WebRequest، مثل هذا:

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);
}

وردا على ذلك يحصل كتابة إلى دفق استجابة تحتوي على نص الخطأ المحددة التي كنت بعد.

وعلى وجه الخصوص، وكانت مشكلتي أنني وضع endlines بين قطع البيانات المشفرة رابط. عندما أخذت بها، وعملت كل شيء. كنت قد تكون قادرة على استخدام تقنية مماثلة للاتصال خدمتكم وقراءة نص الخطأ استجابة الفعلي.

وجرب هذا (هو VB-الرمز: -):

Try

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

ونسخة غير متزامن وظيفة ملحق:

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

هذا حلها بالنسبة لي:
https://Gist.github.com/beccasaurus/929007/a8f820b153a1cfdee3d06a9c0a1d7ebfced8bb77

ليرة تركية؛دكتور:
مشكلة:
يُرجع المضيف المحلي المحتوى المتوقع، ويغير عنوان IP البعيد محتوى 400 إلى "طلب سيء"
حل:
إضافة <httpErrors existingResponse="PassThrough"></httpErrors> ل web.config/configuration/system.webServer حل هذا بالنسبة لي.الآن تعرض جميع الخوادم (المحلية والبعيدة) نفس المحتوى بالضبط (الذي أنشأته بنفسي) بغض النظر عن عنوان IP و/أو رمز HTTP الذي أرجعه.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top