Whenever I use the Windows.Web.Http.HttpClient class to make HTTP requests, I always handle network exceptions like this:
HttpResponseMessage response;
try
{
response = await httpClent.GetAsync(new Uri("http://www.microsoft.com"));
}
catch (Exception e)
{
// Most likely a network exception.
// Inspect e.HResult value to see what the specific error was.
}
But now I'll catch all exceptions instead of just network exceptions, especially if the try block encompasses more than just the httpClient.GetAsync
call.
Various exception HRESULTs are already converted into appropriate managed types automatically at the ABI layer (e.g. E_OUTOFMEMORY is projected to System.OutOfMemoryException), so why are network exceptions not projected in a similar manner?
There are a very small number of exception types defined by WinRT, and a limited number of HRESULT
s that will project specially into C#.
In general, the WinRT API design pattern avoids exceptions for everything except things that are programming errors and should be discovered at design-time (invalid arguments, missing capabilities, etc) or things that you can't really recover from (such as out-of-memory). You should avoid handling these types of exceptions with try
\ catch
because they represent bugs in your app or an inability of the system to keep running your app.
Instead, WinRT prefers to have methods succeed but return objects with status codes in them (eg, ResponseCode
) that you can query to see whether the method completed successfully or not.
The reasoning for this is that many developers fail to handle exceptions (due to not fully testing their app under different configurations). An unhandled exception is guaranteed to bring down the process, which isn't a great experience for customers, but a return value that indicates failure can often be handled by apps, either because they were already checking the status for other reasons (eg, you probably always want to check the HTTP status, whether you got an error or not) or because the code is already resilient to "empty" results (eg, foreach
over an empty list is well-defined).
Not all APIs follow this pattern - especially those designed early on in Windows 8 -- but it is a pattern you should see in most WinRT APIs. You will also notice a lot of Try
-style APIs in WinRT that attempt to do something and return true
or false
rather than throwing an exception. So for the most part, your code should be free of try
/ catch
blocks around WinRT API calls, although you might still need to use them for your own code or 3rd-party libraries.
I don't know why Windows.Web.Http.HttpClient
class exceptions are not automatically wrapped in appropriate managed types, but (thankfully!) there is a method which allows to get the actual reason -- Windows.Web.WebError.GetStatus.
For example:
using (var client = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.example.com"));
try
{
// Http-errors are returned in the response, and no exception is thrown.
HttpResponseMessage response = await client.SendRequestAsync(request);
}
catch (Exception ex)
{
WebErrorStatus error = WebError.GetStatus(ex.HResult);
// For example, if your device could not connect to the internet at all,
// the error would be WebErrorStatus.HostNameNotResolved.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With