Add API to help set and revert response bodies
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
## Background and Motivation
A very common pattern in ASP.NET Core middleware (and other middleware like components) is to set a temporary response body, execute some user code, then revert to the previous response body when unwinding. The steps go like this:
- Store a reference to the existing body
- Replace the body with the new stream
- Execute user code
- Grab the contents of the body stream and copy it to the previous stream
- Restore the previous body in a finally so exceptional cases are handled
- Don't forget to dispose any streams created
``` C#
app.Use(async (context, next) =>
{
var previous = context.Response.Body;
try
{
using var stream = new FileBufferingWriteStream();
context.Response.Body = stream;
await next();
await stream.CopyToAsync(previous);
}
finally
{
context.Response.Body = previous;
}
});
```
This code today is very manual and we could instead make it a bit more pleasant with some new APIs.
## Proposed API
Please provide the specific public API signature diff that you are proposing. For example:
```diff
namespace Microsoft.AspNetCore.Http
{
public class HttpResponse
{
+ public ResponseBodyScope UseBody(Stream stream);
}
+ public struct ResponseBodyScope : IDisposable, IAsyncDisposable
+ {
+ public Stream PreviousBody { get; }
+ public Stream CurrentBody { get; }
+ public void Dispose();
+ public ValueTask DisposeAsync();
+ }
}
```
## Usage Examples
``` C#
app.Use(async (context, next) =>
{
using var scope = context.Response.UseBody(new FileBufferingWriteStream());
await next();
await scope.CurrentBody.CopyToAsync(scope.PreviousBody);
});
```
## Alternative Designs
An alternative might be an explicit push/pop style API but that wouldn't automagically handle the pop in the failure case.
We may also want to consider a mode that auto-flushes to the previous response body but then failure cases also get weird (did you want to flush the response on failure?)
Contributor guide
Assessment
This issue has not been assessed yet.