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


предположим, что у меня есть следующая переменная:

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);
7 55

7 ответов:

если вы используете 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 бросать исключение в случае ответ не был успешным.

класс HttpResponseMessage имеет свойство IsSuccessStatusCode, глядя на исходный код, это похоже на то, что usr уже предложил 200-299, вероятно, лучшее, что вы можете сделать.

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

принятый ответ немного беспокоит меня, поскольку он содержит магические числа (хотя они находятся в стандартной форме) во второй части. И первая часть не является общей для простых целочисленных кодов состояния, хотя она близка к моему ответу.

вы можете достичь точно такого же результата, создав экземпляр HttpResponseMessage с вашим кодом состояния и проверив его на успех. Он вызывает исключение аргумента, если значение меньше нуля или больше 999.

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

Это не совсем лаконично, но вы могли бы сделать его расширением.

добавление в @TomDoesCode ответа, если вы используете HttpWebResponse вы можете добавить этот метод расширения:

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

Это зависит от того, какой HTTP-ресурс вы вызываете. Обычно 2xx диапазон определяется как диапазон кодов состояния успеха. Это явно соглашение, которое не каждый HTTP-сервер будет придерживаться.

например, отправка формы на веб-сайте часто возвращает перенаправление 302.

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

Если вы звоните своему собственные сервер тогда вы наверное следует убедиться, что вы стандартизируете на 200.

Это расширение предыдущего ответа, которое позволяет избежать создания и последующей сборки мусора нового объекта для каждого вызова.

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);
}

я неравнодушен к нахождению методов расширения.

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

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