File(stream, ...) does not dispose the stream
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [x] I have searched the existing issues
### Describe the bug
Not sure if this is actually a bug or not, but it's a surprise. If this is intended behavior, it needs to be spelled out in the documentation because it violates expectations.
We have code that looks like this:
```
[HttpPost]
public IActionResult Run(ExportRequestModel request) {
var result = this.ExportService.Export(request);
string suffix = "." + result.DefaultExtension;
if (request.FileName?.EndsWith(suffix) == true) {
request.FileName = request.FileName[..^suffix.Length];
}
var name = (request.FileName ?? "export").Replace('.', '_') + suffix;
return File(result.Contents, result.ContentType, name);
}
```
However the stream from ExportService really does need to be disposed. There's a finalizer that will take care of it eventually, but that's unexpected. Making it work:
```
[HttpPost]
public IActionResult Run(ExportRequestModel request) {
var result = this.ExportService.Export(request);
string suffix = "." + result.DefaultExtension;
if (request.FileName?.EndsWith(suffix) == true) {
request.FileName = request.FileName[..^suffix.Length];
}
var name = (request.FileName ?? "export").Replace('.', '_') + suffix;
HttpContext.Response.RegisterForDisposeAsync(result.Contents);
return File(result.Contents, result.ContentType, name);
}
```
Yup. File() doesn't dispose the stream. Surprise!
### Expected Behavior
Option 1) File(stream, ...) disposes the stream
Option 2) Unexpected behavior documented at https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.filestreamresult.-ctor?view=aspnetcore-9.0#microsoft-aspnetcore-mvc-filestreamresult-ctor(system-io-stream-system-string)
### Steps To Reproduce
_No response_
### Exceptions (if any)
_No response_
### .NET Version
8.0.10
### Anything else?
Hand verified by putting a breakpoint in the dispose method.
You don't have to worry about breaking *me* at least; I can handle being double-disposed.
Contributor guide
Assessment
This issue has not been assessed yet.