You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:41:07