Why does ASP.NET MVC Controller FileStreamResult error on closed stream?

I am trying to return a csv file from an MVC Controller derived from a List. I came up with the following code for controller based on combining what I read from docs and SO questions. I must be missing something because I am getting yellow screen of death with “Cannot access a closed stream”…

public class ConsumersFileController : Controller
{
    private readonly TDCContext _db = new TDCContext();


    public ActionResult Index()
    {
        IEnumerable<Consumer> list = _db.Consumers.ToList();

        //put List in memory stream object
        MemoryStream memoryStream = new MemoryStream();
        using (memoryStream)
        {
            //return memory stream as file stream result:
            using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream, System.Text.Encoding.UTF8, true))
            {
                foreach (var item in list)
                {
                    var itemBytes = item.Serialize();
                    binaryWriter.Write(itemBytes.Length);
                    binaryWriter.Write(itemBytes);

                }

                FileStreamResult fileStream =
                    new FileStreamResult(memoryStream, "application/txt") {FileDownloadName = "zips.csv"};

                return fileStream;
            }
        }
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _db.Dispose();
        }
        base.Dispose(disposing);
    }

}

Here is the stack trace:

[ObjectDisposedException: Cannot access a closed Stream.]
   System.IO.__Error.StreamIsClosed() +59
   System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count) +14731549
   System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase response) +93
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +88
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult) +831
   System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +81
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__1e(IAsyncResult asyncResult) +185
   System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +67
   System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36
   System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +43
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +67
   System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +607
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +134

How can the stream get closed if I am returning the result inside the using block of the stream?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You should remove:

using (memoryStream)

FileStreamResult will dispose memoryStream for you.

The reason that your code doesn’t work is that the actual work that reads from memoryStream is not in your code – it is in MVC code that calls fileStream.WriteFile. But that code is executed somewhere higher up the call stack. And by the time WriteFile is called (which needs memoryStream) you have already disposed it.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x