PartialView as string + JsonResult

时间:2009-11-17 12:07:03

标签: asp.net-mvc

我正在寻找一种很好的方法,如何从服务器返回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。&lt;&gt; 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还有另外一种很好的方法
如何使这种方法工作(如何杀死该死的例外,
究竟是什么强制要发送这些标题?)

2 个答案:

答案 0 :(得分:2)

使用this了解它。

这就是问题:

  

在第一种情况下,使用“捕获过滤器”拦截输出到HttpResponse会强制您在渲染整个视图之前刷新输出,并且由于使用了原始的HttpResponse对象,因此不允许您更改内容编码,mime类型或在渲染局部视图后添加标题。

解决方案 - 不要使用'刷新'技术来渲染局部视图。

答案 1 :(得分:1)

在我看来,RenderViewToString应创建ViewUserControl而不是ViewPage

请注意,在呈现视图后,您正在执行的操作会使任何Action过滤器上的OnResultExecuting发生