问题
What's the usage pattern of HttpResponseMessage.EnsureSuccessStatusCode()
? It disposes of the Content of the message and throws HttpRequestException
, but I fail to see how to programmatically handle it any differently than a generic Exception
. For example, it doesn't include the HttpStatusCode
, which would have been handy.
Is there any way of getting more info out of it? Could anyone show relevant usage pattern of both EnsureSuccessStatusCode()
and HttpRequestException?
回答1:
The idiomatic usage of EnsureSuccessStatusCode
is to concisely verify success of a request, when you don't want to handle failure cases in any specific way. This is especially useful when you want to quickly prototype a client.
When you decide you want to handle failure cases in a specific way, do not do the following.
var response = await client.GetAsync(...);
try
{
response.EnsureSuccessStatusCode();
// Handle success
}
catch (HttpRequestException)
{
// Handle failure
}
This throws an exception just to immediately catch it, which doesn't make any sense. The IsSuccessStatusCode
property of HttpResponseMessage
is there for this purpose. Do the following instead.
var response = await client.GetAsync(...);
if (response.IsSuccessStatusCode)
{
// Handle success
}
else
{
// Handle failure
}
回答2:
I don't like EnsureSuccessStatusCode as it doesn't return anything meaninful. That is why I've created my own extension:
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;
}
}
source code for Microsoft's EnsureSuccessStatusCode can be found here
Synchronous version based on SO link :
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);
}
What I don't like about IsSuccessStatusCode is that it is not "nicely" reusable. For example you can use library like polly to repeat a request in case of network issue. In that case you need your code to raise exception so that polly or some other library can handle it...
回答3:
I use EnsureSuccessStatusCode when I don't want to handle the Exception on the same method.
public async Task DoSomethingAsync(User user)
{
try
{
...
var userId = await GetUserIdAsync(user)
...
}
catch(Exception e)
{
throw;
}
}
public async Task GetUserIdAsync(User user)
{
using(var client = new HttpClient())
{
...
response = await client.PostAsync(_url, context);
response.EnsureSuccesStatusCode();
...
}
}
The Exception thrown on GetUserIdAsync will be handled on DoSomethingAsync.
来源:https://stackoverflow.com/questions/21097730/usage-of-ensuresuccessstatuscode-and-handling-of-httprequestexception-it-throws