2009-11-17 5 views
2

Я просто ищу хороший способ вернуть объект JSON с сервера, который содержит html частичного представления и некоторые дополнительные данные, если это необходимо.PartialView as string + JsonResult

Я использую approach by Tim Scott для рендеринга частичного просмотра как строки (с некоторыми изменениями - сделал его доступным для просмотра в представлении), чтобы понять разницу между представлением и частичным представлением, поместить его в класс 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) + 8760264 System.Web.HttpResponseWrapper.set_ContentType (строковое значение) +11 System.Web.Mvc.JsonResult.ExecuteResult (ControllerContext контекст) +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, 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 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 .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, исключение будет быть брошенным, если я собираюсь вернуть любой другой ActionResult, который не является ContentResult.

Так что - есть еще один хороший способ, как сериализовать анонимный объект в Json без инструментов 3 участника
ИЛИ
, как сделать этот подход к работе (как убить это проклятое исключение,
, что именно заставляют тех, заголовки для отправки)?

+0

Я думаю, что MVC кэширует вывод, поэтому вы можете вызвать Response.Clear() и даже очистить Response.Headers тоже после того, как вы получите эту строку в памяти. –

+0

@ Возможно, я делаю что-то неправильно, но это не помогло. –

ответ

2

Получил его, используя this.

Это была проблема:

В первом случае, перехватывая вывод HttpResponse с помощью «захвата фильтра» заставляет вас удалить вывод, прежде чем вся точка зрения оказывается и, так как исходный объект HttpResponse , не позволяет вам изменять кодировку содержимого, тип mime или добавлять заголовки после визуализации частичного представления.

Решение - не использовать технику «промывки» для частичного просмотра.

+0

Это то, что я переживаю. Теперь нужно заставить его работать для себя. Спасибо –

+0

@ Кирилл Я рад, что это помогло. –

1

Мне кажется, что ваш RenderViewToString должен создавать ViewUserControl, а не ViewPage.

Обратите внимание, что то, что вы делаете, сделает на любых фильтрах действий. после вид выдается!

+0

На данный момент - расследование этого = = http://www.klopfenstein.net/lorenz.aspx/render-partial-view-to-string-in-asp-net-mvc Выглядит многообещающе. –