I'm just looking for a nice way how to return JSON object from server that contains html of partial view and some additional data if needed.
I'm using approach by Tim Scott to render partialview as string (with some modifications - made it to be viewenginescollection aware, made it to understand difference between view and partial view, put it into StringResult class and wrapped around with controller extension method).
Here's what causes trouble:
public static string RenderViewToString(ControllerContext controllerContext,
IView view, ViewDataDictionary viewData, TempDataDictionary tempData)
{
Stream filter = null;
ViewPage viewPage =
new ViewPage
{
ViewContext = new ViewContext
(controllerContext, view, viewData, tempData)
};
//Right, create our view
//Get the response context, flush it and get the response filter.
var response = viewPage.ViewContext.HttpContext.Response;
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;
}
}
usage looks like this:
var v = this.ViewResultToString(PartialView("_Foo", foo));
return Json(new {Html = Server.HtmlEncode(v), Bar = foo.Bar});
However - this throws an exception:
Server cannot set content type after HTTP headers have been sent.
Here's a stack trace:
[HttpException (0x80004005): Server cannot set content type after HTTP headers have been sent.] System.Web.HttpResponse.set_ContentType(String value) +8760264 System.Web.HttpResponseWrapper.set_ContentType(String value) +11 System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext context) +131 System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +10 System.Web.Mvc.<>c__DisplayClass11.b__e() +20 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func
1 continuation) +255 System.Web.Mvc.<>c__DisplayClass13.<InvokeActionResultWithFilters>b__10() +20 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList
1 filters, ActionResult actionResult) +179 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +395 System.Web.Mvc.Controller.ExecuteCore() +123 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +23 Company.UI.Project.Controllers.Base.BaseController.Execute(RequestContext requestContext) in c:\Project\Controllers\Base\BaseController.cs:109 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +144 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +54 System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +7 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75
Thing is - whenever i call RenderViewToString, an exception will be thrown if I'm going to return any other ActionResult that's not ContentResult.
So - is there another nice way how to serialize anonymous object into Json without 3rd party tools
OR
how to make this approach to work (how to kill that damn exception,
what exactly forces those headers to be sent)?