Memeriksa apakah HttpStatusCode menunjukkan berhasil atau gagal

93

Misalkan saya memiliki variabel berikut:

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

Bagaimana saya bisa memeriksa apakah ini adalah kode status sukses atau gagal?

Misalnya, saya dapat melakukan hal berikut:

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

Saya juga dapat memiliki semacam daftar putih:

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

Tak satu pun dari alternatif ini meyakinkan saya, dan saya berharap untuk kelas atau metode .NET yang dapat melakukan pekerjaan ini untuk saya, seperti:

bool isSuccess = HttpUtilities.IsSuccess(status);
Matias Cicero
sumber
yang perlu Anda lakukan int code = (int)Response.StatusCodedari sana, Anda perlu membuat Enumcek sendiri di sini untuk contoh kerja stackoverflow.com/questions/1330856/…
MethodMan
Apakah Anda kebetulan menggunakan HttpClientkelas?
dcastro
1
@dcastro Tidak, maaf. Saya menggunakan API tingkat tinggi yang mungkin (atau mungkin tidak) menggunakannya secara internal. API memperlihatkan kode status respons, tetapi tidak mengekspos bagian dalam HttpResponseMessagemisalnya
Matias Cicero
@MatiCicero Itu terlalu buruk: / Anda selalu dapat menggunakan kembali implementasi HttpResponseMessage.IsSuccessStatusCode(lihat jawaban saya) yang persis sama dengan pendekatan pertama Anda, dan menjadikannya metode ekstensi pada HttpStatusCodetipe.
dcastro

Jawaban:

177

Jika Anda menggunakan HttpClientkelas, maka Anda akan mendapatkan keuntungan HttpResponseMessage.

Kelas ini memiliki properti berguna yang disebut IsSuccessStatusCodeyang akan melakukan pemeriksaan untuk Anda.

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

Jika Anda penasaran, properti ini diimplementasikan sebagai:

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

Jadi, Anda dapat menggunakan kembali algoritme ini jika Anda tidak menggunakannya HttpClientsecara langsung.

Anda juga dapat menggunakan EnsureSuccessStatusCodeuntuk melempar pengecualian jika respons tidak berhasil.

dcastro
sumber
1
FYI: Apakah 'respons. Berhasil' bagi saya.
Topher Birth
Jawaban Anda cukup membantu tetapi sekarang berfungsi seperti: if (response.IsCompletedSuccessfully) {//}
salman
12

Kelas HttpResponseMessage memiliki properti IsSuccessStatusCode, melihat kode sumbernya seperti ini sehingga usr telah menyarankan 200-299 mungkin adalah yang terbaik yang dapat Anda lakukan.

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

Jawaban yang diterima sedikit mengganggu saya karena mengandung angka ajaib, (meskipun dalam standar) di bagian kedua. Dan bagian pertama tidak umum untuk kode status integer biasa, meskipun dekat dengan jawaban saya.

Anda dapat mencapai hasil yang persis sama dengan membuat instance HttpResponseMessage dengan kode status Anda dan memeriksa keberhasilan. Itu melempar pengecualian argumen jika nilainya lebih kecil dari nol atau lebih besar dari 999.

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

Ini tidak terlalu ringkas, tetapi Anda dapat membuatnya menjadi ekstensi.

pengguna232548
sumber
Ini bekerja dengan sempurna untuk saya karena saya hanya memiliki HttpStatusCode dan bukan pesan Respon. Kerja bagus!
Todd Vance
5
"Jawaban yang diterima sedikit mengganggu saya karena mengandung angka ajaib, (meskipun dalam standar)" - Itu bukan "ajaib" jika dibakukan, dipahami dengan baik, dan tidak akan pernah berubah. Tidak ada yang salah dengan menggunakan kode secara langsung. Jika Anda memiliki yang IsSuccessStatusCodehebat, gunakan itu (seperti yang dikatakan jawaban yang diterima.) Jika tidak, jangan menambahkan cruft Anda sendiri dengan menggunakan abstraksi kecuali Anda melakukan pemeriksaan ini di semua tempat
Ed S.
1
Ingatlah bahwa membuat instance HttpResponseMessageuntuk menggunakan salah satu propertinya membutuhkan lebih banyak waktu daripada memeriksa dua kondisi logis dengan int.
Miro J.
10

Menambahkan ke jawaban @TomDoesCode Jika Anda menggunakan HttpWebResponse, Anda dapat menambahkan metode ekstensi ini:

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

Saya lebih memilih metode ekstensi yang dapat ditemukan.

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

Selama namespace Anda berada dalam cakupan, penggunaannya akan statusCode.IsSuccessStatusCode().

bojingo
sumber
Metode ekstensi itu keren, tapi saya bingung - bukankah ini melakukan hal yang sama seperti properti IsSuccessStatusCode HTTPResponseMessage yang digunakan dengan HTTPClient atau IHTTPClientFactory? @DCastro bahkan menunjukkan kepada kita bahwa ini diterapkan persis seperti ini di .NET. Kapan / mengapa saya menggunakan metode ekstensi seperti ini untuk Kode Status HTTP dalam kisaran 2xx?
sfors mengatakan memulihkan Monica
4
@sfors, ya, tetapi bagaimana jika Anda hanya memiliki HttpStatusCodecakupan? Ada banyak pustaka yang tidak menggunakan atau muncul HttpResponseMessagetetapi memberi Anda kode status.
bojingo
3

Itu tergantung pada sumber daya HTTP apa yang Anda panggil. Biasanya, 2xxkisaran didefinisikan sebagai kisaran kode status sukses. Itu jelas merupakan konvensi yang tidak dipatuhi oleh setiap server HTTP.

Misalnya, mengirimkan formulir di situs web sering kali akan menghasilkan pengalihan 302.

Jika Anda ingin merancang metode umum maka code >= 200 && code < 300idenya mungkin adalah pilihan terbaik Anda.

Jika Anda memanggil server Anda sendiri maka Anda mungkin harus memastikan bahwa Anda melakukan standarisasi 200.

usr
sumber
2

Ini adalah perpanjangan dari jawaban sebelumnya, yang menghindari pembuatan dan pengumpulan sampah berikutnya dari objek baru untuk setiap pemanggilan.

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);
}
Rob Lyndon
sumber