PartialView как строка + JsonResult - PullRequest
2 голосов
/ 17 ноября 2009

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

Я использую подход Тима Скотта , чтобы визуализировать частичное представление как строку (с некоторыми изменениями - сделано так, чтобы оно учитывало представление 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, фильтры 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.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, логическое и завершено синхронно) + 75

Дело в том, что всякий раз, когда я вызываю RenderViewToString, генерируется исключение, если я собираюсь вернуть любой другой ActionResult, который не является ContentResult.

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

Ответы [ 2 ]

2 голосов
/ 17 ноября 2009

Получил работу, используя this .

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

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

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

1 голос
/ 17 ноября 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...