161

Is there an easy way to get the HTTP status code from a System.Net.WebException?

WynandB
  • 1,267
  • 13
  • 15
Gilsham
  • 2,136
  • 2
  • 12
  • 14

6 Answers6

258

Maybe something like this...

try
{
    // ...
}
catch (WebException ex)
{
    if (ex.Status == WebExceptionStatus.ProtocolError)
    {
        var response = ex.Response as HttpWebResponse;
        if (response != null)
        {
            Console.WriteLine("HTTP Status Code: " + (int)response.StatusCode);
        }
        else
        {
            // no http status code available
        }
    }
    else
    {
        // no http status code available
    }
}
LukeH
  • 242,140
  • 52
  • 350
  • 400
  • but in case of "connectfailure" exception of webexception i get response as null, in that case how can i get the httpstatus code – Rusty Mar 20 '14 at 10:32
  • 10
    @rusty: You can't. If there's a connection failure then there is no HTTP status code to be got. – LukeH Mar 20 '14 at 11:03
  • 4
    If the error is a ProtocolError, you don't have to check the response for null. See the comment in the example on this [MSDN page](http://msdn.microsoft.com/en-us/library/es54hw8e%28v=vs.110%29.aspx) – Andras Toth May 20 '14 at 15:19
  • 5
    @AndrasToth But tools like ReSharper will give you a warning if you omit the null-check. And in any case, it's good practise to code defensively. – Tom Lint Feb 19 '15 at 11:14
  • @TomLint I don't think it's about warnings or defensive coding, it's that @LukeH is using the `as` operator, which is a dynamic cast, so the check for null is to see if the cast has worked or not, at runtime. – ympostor Jun 27 '17 at 05:37
  • @ympostor I know, but there are people who just assume the cast just works. And oftentimes it does, depending on the situation. The null-check gives you ensurance that your assumption was actually correct, and prevents unexpected exceptions should the cast fail. – Tom Lint Jul 05 '17 at 08:33
  • 1
    How get ***HTTP Substatus*** value ? For example, _404.13 Content Length Too Large Reference_: https://docs.microsoft.com/en-us/iis/configuration/system.webServer/security/requestFiltering/requestLimits/ – Kiquenet Mar 23 '18 at 11:10
28

By using the null-conditional operator (?.) you can get the HTTP status code with a single line of code:

 HttpStatusCode? status = (ex.Response as HttpWebResponse)?.StatusCode;

The variable status will contain the HttpStatusCode. When the there is a more general failure like a network error where no HTTP status code is ever sent then status will be null. In that case you can inspect ex.Status to get the WebExceptionStatus.

If you just want a descriptive string to log in case of a failure you can use the null-coalescing operator (??) to get the relevant error:

string status = (ex.Response as HttpWebResponse)?.StatusCode.ToString()
    ?? ex.Status.ToString();

If the exception is thrown as a result of a 404 HTTP status code the string will contain "NotFound". On the other hand, if the server is offline the string will contain "ConnectFailure" and so on.

(And for anybody that wants to know how to get the HTTP substatus code. That is not possible. It is a Microsoft IIS concept that is only logged on the server and never sent to the client.)

Kiquenet
  • 13,271
  • 31
  • 133
  • 232
Martin Liversage
  • 96,855
  • 20
  • 193
  • 238
  • Not sure whether the `?.` operator was originally named null propagation operator or null-conditional operator during preview release. But Atlassian resharper gives a warning to use null propagation operator in such scenarios. Nice to know that it is also called null-conditional operator. – RBT Mar 05 '17 at 08:03
  • 1
    A bit late to this party, but fair warning that the null-conditional operator is a C# 6.0 feature, so one needs to be using a compiler that supports it. [Stack Overflow answer with further details](https://stackoverflow.com/questions/39089426/how-to-install-the-ms-c-sharp-6-0-compiler). VS 2015+ has it by default, but if one is using any kind of build/deploy environment other than just "their machine", other things might need to be taken into consideration. – CodeHxr Dec 11 '17 at 21:47
10

this works only if WebResponse is a HttpWebResponse.

try
{
    ...
}
catch (System.Net.WebException exc)
{
    var webResponse = exc.Response as System.Net.HttpWebResponse;
    if (webResponse != null && 
        webResponse.StatusCode == System.Net.HttpStatusCode.Unauthorized)
    {
        MessageBox.Show("401");
    }
    else
        throw;
}
sharptooth
  • 159,303
  • 82
  • 478
  • 911
pr0gg3r
  • 3,904
  • 1
  • 33
  • 25
  • why only deal with 401-Unauthorized instead of all possible HTTP error status codes? this is the worst answer – ympostor Jun 27 '17 at 05:39
  • 5
    @ympostor This is just an example. Any reasonable developer understands this. Your comment is the most thoughtless I've ever read here. – pr0gg3r Jun 28 '17 at 08:53
10

(I do realise the question is old, but it's among the top hits on Google.)

A common situation where you want to know the response code is in exception handling. As of C# 7, you can use pattern matching to actually only enter the catch clause if the exception matches your predicate:

catch (WebException ex) when (ex.Response is HttpWebResponse response)
{
     doSomething(response.StatusCode)
}

This can easily be extended to further levels, such as in this case where the WebException was actually the inner exception of another (and we're only interested in 404):

catch (StorageException ex) when (ex.InnerException is WebException wex && wex.Response is HttpWebResponse r && r.StatusCode == HttpStatusCode.NotFound)

Finally: note how there's no need to re-throw the exception in the catch clause when it doesn't match your criteria, since we don't enter the clause in the first place with the above solution.

miniyou
  • 101
  • 1
  • 4
5

You can try this code to get HTTP status code from WebException. It works in Silverlight too because SL does not have WebExceptionStatus.ProtocolError defined.

HttpStatusCode GetHttpStatusCode(WebException we)
{
    if (we.Response is HttpWebResponse)
    {
        HttpWebResponse response = (HttpWebResponse)we.Response;
        return response.StatusCode;
    }
    return null;
}
Sergey
  • 1,434
  • 19
  • 16
  • 1
    `return 0` ? or better `HttpStatusCode?` (***nullable***)? – Kiquenet Mar 23 '18 at 11:27
  • Will this work? `var code = GetHttpStatusCode(ex); if (code != HttpStatusCode.InternalServerError) {EventLog.WriteEntry( EventLog.WriteEntry("MyApp", code, System.Diagnostics.EventLogEntryType.Information, 1);}` – FMFF Nov 30 '18 at 19:46
  • I can't understand what you wanted to do in this sample. In what cases you wanted event to be logged? – Sergey Dec 01 '18 at 22:34
1

I'm not sure if there is but if there was such a property it wouldn't be considered reliable. A WebException can be fired for reasons other than HTTP error codes including simple networking errors. Those have no such matching http error code.

Can you give us a bit more info on what you're trying to accomplish with that code. There may be a better way to get the information you need.

JaredPar
  • 673,544
  • 139
  • 1,186
  • 1,421