Asp.net core 在ASP.NET Core中禁用分块

Asp.net core 在ASP.NET Core中禁用分块,asp.net-core,asp.net-core-mvc,azure-web-app-service,Asp.net Core,Asp.net Core Mvc,Azure Web App Service,我正在使用ASP.NET核心Azure Web应用程序向客户端提供RESTful API,但客户端无法正确处理分块 是否可以在控制器级别或web.config文件中完全关闭传输编码:chunked 我返回的JsonResult有点像这样: [HttpPost] [Produces("application/json")] public IActionResult Post([FromBody] AuthRequest RequestData) { AuthResult

我正在使用ASP.NET核心Azure Web应用程序向客户端提供RESTful API,但客户端无法正确处理分块

是否可以在控制器级别或web.config文件中完全关闭
传输编码:chunked

我返回的JsonResult有点像这样:

[HttpPost]
[Produces("application/json")]
public IActionResult Post([FromBody] AuthRequest RequestData)
{
    AuthResult AuthResultData = new AuthResult();

    return Json(AuthResultData);
}

在ASP.NET Core中,这似乎可以跨主机工作:

response.Headers["Content-Encoding"] = "identity";
response.Headers["Transfer-Encoding"] = "identity";
指示标识功能(即无压缩,或 修改)。除非明确指定,否则此标记始终为 认为可以接受

当您显式禁用响应缓冲时,这也会起作用:

var bufferingFeature = httpContext.Features.Get<IHttpBufferingFeature>();
bufferingFeature?.DisableResponseBuffering();
var bufferingFeature=httpContext.Features.Get();
bufferingFeature?.DisableResponseBuffering();

它在.NET Core 2.0中工作。在将结果写入响应体流之前,只需设置
ContentLength

在startup类中:

app.Use(async (ctx, next) =>
{
    var stream = new xxxResultTranslatorStream(ctx.Response.Body);
    ctx.Response.Body = stream;

    await Run(ctx, next);

    stream.Translate(ctx);
    ctx.Response.Body = stream.Stream;
});
在xxxResultTranslatorStream中:

ctx.Response.Headers.ContentLength = 40;
stream.Write(writeTargetByte, 0, writeTargetByte.Length);

如何在.NET Core 2.2中消除分块:

诀窍是将响应体读入您自己的MemoryStream,这样您就可以得到长度。一旦您这样做了,您就可以设置内容长度头,IIS就不会将其分块。我想这也适用于Azure,但我还没有测试过

以下是中间件:

public class DeChunkerMiddleware
{
    private readonly RequestDelegate _next;

    public DeChunkerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        var originalBodyStream = context.Response.Body;
        using (var responseBody = new MemoryStream())
        {
            context.Response.Body = responseBody;
            long length = 0;
            context.Response.OnStarting(() =>
            {
                context.Response.Headers.ContentLength = length;
                return Task.CompletedTask;
            });
            await _next(context);

            // If you want to read the body, uncomment these lines.
            //context.Response.Body.Seek(0, SeekOrigin.Begin);
            //var body = await new StreamReader(context.Response.Body).ReadToEndAsync();

            length = context.Response.Body.Length;
            context.Response.Body.Seek(0, SeekOrigin.Begin);
            await responseBody.CopyToAsync(originalBodyStream);
        }
    }
}
然后将其添加到启动中:

app.UseMiddleware<DeChunkerMiddleware>();
app.UseMiddleware();

它需要在app.UseMvC()之前

我发现,如果我从Get()返回一个文件流并让ASP.NET处理其余的问题,我的所有分块问题都会消失


如果你放弃控制并信任他们,微软的软件往往工作得最好。如果你真的试图控制流程,它的效果往往最差。

你在响应中有“内容长度”标题吗?我已经添加了一个我的操作的示例。我没有添加这个标题,因为我不知道Json将产生多长时间。以前,ASP已经添加了这个头,但在最近的服务器上它不再这样做了(可能是因为移动到RC2),您可以通过响应缓冲来实现这一点:有趣的是,它可以在本地服务器上工作,但不能在Azure中工作。我猜
服务器:Kestrel
服务器:Microsoft IIS/8.0
之间有什么区别?你找到解决方案了吗?我也有同样的问题,在我的本地VS上有效,但在我将其部署到Azure应用程序服务时不起作用。这很好,但运行方法是什么?对于我来说,这只是一个提示,使用ASP.Net Core 2.2,这两种解决方案都不起作用。添加这些头会导致我的客户端出现一种冻结的响应,而响应的主体是空的。mono droid 1.2中的一个bug修复得很好&尽管我认为在读取和复制整个响应时不可避免地会在内存和处理方面产生一些开销。只是好奇你是否尝试过基准测试?我已经实现了这一点,但添加了逻辑,这样我只在传入请求存在“nochunk”头时才这样做,这样客户端就可以请求一个“未分块”响应,所以我不会强制所有客户端都生活在一个未分块的环境中。不要使用OnStarting设置内容长度,在CopyToAsync之前设置它。