Search code examples
c#jqueryasp.net-mvcusingmemorystream

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


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);

Solution

  • 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.