HttpClient PutAsync调用报远程主机强制关闭连接异常排查
问题描述
现有一个.NET WebApi服务,.NET客户端调用服务端点的PutAsync()方法始终失败,但同端点通过Postman测试可正常运行,需排查客户端配置/编写错误。
服务端代码
WebAPI控制器定义
public class SampleController : ApiController { [HttpPut] public HttpResponseMessage Register(string useremail) { return Request.CreateResponse(HttpStatusCode.OK, "Success"); } }
WebApi路由配置
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
客户端调用代码
using (var client = new HttpClient()) { var requestUri = new Uri(@"http://localhost:44335/api/Sample/Register?useremail=jxb@tiac.net"); var responseTask = client.PutAsync(requestUri, null); responseTask.Wait(); var result = responseTask.Result; }
报错信息
运行时在responseTask.Wait()处抛出异常:
"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host." "An existing connection was forcibly closed by the remote host"
正常调用验证
通过Postman调用以下地址可获得成功响应:
https://localhost:44335/api/Sample/Register?useremail=jxb@tiac.net
故障原因
两个核心问题导致调用失败:
- 请求协议不匹配
客户端代码里的请求地址用的是http协议,但服务监听的44335端口是HTTPS端口(Postman调用成功的地址明确为https开头),HTTP请求发到HTTPS端口时,服务端会直接强制断开连接,抛出连接被远程主机强制关闭的异常。 - PUT请求Content参数传null不符合HTTP规范
PutAsync方法的第二个参数是请求体内容,即使接口不需要请求体,也不能传null,需要传入空的HttpContent实例,否则部分.NET版本的HttpClient会构造不符合规范的请求,被服务端直接拒绝。
修复方案
修改客户端代码如下:
using (var client = new HttpClient()) { // 修正请求协议为https,和服务端监听配置一致 var requestUri = new Uri(@"https://localhost:44335/api/Sample/Register?useremail=jxb@tiac.net"); // 空请求体传入空字符串内容,禁止传null var responseTask = client.PutAsync(requestUri, new StringContent("")); responseTask.Wait(); var result = responseTask.Result; }
如果本地开发环境遇到HTTPS证书不受信任的问题,可临时添加以下配置跳过证书验证(仅本地调试可用,生产环境禁止配置):
// 配置在HttpClient初始化之前 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
内容的提问来源于stack exchange,提问作者JohnB
相关产品推荐
相关产品推荐

