Использование EnsureSuccessStatusCode и обработка исключений HttpRequestException
Каков шаблон использования HttpResponseMessage.EnsureSuccessStatusCode()
? Он располагает Контентом сообщения и выбрасывает HttpRequestException
, но я не вижу, как программно обрабатывать его иначе, чем общий Exception
. Например, он не включает HttpStatusCode
, что было бы удобно.
Есть ли способ получить больше информации? Может ли кто-нибудь показать соответствующий шаблон использования как EnsureSuccessStatusCode()
, так и HttpRequestException?
Ответы
Ответ 1
Идиоматическое использование EnsureSuccessStatusCode
заключается в том, чтобы кратко подтвердить успех запроса, когда вы не хотите обрабатывать случаи отказа каким-либо конкретным способом. Это особенно полезно, если вы хотите быстро прототипировать клиента.
Когда вы решите, что хотите обрабатывать случаи отказа определенным образом, не делать следующее.
var response = await client.GetAsync(...);
try
{
response.EnsureSuccessStatusCode();
// Handle success
}
catch (HttpRequestException)
{
// Handle failure
}
Это создает исключение, чтобы сразу его поймать, что не имеет никакого смысла. Для этой цели существует свойство IsSuccessStatusCode
для HttpResponseMessage
. Вместо этого сделайте следующее.
var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)
{
// Handle success
}
else
{
// Handle failure
}
Ответ 2
Мне не нравится 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 можно найти здесь
Синхронная версия на основе Ссылка SO:
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, так это то, что он не "красиво" многоразовый. Например, вы можете использовать библиотеку, например polly, чтобы повторить запрос в случае сетевой проблемы. В этом случае вам нужен ваш код, чтобы повысить исключение, чтобы политическая или некоторая другая библиотека могла его обрабатывать...
Ответ 3
Я знаю, что это не лучший способ сделать это, но я использую вот так:
try
{
...
}
catch (HttpRequestException exception)
{
if (exception.Message.Contains("401 (Unauthorized)"))
{
statusCode = HttpStatusCode.Unauthorized;
}
else if (exception.Message.Contains("403 (Forbidden)"))
{
statusCode = HttpStatusCode.Forbidden;
}
}
Пожалуйста, дайте мне знать, если у вас есть лучшее решение.
С уважением,
B.J.