每当我使用Windows.Web.Http.HttpClient类发出HTTP请求时,我总是处理这样的网络异常:
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.
}
但是现在我将捕获所有异常,而不仅仅是网络异常,特别是如果try块不仅包含httpClient.GetAsync
调用。
各种异常HRESULT已经在ABI层自动转换为适当的托管类型(例如,E_OUTOFMEMORY被投射到System.OutOfMemoryException),那么为什么不以类似的方式预测网络异常?
答案 0 :(得分:3)
WinRT定义的异常类型非常少,而且有限数量的HRESULT
将专门投射到C#中。
通常,WinRT API设计模式避免除了编程错误之外的所有内容的异常,并且应该在设计时发现(无效参数,缺少功能等)或者你可以发现的东西真的从中恢复(比如内存不足)。您应该避免使用try
\ catch
处理这些类型的例外,因为它们代表了您应用中的错误或系统无法继续运行您的应用。
相反,WinRT更喜欢让方法成功但返回其中包含状态代码的对象(例如ResponseCode
),您可以查询该方法是否成功完成。
这样做的原因是许多开发人员无法处理异常(由于未在不同配置下完全测试他们的应用程序)。未处理的异常是保证以降低流程,这对客户来说不是很好的体验,但是指示失败的返回值通常可以由应用处理,因为他们已经在检查状态由于其他原因(例如,您可能总是想检查HTTP状态,是否有错误)或者因为代码已经对“空”结果具有弹性(例如,foreach
在空列表上很好-defined)。
并非所有API都遵循这种模式 - 特别是那些早期在Windows 8中设计的模式 - 但它是您应该在大多数WinRT API中看到的模式。您还会注意到WinRT中有很多Try
样式的API尝试执行某些操作并返回true
或false
而不是抛出异常。因此,在大多数情况下,您的代码应该没有围绕WinRT API调用的try
/ catch
块,尽管您可能仍需要将它们用于您自己的代码或第三方库。
答案 1 :(得分:3)
我不知道为什么Windows.Web.Http.HttpClient
类异常不会自动包装在适当的托管类型中,但是(谢天谢地!)有一种方法可以获得实际的原因 - Windows.Web.WebError.GetStatus。< / p>
例如:
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.
}
}
答案 2 :(得分:0)
对于它的价值,在UWP应用程序中使用Windows.Web.Http.HttpClient时,我一直在努力决定如何处理错误(尤其是与网络相关的错误)。
我确定的模式是返回一个包含信息或异常的对象(我可以使用Task返回):
private class MyResponseObject
{
public string Data = string.Empty;
// Alternatively you could return the HttpResponseMessage (I guess).
//public HttpResponseMessage HttpResponseMessage;
public Exception Exception = null;
}
具体而言,在获得回复后立即使用检查响应IsSuccessStatusCode属性:
private async Task<MyResponseObject> CallService(Uri url)
{
MyResponseObject r = new MyResponseObject();
try
{
HttpResponseMessage response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
// do something with the information successfully received
r.Data = await response.Content.ReadAsStringAsync();
}
}
catch (Exception ex)
{
// do something with the exception
r.Exception = ex;
}
return r;
}