WebException làm thế nào để nhận toàn bộ phản hồi với một phần thân?


109

Trong WebException, tôi không thể thấy nội dung của GetResponse. Đây là mã của tôi trong C #:

try {                
  return GetResponse(url + "." + ext.ToString(), method, headers, bodyParams);
} catch (WebException ex) {
    switch (ex.Status) {
      case WebExceptionStatus.ConnectFailure:
         throw new ConnectionException();                        
     case WebExceptionStatus.Timeout:
         throw new RequestTimeRanOutException();                     
     case WebExceptionStatus.NameResolutionFailure:
         throw new ConnectionException();                        
     case WebExceptionStatus.ProtocolError:
          if (ex.Message == "The remote server returned an error: (401) unauthorized.") {
              throw new CredentialsOrPortalException();
          }
          throw new ProtocolErrorExecption();                    
     default:
          throw;
    }

Tôi thấy tiêu đề nhưng tôi không thấy nội dung. Đây là đầu ra từ Wireshark cho yêu cầu:

POST /api/1.0/authentication.json HTTP/1.1    
Content-Type: application/x-www-form-urlencoded    
Accept: application/json    
Host: nbm21tm1.teamlab.com    
Content-Length: 49    
Connection: Keep-Alive    

userName=XXX&password=YYYHTTP/1.1 500 Server error    
Cache-Control: private, max-age=0    
Content-Length: 106    
Content-Type: application/json; charset=UTF-8    
Server: Microsoft-IIS/7.5    
X-AspNet-Version: 2.0.50727    
X-Powered-By: ASP.NET    
X-Powered-By: ARR/2.5

Date: Mon, 06 Aug 2012 12:49:41 GMT    
Connection: close    

{"count":0,"startIndex":0,"status":1,"statusCode":500,"error":{"message":"Invalid username or password."}}

Có thể bằng cách nào đó để xem văn bản thông báo trong WebException không? Cảm ơn bạn.


Bạn đã thử (HttpWebResponse) we.Response chưa; Trường hợp 'chúng tôi' là WebException bị bắt của bạn?
Justin Harvey

2
Để bảo toàn dấu vết ngăn xếp trong ngoại lệ phát triển lại, không sử dụng throw ex;mà chỉ đơn giản throw;(trong trường hợp mặc định). Ngoài ra (nếu cần), tôi sẽ đặt WebException ban đầu trong InnerException 'tùy chỉnh của bạn (thông qua hàm tạo thích hợp).
user1713059

Câu trả lời:


202
var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();

dynamic obj = JsonConvert.DeserializeObject(resp);
var messageFromServer = obj.error.message;

8
Đối với bất kỳ ai không quen với JsonConvert, bạn cần tải Newtonsoft.Json từ trình quản lý gói nuget.
Kyle

Vui lòng cập nhật câu trả lời với lời giải thích của Kyle vì Newtonsoft.Json là optionall.
Jeroen

3
Ngoài ra, vui lòng giải thích rằng mã này phải nằm trong điều khoản Catch dự phòng của khối mã Try-Catch mà yêu cầu sẽ được thực hiện. tôi biết đối với trường hợp này đó là rõ ràng để người đọc chú ý chi trả và @iwtu, nhưng đầy đủ câu trả lời toàn diện có thể tạo sự khác biệt thực sự cho người mới bắt đầu đọc câu trả lời này;)
Jeroen

2
StreamReader triển khai IDisposable, vì vậy cách tốt nhất không phải là gói điều này trong một câu lệnh using? Xem nhanh phương pháp StreamReader Dispose cho thấy rằng nó thực hiện một số thao tác dọn dẹp quan trọng trong đó.
sammy34 Ngày

@ sammy34 Đừng lo lắng, vì không có mã / dữ liệu không được quản lý nào ở đây trong trường hợp này , Trình thu gom rác có thể xử lý nó dễ dàng ... (Nhưng sử dụng luôn là một thói quen tốt)
LB

42
try {
 WebClient client = new WebClient();
 client.Encoding = Encoding.UTF8;
 string content = client.DownloadString("https://sandiegodata.atlassian.net/wiki/pages/doaddcomment.action?pageId=524365");
 Console.WriteLine(content);
 Console.ReadKey();
} catch (WebException ex) {
 var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
 Console.WriteLine(resp);
 Console.ReadKey();
}

5

Điều này chỉ cải thiện các câu trả lời hiện có. Tôi đã viết một phương pháp xử lý các chi tiết của việc ném / ném lại bằng thông báo nâng cao, bao gồm phần nội dung phản hồi:

Đây là mã của tôi (trong Client.cs):

/// <summary>
///     Tries to rethrow the WebException with the data from the body included, if possible. 
///     Otherwise just rethrows the original message.
/// </summary>
/// <param name="wex">The web exception.</param>
/// <exception cref="WebException"></exception>
/// <remarks>
///     By default, on protocol errors, the body is not included in web exceptions. 
///     This solutions includes potentially relevant information for resolving the
///     issue.
/// </remarks>
private void ThrowWithBody(WebException wex) {
    if (wex.Status == WebExceptionStatus.ProtocolError) {
        string responseBody;
        try {
            //Get the message body for rethrow with body included
            responseBody = new StreamReader(wex.Response.GetResponseStream()).ReadToEnd();

        } catch (Exception) {
            //In case of failure to get the body just rethrow the original web exception.
            throw wex;
        }

        //include the body in the message
        throw new WebException(wex.Message + $" Response body: '{responseBody}'", wex, wex.Status, wex.Response);
    }

    //In case of non-protocol errors no body is available anyway, so just rethrow the original web exception.
    throw wex;
}

Bạn sử dụng nó trong một mệnh đề bắt giống như OP đã trình bày:

//Execute Request, catch the exception to eventually get the body
try {
    //GetResponse....
    }
} catch (WebException wex) {
    if (wex.Status == WebExceptionStatus.ProtocolError) {
        ThrowWithBody(wex);
    }

    //otherwise rethrow anyway
    throw;
}
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.