Search code examples
c#asp.net-core.net-6.0asp.net-core-middleware

Rewriting ASP.NET Core response duplicates the content instead of replacing the original stream


I have an ASP.NET Core application with a custom middleware designed to replace some external CDN links. The middleware correctly updates the response body with the new data, but keeps appending it to the old version. It effectively shows two web pages (the original followed by the modified page).

This is the code for the middleware:

public async Task InvokeAsync(HttpContext context)
{
    using var buffer = new MemoryStream();
    var originalStream = context.Response.Body;
    context.Response.Body = buffer;

    await _next.Invoke(context);

    buffer.Seek(0, SeekOrigin.Begin);

    // Rewrite the body content
    var bufferReader = new StreamReader(buffer);
    string body = await bufferReader.ReadToEndAsync();
    var modifiedBody = RewriteCdnUrls(body);

    // Replace the old content
    await context.Response.WriteAsync(modifiedBody);
    context.Response.Body.Seek(0, SeekOrigin.Begin);

    await context.Response.Body.CopyToAsync(originalStream);
    context.Response.Body = originalStream;
}

I must be missing something fairly obvious but I just can't seem to see it at the moment.


Solution

  • You need to Clear the response

    public async Task InvokeAsync(HttpContext context)
    {
        using var buffer = new MemoryStream();
        var originalStream = context.Response.Body;
        context.Response.Body = buffer;
    
        await _next.Invoke(context);
    
        buffer.Seek(0, SeekOrigin.Begin);
    
        // Rewrite the body content
        var bufferReader = new StreamReader(buffer);
        string body = await bufferReader.ReadToEndAsync();
        var modifiedBody = RewriteCdnUrls(body);
    
        // this line below
        context.Response.Clear(); 
        // this line above
    
        // Replace the old content
        await context.Response.Body.CopyToAsync(originalStream);
        context.Response.Body = originalStream;
    }