Перевірка, чи HttpStatusCode представляє успіх чи невдачу


93

Припустимо, у мене є така змінна:

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

Як я можу перевірити, це код стану успіху чи помилки?

Наприклад, я можу зробити наступне:

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

Я також можу отримати якийсь білий список:

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

Жодна з цих альтернатив мене не переконує, і я сподівався на клас або метод .NET, які можуть зробити цю роботу за мене, наприклад:

bool isSuccess = HttpUtilities.IsSuccess(status);

вам потрібно зробити int code = (int)Response.StatusCodeзвідти вам потрібно буде створити Enumтут власний чек для робочого прикладу stackoverflow.com/questions/1330856/…
MethodMan

Ви випадково користуєтесь HttpClientкласом?
dcastro

1
@dcastro Ні, вибачте. Я використовую високорівневий API, який може (або не використовувати) його внутрішньо. API виставляє код стану відповіді, але не викриває внутрішній, HttpResponseMessageнаприклад
Matias Cicero

@MatiCicero Це дуже погано: / Ви завжди можете повторно використати реалізацію HttpResponseMessage.IsSuccessStatusCode(див. Мою відповідь), яка точно відповідає вашому першому підходу, і зробити її методом розширення для HttpStatusCodeтипу.
dcastro

Відповіді:


173

Якщо ви використовуєте HttpClientклас, то отримаєте HttpResponseMessageназад.

Цей клас має корисну властивість під назвою, IsSuccessStatusCodeяка зробить перевірку за вас.

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

Якщо вам цікаво, ця властивість реалізована як:

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

Таким чином, ви можете просто використовувати цей алгоритм, якщо не використовуєте HttpClientбезпосередньо.

Ви також можете використати EnsureSuccessStatusCodeвикид, якщо відповідь не була успішною.


FYI: Для мене це була "відповідь. Успішна".
Народження

Ваша відповідь є дуже корисною, але зараз вона працює так: if (response.IsCompletedSuccessfully) {//}
salman

12

Клас HttpResponseMessage має властивість IsSuccessStatusCode, дивлячись на вихідний код, він такий, так як usr вже припустив, що 200-299 - це, мабуть, найкраще, що ви можете зробити.

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

11

Прийнята відповідь мене трохи турбує, оскільки вона містить магічні числа (хоча вони є стандартними) у своїй другій частині. І перша частина не є загальною для простих цілочисельних кодів стану, хоча вона близька до моєї відповіді.

Ви могли б досягти точно такого ж результату, створивши інстанцію HttpResponseMessage зі своїм кодом стану та перевіривши успіх. Він викидає виняток аргументу, якщо значення менше нуля або більше 999.

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

Це не зовсім лаконічно, але ви можете зробити це продовженням.


Для мене це спрацювало ідеально, оскільки я мав лише HttpStatusCode, а не повідомлення відповіді. Хороша робота!
Тодд Венс,

5
"Прийнята відповідь мене трохи турбує, оскільки вона містить магічні числа (хоча вони є стандартними)". Вони не є "магічними", якщо вони стандартизовані, добре зрозумілі і ніколи не змінюються. Немає абсолютно нічого поганого у безпосередньому використанні кодів. Якщо у вас IsSuccessStatusCodeтоді чудово, використовуйте його (як говорить прийнята відповідь.) В іншому випадку, не додайте свій власний нафтопродукт, використовуючи абстракцію, якщо ви не виконуєте цю перевірку
Ед С.

1
Майте на увазі, що створення екземпляра HttpResponseMessageдля використання одного з його властивостей вимагає більше часу, ніж перевірка двох логічних умов int.
Міро Дж.

10

Додавання до відповіді @TomDoesCode Якщо ви використовуєте HttpWebResponse, ви можете додати цей метод розширення:

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

8

Я прихильний до відкритості методів розширення.

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

Поки ваш простір імен знаходиться в області дії, використання буде таким statusCode.IsSuccessStatusCode().


2
ви, мабуть, хочете asInt> = 200 там
Джим О'Ніл,

Методи розширення - це круто, але я збентежений - чи не робить це те саме, що властивість IsSuccessStatusCode HTTPResponseMessage, що використовується з HTTPClient або IHTTPClientFactory? @DCastro навіть показує нам, що він реалізований саме так, як у .NET. Коли / чому я повинен використовувати такий метод розширення для кодів статусу HTTP у діапазоні 2xx?
sfors каже, відновити Моніку

4
@sfors, так, але що, якщо у вас є лише HttpStatusCodeсфера дії? Існує безліч бібліотек, які не використовують або не виводять на поверхню, HttpResponseMessageале дають вам код стану.
bojingo

3

Це залежить від того, який ресурс HTTP ви викликаєте. Зазвичай,2xx діапазон визначається як діапазон кодів стану успіху. Це явно домовленість, якої дотримуватиметься не кожен HTTP-сервер.

Наприклад, надсилання форми на веб-сайті часто повертає переадресацію 302.

Якщо ви хочете розробити загальний метод, тоді code >= 200 && code < 300ідея, мабуть, найкращий вистріл.

Якщо ви телефонуєте на власний сервер, то вам, мабуть, слід переконатись, що ви стандартизуєтесь 200.


2

Це розширення попередньої відповіді, яке дозволяє уникнути створення та подальшого збору сміття нового об’єкта для кожного виклику.

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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.