Render view to string followed by redirect results in exception
- by Chris Charabaruk
So here's the issue: I'm building e-mails to be sent by my application by rendering full view pages to strings and sending them. This works without any problem so long as I'm not redirecting to another URL on the site afterwards. Whenever I try, I get "System.Web.HttpException: Cannot redirect after HTTP headers have been sent."
I believe the problem comes from the fact I'm reusing the context from the controller action where the call for creating the e-mail comes from. More specifically, the HttpResponse from the context. Unfortunately, I can't create a new HttpResponse that makes use of HttpWriter because the constructor of that class is unreachable, and using any other class derived from TextWriter causes response.Flush() to throw an exception, itself.
Does anyone have a solution for this?
public static string RenderViewToString(
ControllerContext controllerContext,
string viewPath,
string masterPath,
ViewDataDictionary viewData,
TempDataDictionary tempData)
{
Stream filter = null;
ViewPage viewPage = new ViewPage();
//Right, create our view
viewPage.ViewContext = new ViewContext(controllerContext,
new WebFormView(viewPath, masterPath), viewData, tempData);
//Get the response context, flush it and get the response filter.
var response = viewPage.ViewContext.HttpContext.Response;
//var response = new HttpResponseWrapper(new HttpResponse
// (**TextWriter Goes Here**));
response.Flush();
var oldFilter = response.Filter;
try
{
//Put a new filter into the response
filter = new MemoryStream();
response.Filter = filter;
//Now render the view into the memorystream and flush the response
viewPage.ViewContext.View.Render(viewPage.ViewContext,
viewPage.ViewContext.HttpContext.Response.Output);
response.Flush();
//Now read the rendered view.
filter.Position = 0;
var reader = new StreamReader(filter, response.ContentEncoding);
return reader.ReadToEnd();
}
finally
{
//Clean up.
if (filter != null)
filter.Dispose();
//Now replace the response filter
response.Filter = oldFilter;
}
}