Cách lấy thông tin lỗi khi HttpWebRequest.GetResponse () không thành công


86

Tôi đang khởi tạo HttpWebRequest và sau đó truy xuất phản hồi của nó. Đôi khi, tôi gặp lỗi 500 (hoặc ít nhất 5 ##), nhưng không có mô tả. Tôi có quyền kiểm soát cả hai điểm cuối và muốn người nhận cung cấp thêm một chút thông tin. Ví dụ, tôi muốn chuyển thông báo ngoại lệ từ máy chủ đến máy khách. Điều này có thể sử dụng HttpWebRequest và HttpWebResponse không?

Mã:

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)."
}

Đánh giá rất cao mọi sự giúp đỡ trong trường hợp này.

Câu trả lời:


151

Điều này có thể sử dụng HttpWebRequest và HttpWebResponse không?

Bạn có thể yêu cầu máy chủ web của mình chỉ cần bắt và ghi văn bản ngoại lệ vào phần nội dung của phản hồi, sau đó đặt mã trạng thái thành 500. Bây giờ máy khách sẽ đưa ra một ngoại lệ khi gặp lỗi 500 nhưng bạn có thể đọc luồng phản hồi và tìm nạp thông báo của ngoại lệ.

Vì vậy, bạn có thể bắt gặp một WebException sẽ được ném ra nếu mã trạng thái không phải 200 được trả về từ máy chủ và đọc nội dung của nó:

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
}

Cảm ơn bạn! Điều quan trọng cần lưu ý là luồng từ bên trong câu lệnh using sẽ không có sẵn bên ngoài câu lệnh using, vì trình xử lý của WebResponse sẽ xóa nó. Điều này khiến tôi vấp ngã trong vài phút.
Thorin

@Thorin. "Luồng" từ câu lệnh đầu tiên được chuyển sang câu lệnh tiếp theo. Cũng giống như trong câu lệnh IF một dòng, ví dụ if (something) do-things-here;
Thực tế: Sự cố

1
GetRequestStreamGetResponsecó thể ném các ngoại lệ ?
PreguntonCojoneroCabrón 23/03/18

@ PreguntonCojoneroCabrón Yea, nó có vẻ không đúng lắm phải không. Rất may, Microsoft đã giới thiệu lớp HttpClient mà tôi nghi ngờ hầu hết đang sử dụng những ngày này. msdn.microsoft.com/en-us/library/…
Morten Nørgaard

8

Tôi đã gặp câu hỏi này khi cố gắng kiểm tra xem tệp có tồn tại trên trang FTP hay không. Nếu tệp không tồn tại, sẽ có lỗi khi cố gắng kiểm tra dấu thời gian của tệp. Nhưng tôi muốn chắc chắn rằng lỗi không phải là một cái gì khác, bằng cách kiểm tra loại của nó.

Các Responsetài sản trên WebExceptionsẽ được loại FtpWebResponsemà bạn có thể kiểm tra nó StatusCodesở hữu để xem mà FTP lỗi mà bạn có.

Đây là mã tôi đã kết thúc với:

    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

Tôi đã đối mặt với một tình huống tương tự:

Tôi đang cố gắng đọc phản hồi thô trong trường hợp có lỗi HTTP sử dụng dịch vụ SOAP, sử dụng BasicHTTPBinding.

Tuy nhiên, khi đọc phản hồi bằng cách sử dụng GetResponseStream(), gặp lỗi:

Luồng không thể đọc được

Vì vậy, mã này đã làm việc cho tôi:

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

Bạn cũng có thể sử dụng thư viện này để gói HttpWebRequest và Response thành các phương thức đơn giản trả về các đối tượng dựa trên kết quả. Nó sử dụng một số kỹ thuật được mô tả trong các câu trả lời này và có nhiều mã lấy cảm hứng từ các câu trả lời từ chủ đề này và các chủ đề tương tự. Nó tự động nắm bắt bất kỳ ngoại lệ nào, tìm cách trừu tượng hóa càng nhiều mã đĩa của bộ nồi hơi cần thiết để thực hiện các yêu cầu web này càng tốt và tự động giải mã hóa đối tượng phản hồi.

Ví dụ về mã của bạn trông như thế nào khi sử dụng trình bao bọc này đơn giản như

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

    }

Tiết lộ đầy đủ Thư viện này là một thư viện trình bao bọc mã nguồn mở miễn phí và tôi là tác giả của thư viện nói trên. Tôi không kiếm được tiền từ việc này nhưng đã thấy nó vô cùng hữu ích trong những năm qua và chắc chắn rằng bất kỳ ai vẫn đang sử dụng các lớp HttpWebRequest / HttpWebResponse cũng sẽ như vậy.

Nó không phải là một viên đạn màu bạc nhưng hỗ trợ get, post, delete với cả async và non async cho get và post cũng như các yêu cầu và phản hồi JSON hoặc XML. Nó đang được tích cực duy trì tính đến ngày 21/6/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(); 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.