在ASP.NET Core 6 Web API中阻止分块传输

后端开发 2026-07-11

我有一个遗留的ASP.NET Core 6 Web API程序,由于内部业务原因,无法升级到更新的版本。我收到一个 POST 请求,并在响应体中返回一个JSON响应。

在较新的版本(例如.NET 8)中,我可以使用:

var updatedJsonObject = JsonConvert.SerializeObject(status, new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver()
});
string response = updatedJsonObject.ToString();
return Results.Text(response, "application/json");

它能够正确设置 Content-Length 头,并且不会返回分块响应。我可以手动设置 Content-Length 头,但总是错的,因为.NET系统会自动向响应体中添加内容:

"contentType":"application/json","statusCode":null

因此,基本上是在把我的JSON对象包裹在一个包装器中,并添加它自己的属性。

应该得到的是:

{ "status": "OK" }

但实际得到的是:

{ "content": "{ "status": "OK" }", "contentType": "application/json", "statusCode": null }

如何在响应体中返回已经创建好的原始JSON字符串,而不被.NET增加任何内容,并防止API发送分块响应?

在一个ASP.NET Core 8项目中,这一做法可以完美工作,但我正在尝试更新一个使用.NET 6的遗留项目,但我无法升级。

该Web API使用Kestrel,签名如下:

[HttpPost]
public async Task<IResult> Post()

我尝试过使用 Results.ContentResults.OkResults.Json 等等。它们都会把响应体包装到它们自己的JSON属性中。

之所以不能使用分块,是因为与之通信的设备是资源受限的嵌入式系统。它们没有运行.NET代码的条件。它们用C 语言编写。它们依赖Content-Length来完整处理服务器的响应。使用分块编码时,设备无法处理响应,因为Content-Length是不确定的。反斜杠来自从Postman复制粘贴时。没有流式传输的需求;消息很小。

使用.NET 8的工作项目不会以分块方式发送结果,并且具有正确的Content-Length。只是想在这个.NET 6版本中实现同样的行为。

解决方案

你在控制器中返回一个类型 Results.Text,这会导致ASP.NET Core MVC将 IResult 对象本身序列化,而不是你打算的数据。基本上,MVC正在序列化 TextHttpResult 对象,而不是执行它。

在你的控制器中,你有:

[HttpPost]
public async Task<IResult> Post()

这告诉ASP.NET Core将 IResult 视为要序列化的返回值,而不是要执行的内容。因此,它会序列化对象,而不是返回JSON字符串:

TextHttpResult { Content, ContentType, StatusCode }

解决办法是返回 ContentResult 而不是 IResult

[HttpPost]
public IActionResult Post()
{
    var updatedJson = JsonConvert.SerializeObject(status,
        new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });

    return Content(updatedJson, "application/json");
}
  • 输出原始JSON字符串
  • ASP.NET Core不对任何内容进行包装
  • 自动设置 Content-Length
  • 除非你手动进行流式传输,否则不会分块

另外,如果你打算保持异步,可以像下面这样改为异步:

[HttpPost]
public async Task<IActionResult> Post()
{
    var status = new { status = "OK" };

    var updatedJson = JsonConvert.SerializeObject(
        status,
        new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        });

    // Simulate async work if needed
    await Task.Yield();

    return Content(updatedJson, "application/json");
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章