2009-11-17 82 views
2

我只是寻找一个很好的方式如何从服务器返回包含部分视图的HTML和一些额外的数据,如果需要的JSON对象。部分视图作为字符串+ JsonResult

我使用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(字符串值)+ 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 Sys tem.Web.Mvc。 <> c__DisplayClass11.b__e()20 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter滤波器,ResultExecutingContext preContext,函数功能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 Company.UI.Project.Controllers.Base.BaseController.Execute( RequestContext requestContext)中的System.Web.Mvc.MvcHandler .ProcessR eQUEST的(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步骤,布尔& completedSynchronously)75

事情是 - 每当我打电话RenderViewToString,异常将如果我要返回任何不是ContentResult的其他ActionResult,就会抛出它。

所以 - 有另一种很好的方式,如何序列匿名对象转换为JSON没有第三方工具
OR
如何使这种方法的工作(如何杀了那个该死的例外,
究竟是什么迫使那些标题被发送)?

+0

我想MVC缓存输出,所以你可能会调用Response.Clear(),甚至在内存中获取该字符串后也清除Response.Headers。 – 2009-11-17 12:15:11

+0

@Josh也许我做错了什么 - 但它没有帮助。 – 2009-11-17 13:01:02

回答

2

它使用this工作。

这是问题:

在第一种情况下,使用你一个“捕获过滤器”的力来刷新输出的输出截取到的HttpResponse整个视图被呈现,并且由于原始HttpResponse对象之前被使用,不允许你改变内容编码,MIME类型或在部分视图被渲染后添加标题。

解决方法 - 不要使用“冲洗”技术来渲染局部视图。

+0

这就是我正在经历的。现在必须让它为我自己工作。谢谢 – 2010-01-07 11:34:44

+0

@Cyril我很高兴它有帮助。 – 2010-01-07 11:56:36

1

对我来说好像你的RenderViewToString应该是创建一个ViewUserControl而不是一个ViewPage

请注意,您正在做的事情将使OnResultExecuting上的任何动作过滤器发生视图呈现!

+0

目前 - 调查这一个=> http://www.klopfenstein.net/lorenz.aspx/render-partial-view-to-string-in-asp-net-mvc看起来很有希望。 – 2009-11-17 13:40:34

相关问题