我正在寻找一种很好的方法,如何从服务器返回JSON对象,包含部分视图的html和一些额外的数据(如果需要)。
我正在使用approach by Tim Scott将partialview呈现为字符串(通过一些修改 - 使其成为viewenginescollection意识,使其了解视图和局部视图之间的区别,将其放入StringResult类并使用控制器包裹扩展方法)。
这是造成麻烦的原因:
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;
}
}
用法如下:
var v = this.ViewResultToString(PartialView("_Foo", foo));
return Json(new {Html = Server.HtmlEncode(v), Bar = foo.Bar});
然而 - 这引发了一个例外:
在发送HTTP标头后,服务器无法设置内容类型。
这是一个堆栈跟踪:
[HttpException(0x80004005):服务器无法在发送HTTP标头后设置内容类型。 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过滤器,ResultExecutingContext preContext,Func
1 continuation) +255 System.Web.Mvc.<>c__DisplayClass13.<InvokeActionResultWithFilters>b__10() +20 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList
1过滤器,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 c:\ Project \ Controllers \ Base \ BaseController.cs中的Company.UI.Project.Controllers.Base.BaseController.Execute(RequestContext requestContext):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&amp; completedSynchronously)+75
事情是 - 每当我调用RenderViewToString时,如果我要返回任何不是ContentResult的其他ActionResult,则会抛出异常。
那么 - 如果没有第三方工具,如何将匿名对象序列化为Json还有另外一种很好的方法
或
如何使这种方法工作(如何杀死该死的例外,
究竟是什么强制要发送这些标题?)
答案 0 :(得分:2)
使用this了解它。
这就是问题:
在第一种情况下,使用“捕获过滤器”拦截输出到HttpResponse会强制您在渲染整个视图之前刷新输出,并且由于使用了原始的HttpResponse对象,因此不允许您更改内容编码,mime类型或在渲染局部视图后添加标题。
解决方案 - 不要使用'刷新'技术来渲染局部视图。
答案 1 :(得分:1)
在我看来,RenderViewToString
应创建ViewUserControl
而不是ViewPage
。
请注意,在呈现视图后,您正在执行的操作会使任何Action过滤器上的OnResultExecuting
发生!