Skip to content

IDISP001 Returning ASP.NET Results.File or Results.Stream #586

@pascal-ws

Description

@pascal-ws

Hey there,

I am using ASP.NET (Core) 8 Minimal Web API.
I have several endpoints that look like the following simple example:

    public static async Task<IResult> GetFile()
    {
        FileStream fileStream1 = File.OpenRead("File.txt");
        return Results.Stream(fileStream1, ContentType.TextPlain, "File.txt");
    }

As you can see the object fileStream1 - which implements IDisposable - is not disposed.

This is because the method Results.Stream states that: "The stream parameter is disposed after the response is sent"
Also, I've tried disposing the stream but then when executing the endpoint the file cannot be read because it's a closed stream.
I've read online that you are not supposed to close the stream when giving it to Results.Stream, so that matches my results.
Same goes for Results.File.

Reference: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.results?view=aspnetcore-8.0

I've added the analyzer and now get a IDISP001 warning everywhere to dispose of the stream, of course.

I could not find a good way to do this so I just used a #pragma warning disable for now but would like to know if there is a better option.
If there is no better option, would it be possible if the analyzer could recognize the usage of Results.Stream or Results.File (maybe others) in the future? I dislike adding that pragma. Of course, same with TypedResults.*.

These are the 3 options I have tried, but only the second one - fileStream2 - works, without disposing the stream directly.

        await using FileStream fileStream1 = File.OpenRead("File.txt");
        return Results.Stream(fileStream1, ContentType.TextPlain, "File.txt");
        
        #pragma warning disable IDISP001
        FileStream fileStream2 = File.OpenRead("File.txt");
        #pragma warning restore IDISP001
        return Results.Stream(fileStream2, ContentType.TextPlain, "File.txt");
        
        await using FileStream fileStream3 = File.OpenRead("File.txt");
        return Results.Stream(async stream => await fileStream3.CopyToAsync(stream), ContentType.TextPlain, "File.txt");

Note: In the third version fileStream3 it states that Captured variable is disposed in the outer scope, so that doesn't work either.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions