Использование EnsureSuccessStatusCode и обработка HttpRequestException он бросает


каков шаблон использования HttpResponseMessage.EnsureSuccessStatusCode()? Он избавляется от содержимого сообщения и бросает HttpRequestException, но я не вижу, как программно обрабатывать его иначе, чем общий Exception. Например, он не включает HttpStatusCode, который было бы удобно.

есть ли способ получить больше информации из него? Может ли кто-нибудь показать соответствующий шаблон использования обоих EnsureSuccessStatusCode() и HttpRequestException?

3 63

3 ответа:

идиоматическое использование EnsureSuccessStatusCode заключается в краткой проверке успешности запроса, когда вы не хотите обрабатывать случаи отказа каким-либо конкретным образом. Это особенно полезно, когда вы хотите быстро создать прототип клиента.

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

var response = await client.GetAsync(...);
try
{
    response.EnsureSuccessStatusCode();
    // Handle success
}
catch (HttpRequestException)
{
    // Handle failure
}

Это бросает исключение, чтобы сразу же поймать его, что не имеет никакого смысла. Элемент IsSuccessStatusCode собственность HttpResponseMessage is там для этого есть. Вместо этого сделайте следующее.

var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)
{
    // Handle success
}
else
{
    // Handle failure
}

мне не нравится EnsureSuccessStatusCode, так как он не возвращает ничего значимого. Вот почему я создал свое собственное расширение:

public static class HttpResponseMessageExtensions
{
    public static async Task EnsureSuccessStatusCodeAsync(this HttpResponseMessage response)
    {
        if (response.IsSuccessStatusCode)
        {
            return;
        }

        var content = await response.Content.ReadAsStringAsync();

        if (response.Content != null)
            response.Content.Dispose();

        throw new SimpleHttpResponseException(response.StatusCode, content);
    }
}

public class SimpleHttpResponseException : Exception
{
    public HttpStatusCode StatusCode { get; private set; }

    public SimpleHttpResponseException(HttpStatusCode statusCode, string content) : base(content)
    {
        StatusCode = statusCode;
    }
}

исходный код для Microsoft EnsureSuccessStatusCode можно найти здесь

синхронная версия на основе ссылка:

public static void EnsureSuccessStatusCode(this HttpResponseMessage response)
{
    if (response.IsSuccessStatusCode)
    {
        return;
    }

    var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();

    if (response.Content != null)
        response.Content.Dispose();

    throw new SimpleHttpResponseException(response.StatusCode, content);
}

что мне не нравится в IsSuccessStatusCode, так это то, что он не "красиво" многоразовый. Например, вы можете использовать библиотеку, как Поли повторить a запрос в случае проблем с сетью. В этом случае вам нужно, чтобы ваш код вызывал исключение, чтобы Полли или какая-либо другая библиотека могли его обрабатывать...

Я знаю, что это не лучший способ сделать это, но я использую такой:

try
{
    ...
}
catch (HttpRequestException exception)
{
    if (exception.Message.Contains("401 (Unauthorized)"))
    {
        statusCode = HttpStatusCode.Unauthorized;
    }
    else if (exception.Message.Contains("403 (Forbidden)"))
    {
        statusCode = HttpStatusCode.Forbidden;
    }
}

пожалуйста, дайте мне знать, если у вас есть лучшее решение.