Xamarin.Forms iOS端全局捕获NSURLException转换为HttpException方案问询
解决方案:iOS端WebException转HttpException实现方案
方案一:通过自定义DelegatingHandler实现拦截(推荐)
该方案侵入性最低,仅需在iOS平台侧做配置,无需修改共享代码逻辑:
- 首先在iOS平台项目中创建自定义消息处理类,继承
DelegatingHandler,在请求调用链路中捕获异常并转换:
public class ExceptionTransformHandler : DelegatingHandler { public ExceptionTransformHandler(HttpMessageHandler innerHandler) : base(innerHandler) { } protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { try { return await base.SendAsync(request, cancellationToken); } catch (WebException ex) { // 提取WebException的状态码、响应信息等,构造HttpException var statusCode = ex.Response is HttpWebResponse response ? response.StatusCode : HttpStatusCode.InternalServerError; throw new HttpException((int)statusCode, ex.Message, ex); } } }
- 然后在iOS端初始化
HttpClient时,将ModernHttpClient的NativeMessageHandler作为内层处理者传入自定义Handler即可:
var nativeHandler = new ModernHttpClient.NativeMessageHandler(); var transformHandler = new ExceptionTransformHandler(nativeHandler); var httpClient = new HttpClient(transformHandler); // 后续将该httpClient实例注入共享代码使用即可
方案二:平台全局异常捕获兜底
如果项目中不方便统一封装HttpClient实例,可以使用Xamarin.iOS的全局异常捕获机制做兜底转换:
- 在iOS项目的
AppDelegate.cs的FinishedLaunching方法中注册全局异常处理事件:
AppDomain.CurrentDomain.UnhandledException += (sender, e) => { if (e.ExceptionObject is WebException webEx) { // 仅捕获网络请求相关的WebException进行转换 if (webEx.Source == "ModernHttpClient") { var statusCode = webEx.Response is HttpWebResponse response ? response.StatusCode : HttpStatusCode.InternalServerError; throw new HttpException((int)statusCode, webEx.Message, webEx); } } };
注意:该方案仅作为兜底使用,优先级低于方案一,避免误转换非网络请求场景抛出的WebException
注意事项
- 转换时请务必将原始
WebException作为内部异常传入HttpException,避免丢失原始堆栈信息和错误详情,便于后续问题排查 - 若
NSURLException抛出的场景无对应HTTP状态码,可以按业务规则约定统一映射为500或408等通用状态码
内容的提问来源于stack exchange,提问作者David_Strachan
相关产品推荐
相关产品推荐

