To do that, he decide to get string output from the printer friendly action (by combine model + aspx view) and return the output content as binary with a little bit change in content type ("application/vnd.ms-excel")
Unfortunately, ASP NET MVC does not provide any official way to build string content from a View + Model data.
To support him, I read many articles and found a helpful one on Stackoverflow:
http://stackoverflow.com/questions/483091/render-a-view-as-a-string
However, solutions there are not good ways. Why? Actually, they try to use current context to render the view+model. After that, if you try to Redirect or return a FileContentResult or StreamContentResult, you will meet this exception:
Server cannot set content type after HTTP headers have been sent
Or
Server cannot redirect to action after HTTP headers have been sent
So, how to solve this issue? Finally, I found a very stupid but simple solution:
1. Create 2 actions: 1 action for returning Stream content, 1 action to return HTML content from aspx page + model
2. In the returning Stream action, create a HTTP request to the URL of the action that render the HTML for report by System.Net.WebClient => get return HTML
2. Using the return HTML to create the stream + set content type and return to browser
Below is the code
[AcceptVerbs("GET", "POST")] public ActionResult ViewExcelReport(int? month, int? year) { string excelFileStringContent = DownloadReportHTMLContent(month.Value, year.Value); byte[] excelFileBytesContent = this.Response.ContentEncoding.GetBytes (excelFileStringContent); FileContentResult excelFileContentResult = new FileContentResult( excelFileBytesContent, "application/vnd.ms-excel"); return excelFileContentResult; } [AcceptVerbs("GET", "POST")] public ActionResult ViewHTMLReport(int? month, int? year) { PrepareReportData(month.Value, year.Value); return View(); }
private string DownloadReportHTMLContent(int month, int year) { string linkFormat = Url.Action("ViewHTMLReport", "MyReport", null, "http"); linkFormat += "?month={0}&year={1}"; System.Net.WebClient webClient = new System.Net.WebClient(); webClient.Encoding = Encoding.UTF8; return webClient.DownloadString(string.Format(linkFormat, month, year)); }
Is that simple?