Як отримати в HTML 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), який ви вказали б як нульовий. Також я рекомендую зберегти та відновити (після рендерингу) 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 Я згоден з вами. Я писав це багато років тому, і не знаю, про що думав, включивши у відповідь обробку помилок. Я оновив відповідь, щоб виключити функцію try / catch. Дякуємо за відгук.
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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.