Does a MemoryStream get disposed of automatically when returning it as an ActionResult?

Sean Anderson picture Sean Anderson · Jan 10, 2012 · Viewed 8k times · Source
public ActionResult CustomChart(int reportID)
{
    Chart chart = new Chart();

    // Save the chart to a MemoryStream
    var imgStream = new MemoryStream();
    chart.SaveImage(imgStream);
    imgStream.Seek(0, SeekOrigin.Begin);

    // Return the contents of the Stream to the client
    return File(imgStream, "image/png");
}

I am accustomed to using the 'using' statement in conjuction with MemoryStreams. Is this a scenario where the 'using' statement is not necessary? Or is it valid to call return inside of a 'using' statement?

EDIT:

For my purposes I have found that the introduction of a 'using' statement does NOT work (throws an ObjectDisposedException). Here's what I'm doing with it client-side:

$('#ReportTest').bind('load', function () {
                        $('#LoadingPanel').hide();
                        $(this).unbind('load');
                    }).bind('error', function () {
                        $('#LoadingPanel').hide();
                        $(this).unbind('error');
                    }).attr('src', '../../Chart/CustomChart?ReportID=' + settings.id);

Answer

vcsjones picture vcsjones · Jan 10, 2012

Does a MemoryStream get disposed of automatically when returning it as an ActionResult?

Yes, MVC (at least version 3) will clean it up for you. You can take a look at the source of the WriteFile method in FileStreamResult:

protected override void WriteFile(HttpResponseBase response) {
    // grab chunks of data and write to the output stream
    Stream outputStream = response.OutputStream;
    using (FileStream) {
        byte[] buffer = new byte[_bufferSize];

        while (true) {
            int bytesRead = FileStream.Read(buffer, 0, _bufferSize);
            if (bytesRead == 0) {
                // no more data
                break;
            }

            outputStream.Write(buffer, 0, bytesRead);
        }
    }
}

The line using (FileStream) { will place the Stream in a using block, thus Disposing of it when it has written the contents to the Http Response.

You can also verify this behavior by creating a dummy stream that does this:

public class DummyStream : MemoryStream
{
    protected override void Dispose(bool disposing)
    {
        Trace.WriteLine("Do I get disposed?");
        base.Dispose(disposing);
    }
}

So MVC will dispose it.