2009-11-17 56 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