File download issue with Sitecore MVC and resolution

The problem:

while working on the requirement of downloading calendar item(.ics) for an event on the site, I struck with the below given error.

OutputStream is not available when a custom TextWriter is used.

OutputStream is not available when a custom TextWriter is used.
Sitecore MVC error for File as ActionResult for post action

 

Steps to reproduce issue/problem

  1. Using Sitecore MVC form to do the form posting
 @using (Html.BeginRouteForm(Sitecore.Mvc.Configuration.MvcSettings.SitecoreRouteName, FormMethod.Post))
 {
     @Html.Sitecore().FormHandler("SeminarWebinarEvent", "DownloadCalendar")
     @Html.Hidden("eventId", @eventObj.Id.ToString())
     <button type="submit">Add to Calender</button>
 }
  1. Controller Post Action
 [HttpPost]
 public ActionResult DownloadCalendar(string eventId)
 {
     var eventItem = Sitecore.Context.Database.GetItem(new ID(eventId));
     if (eventItem == null)
     {
         //// TODO : Put the code for the error handling
     }

     //// get file stream
     var fileStream = this.eventService.GetCalendarFileStream(eventItem);
     return File(fileStream , "text/calendar", string.Format("{0}.ics", eventItem.Name));
 }
  1. Finally, Click on the Download link of the rendering on the page.

Root Cause

For the fix and the root cause I took the help of the God (not the real almighty but Google ;-)). I found that because of the basic page architecture of Sitecore, the page rendering has already started before the rendering control action returns the file response.

Solution :

After applying couple of different solutions(every time with fingers crossed), I found below given solution much handy and does the job. The solution is much simple and easy to implement.
In this case we need to split the whole action into two different actions like shown in below steps.

  1. Step 1

Put the logic of creating file stream in one action

 [HttpPost]
 public ActionResult DownloadCalendar(string eventId)
     {
          var eventItem = Sitecore.Context.Database.GetItem(new ID(eventId));
          if (eventItem == null)
          {
              //// TODO : Put the code for the error handling
          }

          //// read the file stream in the string format
          var fileStream = this.eventService.GetCalendarFileStream(eventItem);
          //// due to limitation of sitecore MVC redirect to the different action which is responsible for actual download
          return RedirectToAction("ActualCalenderDownload", new { fileString = fileStream, fileName = eventItem["Name"] });
        }
  1. Step 2

At the end of the action redirect to another action which is actually responsible for downloading the file.

  1. Step 3

Create the new action which takes the file stream from above action and returns the fileResult

 [HttpGet]
 public ActionResult ActualCalenderDownload(string fileString, string fileName)
 {
      if (string.IsNullOrWhiteSpace(fileString))
      {
          //// TODO : Put the code for the error handling
      }

      return File(Encoding.UTF8.GetBytes(fileString), "text/calendar", string.Format("{0}.ics", fileName));
 }

Happy Coding 🙂

Sitecore controller rendering action results – what can I return?

Advertisements

Published by

Parag Daraji

Working with Sitecore more than 6 year from now and in total around 10+ years of experience working on Microsoft web technologies. Challenges are something which keeps me motivated and keep me moving. I am Sitecore Certified Professional Developer as well as Microsoft Certified Professional Developer. Feel free to contact me for your Sitecore or Web Development Queries.

4 thoughts on “File download issue with Sitecore MVC and resolution”

    1. Yeah, even after 6 years working on Sitecore, it still surprise me ….!!! But, I like surprises. Think life without surprises….!!! Thanks for your comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s