.Net HttpWebRequest.GetResponse() يثير الاستثناء عند إرجاع رمز حالة http 400 (طلب غير صالح)
-
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 الذي أرجعه.