Reputation: 19814
I'm probably missing something obvious here.
I'm using HttpClient
which throws HttpRequestException
that contains StatusCode
in the Message string.
How can I access that StatusCode
?
Edit: More info, I wrote this question in rush.
I'm using HttpClient
to access another API within my WebApi project. Yes, I know why I'm calling EnsureSuccessStatusCode()
. I want to propagate some errors downstream such as 404 and 403.
All I wanted was to consistently transform HttpRequestException
into HttpResponseException
using custom ExceptionFilterAttribute
.
Unfortunately, HttpRequestException
does not carry any extra info I could use besides the message. I was hoping to uncover StatusCode
in raw (int or enum) form.
Looks like I can either:
Upvotes: 115
Views: 125378
Reputation: 32069
From .NET 5.0, HttpRequestException
has a StatusCode
property which will have a value if the exception represents a non-successful result, otherwise null. So you can use as follows:
try
{
// Your code
}
catch (HttpRequestException httpRequestException)
{
if ((int)httpRequestException.StatusCode == 401)
{
// Show unauthorized error message
}
else
{
// Other error message
}
}
For more details are here
Upvotes: 34
Reputation: 1019
in .Net 6
try
{
return await _httpClient.GetFromJsonAsync<YourType>("<url>", cancellationToken);
}
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound)
{
// handle 404
}
Upvotes: 4
Reputation: 4516
If what you need is to extract status code from HttpRequestException
(eg: in a application exception handler), look at answers from others.
Otherwise you might take a look at HttpClient.GetAsync()
method. Unlike methods like HttpClient.GetStringAsync()
(which return simple data type and thrown and exception if something goes wrong), that one return you a HttpResponseMessage
object everytime, regardless request success or failure.
From there you can check status code :
var response = await client.GetAsync(...);
if (!response.IsSuccessStatusCode)
{
var statusCode = response.StatusCode;
//throw an exception or something similar
}
var responseText = await response.Content.ReadAsStringAsync();
Upvotes: 0
Reputation: 1832
For .Net Core 3.1 I could not make use of TanvirArjel or Lex Li's solution. So I went with manually calling the HttpClient's GetHttpAsync method and interrogating the Http status code myself. If the status code returns "OK" I process the HttpClient's Content property for the returned Html.
public async Task<string> GetHtml(string url)
{
int retry = 3;
while (retry > 0)
{
retry = retry - 1;
try
{
var result = await client.GetAsync(url);
if (result.StatusCode != HttpStatusCode.OK)
{
switch (result.StatusCode)
{
case HttpStatusCode.BadGateway:
case HttpStatusCode.BadRequest:
case HttpStatusCode.Forbidden:
case HttpStatusCode.ServiceUnavailable:
case HttpStatusCode.GatewayTimeout:
{
Global.Report($"CustomHttpClient: Temporary issue detected. Pausing to allow time to resolve.");
// Wait for temporary issue to resolve
await Task.Delay(120000);
continue;
}
default:
{
throw new Exception($"CustomHttpClient: Error {result.StatusCode}.");
}
}
}
string response = await result.Content.ReadAsStringAsync();
return response;
}
catch (Exception ex)
{
throw new Exception($"CustomHttpClient: Error downloading page => {url}. " + ex);
}
}
throw new Exception($"CustomHttpClient: Temporary issue persists. Retries exhausted. Unable to download page => {url}.");
}
Upvotes: 0
Reputation: 1065
For what its worth, this guy did something clever: https://social.msdn.microsoft.com/Forums/vstudio/en-US/dc9bc426-1654-4319-a7fb-383f00b68def/c-httpresponsemessage-throws-exception-httprequestexception-webexception-the-remote-name?forum=csharpgeneral
In the case where I needed an exception status property, I can do this:
catch (HttpRequestException requestException)
{
if (requestException.InnerException is WebException webException && webException.Status == WebExceptionStatus.NameResolutionFailure)
{
return true;
}
return false;
}
Upvotes: 34
Reputation: 63173
Status code was passed as part of a string to HttpRequestException
so that you cannot recover it from such exceptions alone.
The design of System.Net.Http
requires you to access HttpResponseMessage.StatusCode
instead of waiting for the exception.
http://msdn.microsoft.com/en-us/library/system.net.http.httpresponsemessage(v=vs.110).aspx
If you are now following the Microsoft guide, make sure you understand clearly why it asks you to call HttpResponseMessage.EnsureSucessStatusCode
. If you don't call that function, there should be no exception.
Upvotes: 50
Reputation: 23
This has worked for me
var response = ex.Response;
var property = response.GetType().GetProperty("StatusCode");
if ( property != null && (HttpStatusCode)property.GetValue(response) == HttpStatusCode.InternalServerError)
Upvotes: 1
Reputation: 295
As mentioned by others as well it's not a good practice to get the StatusCode from HttpRequestException, the same can be done beforehand with HttpResponseMessage.StatusCode after checking HttpResponseMessage.IsSuccessStatusCode
Anyhow if due to some constraint/requirement one has to read StatusCode, There can be two solution
Below is the code in System.Net.Http.HttpResponseMessage Where SR.net_http_message_not_success_statuscode ="Response status code does not indicate success: {0} ({1})."
public HttpResponseMessage EnsureSuccessStatusCode()
{
if (!this.IsSuccessStatusCode)
{
if (this.content != null)
{
this.content.Dispose();
}
throw new HttpRequestException(string.Format(CultureInfo.InvariantCulture, SR.net_http_message_not_success_statuscode, new object[]
{
(int)this.statusCode,
this.ReasonPhrase
}));
}
return this;
}
Upvotes: 3