Kiểm tra xem HttpStatusCode biểu thị thành công hay thất bại


93

Giả sử tôi có biến sau:

System.Net.HttpStatusCode status = System.Net.HttpStatusCode.OK;

Làm cách nào để kiểm tra xem đây là mã trạng thái thành công hay thất bại?

Ví dụ, tôi có thể làm như sau:

int code = (int)status;
if(code >= 200 && code < 300) {
    //Success
}

Tôi cũng có thể có một số loại danh sách trắng:

HttpStatusCode[] successStatus = new HttpStatusCode[] {
     HttpStatusCode.OK,
     HttpStatusCode.Created,
     HttpStatusCode.Accepted,
     HttpStatusCode.NonAuthoritativeInformation,
     HttpStatusCode.NoContent,
     HttpStatusCode.ResetContent,
     HttpStatusCode.PartialContent
};
if(successStatus.Contains(status)) //LINQ
{
    //Success
}

Không có lựa chọn thay thế nào thuyết phục tôi và tôi đã hy vọng vào một lớp hoặc phương thức .NET có thể thực hiện công việc này cho tôi, chẳng hạn như:

bool isSuccess = HttpUtilities.IsSuccess(status);

bạn cần làm int code = (int)Response.StatusCodetừ đó, bạn sẽ cần tạo Enumséc của riêng mình ở đây để xem ví dụ hoạt động stackoverflow.com/questions/1330856/…
MethodMan 14/09

Bạn có tình cờ sử dụng HttpClientlớp học không?
dcastro

1
@dcastro Không, tôi xin lỗi. Tôi đang sử dụng API cấp cao có thể (hoặc không) sử dụng nó trong nội bộ. API cho thấy mã trạng thái của phản ứng, nhưng không lộ ra bên trong HttpResponseMessageví dụ
Matias Cicero

@MatiCicero Thật quá tệ: / Bạn luôn có thể sử dụng lại việc triển khai HttpResponseMessage.IsSuccessStatusCode(xem câu trả lời của tôi) giống hệt như cách tiếp cận đầu tiên của bạn và biến nó thành một phương thức mở rộng trên HttpStatusCodeloại.
dcastro 14/09/15

Câu trả lời:


173

Nếu bạn đang sử dụng HttpClientlớp học, thì bạn sẽ nhận được lợi HttpResponseMessagenhuận.

Lớp này có một thuộc tính hữu ích được gọi là IsSuccessStatusCodesẽ thực hiện việc kiểm tra cho bạn.

using (var client = new HttpClient())
{
    var response = await client.PostAsync(uri, content);
    if (response.IsSuccessStatusCode)
    {
        //...
    }
}

Trong trường hợp bạn tò mò, thuộc tính này được triển khai như sau:

public bool IsSuccessStatusCode
{
    get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); }
}

Vì vậy, bạn chỉ có thể sử dụng lại thuật toán này nếu bạn không sử dụng HttpClienttrực tiếp.

Bạn cũng có thể sử dụng EnsureSuccessStatusCodeđể đưa ra một ngoại lệ trong trường hợp phản hồi không thành công.


FYI: Đối với tôi là 'phản hồi. Thành công'.
Topher Birth

