WebClient UploadData遇403状态码未抛出异常技术问询
解决WebClient调用API返回403不抛出WebException的问题
我来帮你梳理下这个问题的根源,再给出两种实用的解决方案:
问题本质
WebClient的设计逻辑比较特殊:它只会在请求彻底无法完成(比如网络断开、服务器返回5xx级别的错误)时自动抛出WebException。对于4xx类的客户端错误(像403 Forbidden、404 Not Found这类),它会认为请求已经成功发送并收到了服务器响应,所以不会主动触发异常,需要你手动检查响应状态来处理。
解决方案1:改造现有WebClient代码,手动校验状态码
你可以通过获取响应头来解析状态码,判断是否需要手动抛出异常。修改后的代码示例如下:
using (var webClient = new WebClient()) { try { webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json"); string json = JsonConvert.SerializeObject(updateLiveMapRequest); byte[] data = Encoding.UTF8.GetBytes(json); // 先获取响应数据 byte[] responseBytes = await webClient.UploadDataTaskAsync("http://localhost:1778/api/upload/data", data); // 解析响应状态码 if (webClient.ResponseHeaders.TryGetValues("Status", out var statusValues)) { string statusLine = statusValues.FirstOrDefault(); if (!string.IsNullOrEmpty(statusLine)) { // 从状态行中提取状态码(格式类似 "HTTP/1.1 403 Forbidden") if (statusLine.Contains("403")) { throw new WebException("服务器返回403禁止访问", WebExceptionStatus.ProtocolError); } // 也可以扩展处理所有4xx错误: // int statusCode = int.Parse(statusLine.Split(' ')[1]); // if (statusCode >= 400 && statusCode < 500) { ... } } } } catch (WebException ex) { Logger.Debug(ex); throw; } }
另外,你也可以在原有的WebException捕获块里补充逻辑,处理协议错误类的响应:
catch (WebException ex) { if (ex.Response is HttpWebResponse httpResponse) { if (httpResponse.StatusCode == HttpStatusCode.Forbidden) { Logger.Debug("触发403禁止访问:" + ex.Message); // 这里可以添加针对403的特殊处理逻辑 } } Logger.Debug(ex); throw; }
解决方案2:改用HttpClient(推荐)
WebClient在.NET Core中已经是过时的API,微软官方更推荐使用HttpClient来处理HTTP请求。HttpClient默认会对非2xx的状态码抛出HttpRequestException,完全符合你预期的异常触发逻辑。示例代码如下:
// 注意:HttpClient建议单例复用,不要每次请求都创建新实例 private static readonly HttpClient _httpClient = new HttpClient(); public async Task UploadDataAsync(UpdateLiveMapRequest updateLiveMapRequest) { try { string json = JsonConvert.SerializeObject(updateLiveMapRequest); var requestContent = new StringContent(json, Encoding.UTF8, "application/json"); HttpResponseMessage response = await _httpClient.PostAsync("http://localhost:1778/api/upload/data", requestContent); // 这行代码会自动对非2xx状态码抛出HttpRequestException response.EnsureSuccessStatusCode(); } catch (HttpRequestException ex) { Logger.Debug(ex); throw; } }
使用HttpClient不仅能解决异常触发的问题,还支持连接池复用、更灵活的请求配置等特性,更适配.NET Core的开发环境。
内容的提问来源于stack exchange,提问作者SeToY
相关产品推荐
相关产品推荐

