Làm cách nào để lấy Mã trạng thái từ HttpRequestException?


87

Tôi có lẽ đang thiếu một cái gì đó rõ ràng ở đây.

Tôi đang sử dụng HttpClientném HttpRequestExceptionnào có chứa StatusCodetrong chuỗi Thông báo.

Làm thế nào tôi có thể truy cập nó StatusCode?


Chỉnh sửa : Thêm thông tin, tôi đã viết câu hỏi này vội vàng.

Tôi đang sử dụng HttpClientđể truy cập một API khác trong dự án WebApi của mình. Vâng, tôi biết tại sao tôi đang gọi EnsureSuccessStatusCode(). Tôi muốn phổ biến một số lỗi xuống phía dưới như 404 và 403.

Tất cả những gì tôi muốn là liên tục chuyển đổi HttpRequestExceptionthành HttpResponseExceptionsử dụng tùy chỉnh ExceptionFilterAttribute.

Thật không may, HttpRequestExceptionkhông mang theo bất kỳ thông tin bổ sung nào mà tôi có thể sử dụng ngoài tin nhắn. Tôi đã hy vọng phát hiện ra StatusCodeở dạng thô (int hoặc enum).

Có vẻ như tôi có thể:

  1. Sử dụng tin nhắn để chuyển mã trạng thái (bleh)
  2. Hoặc tạo phiên bản EnsureSuccessStatusCode của tôi và đưa ra ngoại lệ thực sự có thể sử dụng được.

1
Bạn có thể hiển thị một đoạn mã?
Hamlet Hakobyan

1
Bạn có nghĩa là gì khi "truy cập mã trạng thái đó"?
Marco

Hiển thị mã cho biết bạn đang nhận được ngoại lệ ở đâu.
Đan Mạch

5
Các bạn có gì không rõ về tiêu đề của câu hỏi này?
Kugel

1
Bạn đã tìm ra giải pháp thích hợp nào cho vấn đề này chưa? hãy chia sẻ
Siddharth Pandey

Câu trả lời:


37

Mã trạng thái đã được chuyển như một phần của chuỗi để HttpRequestExceptionbạn không thể khôi phục nó khỏi các trường hợp ngoại lệ như vậy.

Thiết kế của System.Net.Httpyêu cầu bạn truy cập HttpResponseMessage.StatusCodethay vì chờ đợi ngoại lệ.

http://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage(v=vs.110).aspx

Nếu bây giờ bạn đang làm theo hướng dẫn của Microsoft , hãy đảm bảo rằng bạn hiểu rõ ràng lý do tại sao nó yêu cầu bạn gọi HttpResponseMessage.EnsureSucessStatusCode. Nếu bạn không gọi hàm đó, sẽ không có ngoại lệ.


2
Tôi đang cố gắng giải quyết mối quan tâm xuyên suốt ở đây. Nhìn vào bản chỉnh sửa của tôi, có lẽ có một giải pháp tốt hơn.
Kugel

1
Điều này có phù hợp với việc sử dụng HttpClient.GetStreamAsync (url) vì tôi không thể thấy cách thực hiện hành động này mà không cần phải loại bỏ nội dung thư không?
The Senator

1
@TheSenator Bạn phải gọi GetAsync (uri) hoặc PostAsync (uri) để lấy lại HttpResponseMessage. Nếu bạn cố gắng và nhận được nội dung của phản hồi bằng cách đọc nó hoặc sử dụng một phương pháp tiện lợi như GetStreamAsync, thì EnsureSuccessStatusCode được gọi là ẩn.
odyth

6
Điều này đặt ra câu hỏi rõ ràng là điểm nào của các phương thức tiện lợi hiện có ở tất cả nếu chúng ném ra các ngoại lệ không giúp bạn có thể xử lý lỗi một cách hữu ích. Rải mã của bạn với các câu lệnh if và throw không phải là giải pháp, vì vậy từ những gì đã nói ở đây, câu trả lời chính xác hiện tại là bạn phải tự thực hiện lại các phương pháp tiện lợi hoặc EnsureSuccessStatusCode.
Neutrino

1
Điều đó nói dễ hơn là làm. Ngoại lệ có thể được ném từ mã của bên thứ ba. Ví dụ: ứng dụng swagger được tạo tự động.
dùng2555515

27

Đối với giá trị của nó, anh chàng này đã làm điều gì đó thông minh: https://social.msdn.microsoft.com/Forums/vstudio/en-US/dc9bc426-1654-4319-a7fb-383f00b68def/c-httpresponsemessage-throws-exception-httprequestexception -webexception-the-remote-name? forum = csharpgeneral

Trong trường hợp tôi cần một thuộc tính trạng thái ngoại lệ, tôi có thể thực hiện việc này:

catch (HttpRequestException requestException)
{
    if (requestException.InnerException is WebException webException && webException.Status == WebExceptionStatus.NameResolutionFailure)
    {
        return true;
    }

    return false;
}

14
được bình chọn cao vì đôi khi bạn không có quyền truy cập vào câu trả lời, chẳng hạn như khi bạn buộc phải sử dụng một thư viện bao gồm chức năng và đưa ra bất kỳ ngoại lệ nào.
Kell

4
.net core 2.1 HttpClient có GetAsync () và GetStreamAsync (). Đầu tiên sẽ trả về một phản hồi trong khi cái kia sẽ gọi EnsureSucessStatusCode nội bộ và ném một HttpRequestException. Tôi không hiểu sự không nhất quán và nó làm cho việc xử lý lỗi trở nên khó khăn, nhưng tôi đánh giá cao cách giải quyết này.
smurtagh

2
Đang chạy .NET Core 3.1.5, requestException.InnerExceptionlà null nên điều này sẽ không hoạt động
Ohad Schneider

3

Như đã đề cập bởi những người khác cũng không phải là một phương pháp hay để lấy StatusCode từ HttpRequestException, điều tương tự có thể được thực hiện trước với HttpResponseMessage.StatusCode sau khi kiểm tra HttpResponseMessage.IsSuccessStatusCode

Nhưng dù sao nếu do một số ràng buộc / yêu cầu người ta phải đọc Mã trạng thái, Có thể có hai giải pháp

  1. Đã mở rộng HttpResponseMessage với ngoại lệ tùy chỉnh của bạn được giải thích tại đây
  2. Hack trên HttpRequestException.ToString để lấy StatusCode, Vì thông báo là một bài đăng liên tục được sửa bởi StatusCode và Repharse.

Dưới đây là mã trong System.Net.Http.HttpResponseMessage Nơi SR.net_http_message_not_success_statuscode = "Mã trạng thái phản hồi không cho biết thành công: {0} ({1})."

public HttpResponseMessage EnsureSuccessStatusCode()
    {
        if (!this.IsSuccessStatusCode)
        {
            if (this.content != null)
            {
                this.content.Dispose();
            }
            throw new HttpRequestException(string.Format(CultureInfo.InvariantCulture, SR.net_http_message_not_success_statuscode, new object[]
            {
                (int)this.statusCode,
                this.ReasonPhrase
            }));
        }
        return this;
    }

4
chuỗi lỗi với một định dạng cụ thể là một mùi mã, logic không bao giờ được phụ thuộc vào chúng.
user1496062,

1
@ user1496062 Khi lỗi đến từ hệ thống bên ngoài, thường không có giải pháp thay thế.
Ian Warburton

1

Điều này đã làm việc cho tôi

var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
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.