Câu trả lời của bạn khá hữu ích nhưng bây giờ nó hoạt động như sau: if (response.IsCompletedSuccessful) {//}
salman

12

Lớp HttpResponseMessage có thuộc tính IsSuccessStatusCode, nhìn vào mã nguồn thì nó giống như thế này, như usr đã đề xuất 200-299 có lẽ là tốt nhất bạn có thể làm.

public bool IsSuccessStatusCode
{
    get { return ((int)statusCode >= 200) && ((int)statusCode <= 299); }
}

11

Câu trả lời được chấp nhận làm tôi hơi phiền vì nó có chứa những con số ma thuật, (mặc dù chúng là tiêu chuẩn) trong phần thứ hai của nó. Và phần đầu tiên không chung chung cho các mã trạng thái số nguyên thuần túy, mặc dù nó gần với câu trả lời của tôi.

Bạn có thể đạt được kết quả chính xác như vậy bằng cách tạo HttpResponseMessage với mã trạng thái của bạn và kiểm tra xem có thành công hay không. Nó ném ra một ngoại lệ đối số nếu giá trị nhỏ hơn 0 hoặc lớn hơn 999.

if (new HttpResponseMessage((HttpStatusCode)statusCode).IsSuccessStatusCode)
{
    // ...
}

Điều này không chính xác ngắn gọn, nhưng bạn có thể biến nó thành một phần mở rộng.


Điều này hoạt động hoàn hảo đối với tôi vì tôi chỉ có Mã HttpStatusCode chứ không phải thông báo Phản hồi. Làm tốt lắm!
Todd Vance

5
"Câu trả lời được chấp nhận làm tôi hơi phiền vì nó chứa những con số ma thuật, (mặc dù chúng ở mức tiêu chuẩn)" - Chúng không phải là "phép thuật" nếu chúng được tiêu chuẩn hóa, hiểu rõ và không bao giờ thay đổi. Hoàn toàn không có gì sai khi sử dụng các mã trực tiếp. Nếu bạn có IsSuccessStatusCodesau đó tuyệt vời, sử dụng nó (như câu trả lời được chấp nhận nói tới.) Nếu không, không thêm cruft của riêng bạn bằng cách sử dụng một sự trừu tượng, trừ khi bạn đang thực hiện việc kiểm tra này ở khắp mọi nơi
Ed S.

1
Hãy nhớ rằng việc khởi tạo HttpResponseMessageđể sử dụng một trong các thuộc tính của nó mất nhiều thời gian hơn so với việc kiểm tra hai điều kiện logic với int.
Miro J.

10

Thêm vào câu trả lời @TomDoesCode Nếu bạn đang sử dụng HttpWebResponse, bạn có thể thêm phương thức mở rộng này:

public static bool IsSuccessStatusCode(this HttpWebResponse httpWebResponse)
{
    return ((int)httpWebResponse.StatusCode >= 200) && ((int)httpWebResponse.StatusCode <= 299);
}

8

Tôi phụ thuộc vào khả năng khám phá của các phương pháp mở rộng.

public static class HttpStatusCodeExtensions
{
    public static bool IsSuccessStatusCode(this HttpStatusCode statusCode)
    {
        var asInt = (int)statusCode;
        return asInt >= 200 && asInt <= 299;
    }
}

Miễn là không gian tên của bạn còn trong phạm vi, thì việc sử dụng sẽ được statusCode.IsSuccessStatusCode().


2
bạn có thể muốn asInt> = 200 ở đó
Jim O'Neil

Các phương thức mở rộng rất thú vị, nhưng tôi bối rối - điều này không hoạt động tương tự như thuộc tính IsSuccessStatusCode của HTTPResponseMessage được sử dụng với HTTPClient hoặc IHTTPClientFactory? @DCastro thậm chí còn cho chúng ta thấy rằng nó được triển khai chính xác như thế này trong .NET. Khi nào / tại sao tôi sử dụng phương thức mở rộng như thế này cho Mã trạng thái HTTP trong phạm vi 2xx?
sfors nói Khôi phục Monica

4
@sfors, vâng, nhưng nếu bạn chỉ có HttpStatusCodetrong phạm vi thì sao? Có rất nhiều thư viện không sử dụng hoặc hiển thị HttpResponseMessagenhưng cung cấp cho bạn mã trạng thái.
bojingo

3

Nó phụ thuộc vào tài nguyên HTTP bạn đang gọi. Thông thường, 2xxphạm vi được xác định là phạm vi của mã trạng thái thành công. Đó rõ ràng là một quy ước mà không phải máy chủ HTTP nào cũng tuân thủ.

Ví dụ: gửi biểu mẫu trên một trang web thường sẽ trả lại chuyển hướng 302.

Nếu bạn muốn nghĩ ra một phương pháp chung thì code >= 200 && code < 300ý tưởng đó có lẽ là cách tốt nhất của bạn.

Nếu bạn đang gọi máy chủ của mình thì có lẽ bạn nên đảm bảo rằng bạn đã chuẩn hóa 200.


2

Đây là phần mở rộng của câu trả lời trước đó, tránh việc tạo và thu thập rác tiếp theo của một đối tượng mới cho mỗi lời gọi.

public static class StatusCodeExtensions
{
    private static readonly ConcurrentDictionary<HttpStatusCode, bool> IsSuccessStatusCode = new ConcurrentDictionary<HttpStatusCode, bool>();
    public static bool IsSuccess(this HttpStatusCode statusCode) => IsSuccessStatusCode.GetOrAdd(statusCode, c => new HttpResponseMessage(c).IsSuccessStatusCode);
}
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.