Як отримати інформацію про помилку, коли HttpWebRequest.GetResponse () не вдається


86

Я ініціюю HttpWebRequest, а потім отримую його відповідь. Іноді я отримую помилку 500 (або принаймні 5 ##), але без опису. Я контролюю обидві кінцеві точки і хотів би, щоб кінець, що отримує, отримав трохи більше інформації. Наприклад, я хотів би передати повідомлення про виняток із сервера на клієнт. Чи можливо це за допомогою HttpWebRequest та HttpWebResponse?

Код:

try
{
    HttpWebRequest webRequest = HttpWebRequest.Create(URL) as HttpWebRequest;
    webRequest.Method = WebRequestMethods.Http.Get;
    webRequest.Credentials = new NetworkCredential(Username, Password);
    webRequest.ContentType = "application/x-www-form-urlencoded";
    using(HttpWebResponse response = webRequest.GetResponse() as HttpWebResponse)
    {
        if(response.StatusCode == HttpStatusCode.OK)
        {
            // Do stuff with response.GetResponseStream();
        }
    }
}
catch(Exception ex)
{
    ShowError(ex);
    // if the server returns a 500 error than the webRequest.GetResponse() method
    // throws an exception and all I get is "The remote server returned an error: (500)."
}

Будь-яка допомога з цим буде дуже вдячна.

Відповіді:


151

Чи можливо це за допомогою HttpWebRequest та HttpWebResponse?

Ви могли б зробити так, щоб ваш веб-сервер просто ловив і писав текст винятку в тілі відповіді, а потім встановлював код стану на 500. Тепер клієнт видасть виняток, коли виявить помилку 500, але ви можете прочитати потік відповідей і отримати повідомлення про виключення.

Таким чином, ви можете зловити WebException, який буде видано, якщо код сервера, який не має 200, буде повернутий із сервера та прочитає його тіло:

catch (WebException ex)
{
    using (var stream = ex.Response.GetResponseStream())
    using (var reader = new StreamReader(stream))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
}
catch (Exception ex)
{
    // Something more serious happened
    // like for example you don't have network access
    // we cannot talk about a server exception here as
    // the server probably was never reached
}

Дякую! Важливо зауважити, що потік усередині оператора using не буде доступний поза оператором using, оскільки розпорядник WebResponse очистить його. Це спокусило мене на кілька хвилин.
Торін,

@Thorin. "Потік" від першого твердження переходить до наступного. Так само, як в однорядковому твердженні IF, наприклад if (something) do-stuff-here;
RealityDysfunction 01

1
GetRequestStreamа GetResponseможе кинути винятки ?
PreguntonCojoneroCabrón

@ PreguntonCojoneroCabrón Так, здається, це не зовсім правильно, правда. На щастя, Microsoft представила клас HttpClient, яким, на мою думку, більшість зараз користуються. msdn.microsoft.com/en-us/library/…
Мортен Норгаард

8

Я зіткнувся з цим запитанням, намагаючись перевірити, чи існує файл на FTP-сайті чи ні. Якщо файл не існує, буде помилка при спробі перевірити його позначку часу. Але я хочу переконатися, що помилка не є чимось іншим, перевіривши її тип.

ResponseВласності на WebExceptionматиме тип , FtpWebResponseна якому ви можете перевірити його StatusCodeвластивості , щоб побачити , який FTP помилка у вас є.

Ось код, з яким я опинився:

    public static bool FileExists(string host, string username, string password, string filename)
    {
        // create FTP request
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://" + host + "/" + filename);
        request.Credentials = new NetworkCredential(username, password);

        // we want to get date stamp - to see if the file exists
        request.Method = WebRequestMethods.Ftp.GetDateTimestamp;

        try
        {
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            var lastModified = response.LastModified;

            // if we get the last modified date then the file exists
            return true;
        }
        catch (WebException ex)
        {
            var ftpResponse = (FtpWebResponse)ex.Response;

            // if the status code is 'file unavailable' then the file doesn't exist
            // may be different depending upon FTP server software
            if (ftpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
            {
                return false;
            }

            // some other error - like maybe internet is down
            throw;
        }
    }

4

Я зіткнувся з подібною ситуацією:

Я намагався прочитати необроблену відповідь у випадку помилки HTTP, яка споживає послугу SOAP, використовуючи BasicHTTPBinding.

Однак при читанні відповіді з використанням GetResponseStream()з'явилася помилка:

Потік не читається

Отже, цей код працював для мене:

try
{
    response = basicHTTPBindingClient.CallOperation(request);
}
catch (ProtocolException exception)
{
    var webException = exception.InnerException as WebException;
    var rawResponse = string.Empty;

    var alreadyClosedStream = webException.Response.GetResponseStream() as MemoryStream;
    using (var brandNewStream = new MemoryStream(alreadyClosedStream.ToArray()))
    using (var reader = new StreamReader(brandNewStream))
        rawResponse = reader.ReadToEnd();
}

0

Ви також можете використовувати цю бібліотеку, яка обертає HttpWebRequest та Response у прості методи, які повертають об'єкти на основі результатів. Він використовує деякі методи, описані в цих відповідях, і має безліч коду, натхненного відповідями з цієї та подібних тем. Він автоматично вловлює будь-які винятки, прагне абстрагувати якомога більше кодової таблички, необхідної для здійснення цих веб-запитів, і автоматично десеріалізує об'єкт відповіді.

Приклад того, як би виглядав ваш код за допомогою цієї обгортки, простий

    var response = httpClient.Get<SomeResponseObject>(request);
    
    if(response.StatusCode == HttpStatusCode.OK)
    {
        //do something with the response
        console.Writeline(response.Body.Id); //where the body param matches the object you pass in as an anonymous type.  
    }else {
         //do something with the error
         console.Writelint(string.Format("{0}: {1}", response.StatusCode.ToString(), response.ErrorMessage);

    }

Повне розкриття інформації Ця бібліотека є безкоштовною бібліотекою обгортки з відкритим кодом, і я є автором цієї бібліотеки. Я на цьому не заробляю грошей, але протягом багатьох років вважаю це надзвичайно корисним, і впевнений, що той, хто все ще використовує класи HttpWebRequest / HttpWebResponse, теж буде.

Це не срібний маркер, але підтримує отримання, розміщення, видалення як з асинхронізацією, так і з несинхронізацією для отримання та публікації, а також запити та відповіді JSON або XML. Він активно підтримується станом на 21.06.2020


-3
HttpWebRequest myHttprequest = null;
HttpWebResponse myHttpresponse = null;
myHttpRequest = (HttpWebRequest)WebRequest.Create(URL);
myHttpRequest.Method = "POST";
myHttpRequest.ContentType = "application/x-www-form-urlencoded";
myHttpRequest.ContentLength = urinfo.Length;
StreamWriter writer = new StreamWriter(myHttprequest.GetRequestStream());
writer.Write(urinfo);
writer.Close();
myHttpresponse = (HttpWebResponse)myHttpRequest.GetResponse();
if (myHttpresponse.StatusCode == HttpStatusCode.OK)
 {
   //Perform necessary action based on response
 }
myHttpresponse.Close(); 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.