【问题标题】:PartialView as string + JsonResultPartialView 作为字符串 + JsonResult
【发布时间】:2009-11-17 12:07:03
【问题描述】:

我只是在寻找一种很好的方法,如何从服务器返回 JSON 对象,其中包含部分视图的 html 和一些额外的数据(如果需要)。

我正在使用approach by Tim Scott 将部分视图呈现为字符串(进行了一些修改 - 使其具有 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(字符串值) +8760264 System.Web.HttpResponseWrapper.set_ContentType(字符串值)+11 System.Web.Mvc.JsonResult.ExecuteResult(ControllerContext 上下文)+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,Func1 continuation) +255 System.Web.Mvc.<>c__DisplayClass13.<InvokeActionResultWithFilters>b__10() +20 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList1 过滤器,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) 在 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

事情是 - 每当我调用 RenderViewToString 时,如果我要返回任何其他不是 ContentResult 的 ActionResult,就会引发异常。

那么 - 还有另一种好方法如何在没有第三方工具的情况下将匿名对象序列化为 Json
OR
如何使这种方法发挥作用(如何杀死该死的异常,
究竟是什么强制发送这些标头)?

【问题讨论】:

  • 我认为 MVC 会缓存输出,因此您可能会调用 Response.Clear() 甚至在将字符串放入内存后也清除 Response.Headers。
  • @Josh 也许我做错了什么 - 但它没有帮助。

标签: asp.net-mvc


【解决方案1】:

使用this 让它工作。

这就是问题所在:

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

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

【讨论】:

  • 这就是我正在经历的。现在必须让它为我自己工作。谢谢
【解决方案2】:

在我看来,您的 RenderViewToString 应该创建一个 ViewUserControl 而不是 ViewPage

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-06
  • 1970-01-01
  • 2011-02-10
  • 1970-01-01
  • 2011-09-15
  • 2013-08-26
相关资源
最近更新 更多