Как в MVC3 Razor получить html визуализированного представления внутри действия?

90

Кто-нибудь знает, как получить сгенерированный html представления внутри действия?

Это примерно так:

public ActionResult Do()
{
    var html = RenderView("hello", model);
...
}
Ому
источник

Ответы:

152

Я использую статический метод в классе, который я назвал. Utilities.CommonЯ постоянно передаю представления обратно клиенту в качестве свойств объектов JSON, поэтому мне нужно было преобразовать их в строку. Вот и все:

public static string RenderPartialViewToString(Controller controller, string viewName, object model)
{
    controller.ViewData.Model = model;
    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.ToString();
    }
}

Это будет работать как для полных, так и для частичных просмотров, просто измените ViewEngines.Engines.FindPartialViewна ViewEngines.Engines.FindView.

Чев
источник
14
FindView нужен еще один параметр ( masterName), который вы должны указать null. Также я рекомендую сохранить и восстановить (после рендеринга) controller.ViewData.Model в случае, если метод вызывается в текущем экземпляре контроллера и модель была назначена до этого вызова.
Андрей Рыня
4
Вы также должны вызвать viewResult.ViewEngine.ReleaseView (controller.ControllerContext, viewResult.View)
sjmeverett
3
Он отлично работает, но я бы не хотел перехватывать и отображать исключения в моем живом коде.
pauloya
3
Если вы вызываете его из самого контроллера, просто передайте его thisв качестве аргумента контроллера. RenderPartialViewToString(this, "index", viewModel). Я действительно считаю глупым то, что нет более простого способа просто вызвать механизм представления и вернуть строку, но в ASP.NET механизму представления требуется ссылка на экземпляр контроллера для компиляции представления. Сейчас я разработчик nodeJS, и механизмы просмотра в node - это целые отдельные модули, которые вы можете вызывать вручную или с помощью инфраструктуры MVC, такой как express .
Chev
5
@PauloManuelSantos Я согласен с вами. Я написал это много лет назад и не знаю, о чем думал, включив в ответ обработку ошибок. Я обновил ответ, чтобы исключить попытку / уловку. Спасибо за ответ.
Chev
4

Принятый ответ @Chev выше хорош, но я хотел отобразить результат определенного действия , а не только конкретное представление .

Кроме того, мне нужно было передать параметры этому действию, а не полагаться на внедрение модели.

Итак, я придумал свой собственный метод, который я поместил в базовый класс своих контроллеров (делая его доступным для всех):

    protected string RenderViewResultAsString(ViewResult viewResult)
    {
        using (var stringWriter = new StringWriter())
        {
            this.RenderViewResult(viewResult, stringWriter);

            return stringWriter.ToString();
        }
    }

    protected void RenderViewResult(ViewResult viewResult, TextWriter textWriter)
    {
        var viewEngineResult = this.ViewEngineCollection.FindView(
            this.ControllerContext, 
            viewResult.ViewName, 
            viewResult.MasterName);
        var view = viewEngineResult.View;

        try
        {
            var viewContext = new ViewContext(
                this.ControllerContext, 
                view, 
                this.ViewData, 
                this.TempData, 
                textWriter);

            view.Render(viewContext, textWriter);
        }
        finally
        {
            viewEngineResult.ViewEngine.ReleaseView(this.ControllerContext, view);
        }
    }

Предположим, у меня есть вызываемое действие, Fooкоторое принимает объект модели и некоторые другие параметры, которые вместе влияют на то, какое представление будет использоваться:

    public ViewResult Foo(MyModel model, int bar)
    {
        if (bar == 1)
            return this.View("Bar1");
        else
            return this.View("Bar2", model);
    }

Теперь, если я хочу получить результат вызова действия Foo, я могу просто получить его ViewResult, вызвав Fooметод, а затем позвонить RenderViewResultAsStringдля получения текста HTML:

    var viewResult = this.Foo(model, bar);

    var html = this.RenderViewResultAsString(viewResult);
Гэри МакГилл
источник