No1Lives4Ever
No1Lives4Ever

Reputation: 6883

c#: Return a stream on Web API core

I have an ASP.NET web API server written with C# (v2.2). One of my exposed methods, creating a MemoryStream and adding data into it. In the end, return it with the return File(ms) method.

My code looks like this:

[HttpGet]
[Route("my-endpoint")]
public async Task<ActionResult> TestMe()
{
    MemoryStream ms = new MemoryStream();
    StreamWriter sw = new StreamWriter(ms);
    await sw.WriteLineAsync($"A,B,C").ConfigureAwait(false);
    await sw.WriteLineAsync($"1,2,3").ConfigureAwait(false);
    await sw.FlushAsync().ConfigureAwait(false);
    ms.Seek(0, SeekOrigin.Begin);

    return File(ms, "application/csv");
}

The problem here is that this code not disposing all the stream from the memory for sure. In case that everything was OK, the stream will be closed by the ASP.NET code. If an exception was thrown, the stream won't be disposed.

I thought that the right way to implement it will be (this code is NOT working):

[HttpGet]
[Route("my-endpoint")]
public async Task<ActionResult> TestMe()
{
    using (MemoryStream ms = new MemoryStream())
    using (StreamWriter sw = new StreamWriter(ms))
    {
        await sw.WriteLineAsync($"A,B,C").ConfigureAwait(false);
        await sw.WriteLineAsync($"1,2,3").ConfigureAwait(false);
        await sw.FlushAsync().ConfigureAwait(false);
        ms.Seek(0, SeekOrigin.Begin);

        return File(ms, "application/csv");
    }
}

The problem here is when we are leaving the function (on the return line). Then, the stream will be disposed before being returned to the client.

How to make my code work safely?

Upvotes: 0

Views: 4281

Answers (1)

Sean
Sean

Reputation: 62492

There's nothing wrong with your first method. If the code throws (either in your method or in the asp.net framework) then eventually the stream and writer will be garbage collected.

If nothing goes from then the File class will call Dispose on the memory stream, but as this is just a wrapper over a byte array nothing will really happen until the garbage collector kicks in, so either way your code is fine.

Upvotes: 2

Related Questions