Mã trạng thái HTTP System.Net.WebException


Câu trả lời:


248

Có lẽ một cái gì đó như thế này ...

try
{
    // ...
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError)
    {
        var response = ex.Response as HttpWebResponse;
        if (response != null)
        {
            Console.WriteLine("HTTP Status Code: " + (int)response.StatusCode);
        }
        else
        {
            // no http status code available
        }
    }
    else
    {
        // no http status code available
    }
}

nhưng trong trường hợp "kết nối ngoại lệ" ngoại trừ webexception tôi nhận được phản hồi là null, trong trường hợp đó làm thế nào tôi có thể nhận được mã httpstatus
Rusty

8
@rusty: Bạn không thể. Nếu có lỗi kết nối thì sẽ không có mã trạng thái HTTP.
LukeH

4
Nếu lỗi là ProtocolError, bạn không phải kiểm tra phản hồi cho null. Xem bình luận trong ví dụ trên trang MSDN này
Andras Toth

5
@AndrasToth Nhưng các công cụ như ReSharper sẽ đưa ra cảnh báo nếu bạn bỏ qua kiểm tra null. Và trong mọi trường hợp, đó là cách thực hành tốt để viết mã phòng thủ.
Tom Lint

1
Làm thế nào để có được giá trị HTTP Substatus ? Ví dụ: 404.13 Độ dài nội dung Tham chiếu quá lớn : docs.microsoft.com/en-us/iis/configuration/system.webServer/ Kẻ
Kiquenet 23/03/18

27

Bằng cách sử dụng toán tử có điều kiện null ( ?.), bạn có thể nhận được mã trạng thái HTTP với một dòng mã:

 HttpStatusCode? status = (ex.Response as HttpWebResponse)?.StatusCode;

Biến statussẽ chứa HttpStatusCode. Khi có một lỗi chung hơn như lỗi mạng trong đó không có mã trạng thái HTTP nào được gửi thì statussẽ không có giá trị. Trong trường hợp đó bạn có thể kiểm tra ex.Statusđể có được WebExceptionStatus.

Nếu bạn chỉ muốn một chuỗi mô tả đăng nhập trong trường hợp thất bại, bạn có thể sử dụng toán tử hợp nhất null ( ??) để nhận lỗi liên quan:

string status = (ex.Response as HttpWebResponse)?.StatusCode.ToString()
    ?? ex.Status.ToString();

Nếu ngoại lệ được ném do kết quả của mã trạng thái HTTP HTTP, chuỗi sẽ chứa "NotFound". Mặt khác, nếu máy chủ ngoại tuyến, chuỗi sẽ chứa "ConnectFailure", v.v.

(Và đối với bất kỳ ai muốn biết cách lấy mã thế hệ HTTP. Điều đó là không thể. Đây là một khái niệm Microsoft IIS chỉ được ghi lại trên máy chủ và không bao giờ được gửi cho khách hàng.)


Không chắc chắn rằng ?.toán tử ban đầu được đặt tên là toán tử lan truyền null hoặc toán tử có điều kiện null trong khi phát hành bản xem trước. Nhưng chia sẻ lại Atlassian đưa ra một cảnh báo để sử dụng toán tử lan truyền null trong các tình huống như vậy. Rất vui khi biết rằng nó cũng được gọi là toán tử có điều kiện null.
RBT

1
Một chút muộn cho bên này, nhưng cảnh báo công bằng rằng toán tử có điều kiện null là một tính năng C # 6.0, vì vậy một người cần phải sử dụng một trình biên dịch hỗ trợ nó. Stack Overflow trả lời với các chi tiết khác . VS 2015+ có mặc định, nhưng nếu một người đang sử dụng bất kỳ loại môi trường xây dựng / triển khai nào ngoài "máy của họ", những thứ khác có thể cần được xem xét.
CodeHxr

9

điều này chỉ hoạt động nếu WebResponse là một httpWebResponse.

try
{
    ...
}
catch (System.Net.WebException exc)
{
    var webResponse = exc.Response as System.Net.HttpWebResponse;
    if (webResponse != null && 
        webResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized)
    {
        MessageBox.Show("401");
    }
    else
        throw;
}

tại sao chỉ xử lý với 401-Không được phép thay vì tất cả các mã trạng thái lỗi HTTP có thể? đây là câu trả lời tồi tệ nhất
ympostor

4
@ympostor Đây chỉ là một ví dụ. Bất kỳ nhà phát triển hợp lý đều hiểu điều này. Nhận xét của bạn là thiếu suy nghĩ nhất mà tôi từng đọc ở đây.
pr0gg3r

9

(Tôi nhận ra câu hỏi đã cũ, nhưng đây là một trong những lượt truy cập hàng đầu trên Google.)

Một tình huống phổ biến mà bạn muốn biết mã phản hồi là xử lý ngoại lệ. Kể từ C # 7, bạn có thể sử dụng khớp mẫu để thực sự chỉ nhập mệnh đề bắt nếu ngoại lệ khớp với vị từ của bạn:

catch (WebException ex) when (ex.Response is HttpWebResponse response)
{
     doSomething(response.StatusCode)
}

Điều này có thể dễ dàng được mở rộng đến các cấp độ khác, chẳng hạn như trong trường hợp WebExceptionnày thực sự là ngoại lệ bên trong của một cấp độ khác (và chúng tôi chỉ quan tâm đến 404):

catch (StorageException ex) when (ex.InnerException is WebException wex && wex.Response is HttpWebResponse r && r.StatusCode == HttpStatusCode.NotFound)

Cuối cùng: lưu ý làm thế nào không cần phải ném lại ngoại lệ trong mệnh đề bắt khi nó không phù hợp với tiêu chí của bạn, vì chúng tôi không nhập mệnh đề ở vị trí đầu tiên với giải pháp trên.


4

Bạn có thể thử mã này để lấy mã trạng thái HTTP từ WebException. Nó cũng hoạt động trong Silverlight vì SL không có WebExceptionStatus.ProtocolError được xác định.

HttpStatusCode GetHttpStatusCode(WebException we)
{
    if (we.Response is HttpWebResponse)
    {
        HttpWebResponse response = (HttpWebResponse)we.Response;
        return response.StatusCode;
    }
    return null;
}

1
return 0? hoặc tốt hơn HttpStatusCode?( nullable )?
Kiquenet

Điều này sẽ làm việc? var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}
FMFF

Tôi không thể hiểu những gì bạn muốn làm trong mẫu này. Trong trường hợp bạn muốn sự kiện được đăng nhập?
Serge

1

Tôi không chắc có nếu có nhưng nếu có một tài sản như vậy thì nó sẽ không được coi là đáng tin cậy. A WebExceptioncó thể bị loại vì các lý do khác với mã lỗi HTTP bao gồm các lỗi mạng đơn giản. Những người không có mã lỗi http phù hợp như vậy.

Bạn có thể cho chúng tôi thêm một chút thông tin về những gì bạn đang cố gắng thực hiện với mã đó không. Có thể có một cách tốt hơn để có được thông tin bạn cần.

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.