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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 22:06:03