使用WebRequest发起带JSON Body的POST请求返回400错误如何解决?
POST调用返回400 Bad Request错误排查方案
核心错误原因
- 请求流操作顺序错误
现有代码中写入JSON后没有先清空缓冲区、关闭写入流,就直接调用GetResponse()发起请求,导致请求体数据还停留在StreamWriter的缓冲区中,没有实际发送到服务端。服务端接收到空的请求体后,[FromBody]参数绑定失败直接返回400。 - 路由规则冗余
控制器已经配置了[Route("api/[controller]")](最终前缀为api/Sale),Action上的[Route("Sale/Test")]会拼接为api/Sale/Sale/Test,虽然你同时配置了[Route("[action]")]可以匹配到api/Sale/Test,但冗余路由容易引发匹配混乱。 - 序列化规则不匹配
你使用的JavaScriptSerializer默认序列化输出为PascalCase格式(属性首字母大写),而.NET Core/5+的Web API默认使用System.Text.Json序列化器,要求输入为驼峰格式(属性首字母小写),可能会导致反序列化失败返回400。
修复方案
1. 调整调用代码流操作顺序
public IEnumerable<Inventory> GetTest(IpPartial ipPartial, Inventory[] inventories) { WebRequest request = WebRequest.Create("http://localhost:5002/api/Sale/Test"); request.Method = "POST"; request.ContentType = "application/json"; // 提前序列化JSON,也可替换为System.Text.Json避免格式兼容问题 string jsonString = new JavaScriptSerializer().Serialize(inventories); // 手动设置ContentLength避免部分服务端校验失败 request.ContentLength = jsonString.Length; using (var streamWriter = new StreamWriter(request.GetRequestStream())) { streamWriter.Write(jsonString); // 写入完成后先清空缓冲区、关闭写入流再发起请求 streamWriter.Flush(); streamWriter.Close(); } // 流写入完成后再获取响应 var httpResponse = (HttpWebResponse)request.GetResponse(); using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) { var result = streamReader.ReadToEnd(); var pass = result.ToString(); } return inventories; }
2. (可选)替换序列化方式对齐服务端规则
// 使用System.Text.Json序列化,和服务端默认驼峰规则对齐 using System.Text.Json; using System.Text.Json.Serialization; string jsonString = JsonSerializer.Serialize(inventories, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
3. 清理冗余路由
[HttpPost] [Route("[action]")] // 仅保留该配置即可匹配api/Sale/Test路由 public string Test([FromBody] Inventory[] inventories) { return "Found me"; }
调试建议
如果修改后还有问题,可以用抓包工具查看实际发送的请求体内容、请求头是否符合预期,也可以在服务端接口处打断点查看参数绑定的具体错误信息。
内容的提问来源于stack exchange,提问作者Johandre
相关产品推荐
相关产品推荐

