Wie erhalte ich in MVC3 Razor das HTML einer gerenderten Ansicht innerhalb einer Aktion?

90

Weiß jemand, wie man das generierte HTML einer Ansicht innerhalb einer Aktion erhält?

Ist es so etwas:

public ActionResult Do()
{
    var html = RenderView("hello", model);
...
}
Omu
quelle

Antworten:

152

Ich verwende eine statische Methode in einer Klasse, die ich aufgerufen habe. Utilities.CommonIch übergebe Ansichten als Eigenschaften von JSON-Objekten ständig an den Client zurück, sodass ich sie in eine Zeichenfolge rendern musste. Hier gehts:

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();
    }
}

Dies funktioniert sowohl für Vollansichten als auch für Teilansichten. Wechseln Sie einfach ViewEngines.Engines.FindPartialViewzu ViewEngines.Engines.FindView.

Chev
quelle
14
FindView benötigt einen anderen Parameter ( masterName), den Sie null angeben würden. Außerdem empfehle ich, controller.ViewData.Model (nach dem Rendern) zu speichern und wiederherzustellen, falls die Methode für die aktuelle Controller-Instanz aufgerufen wird und das Modell vor diesem Aufruf zugewiesen wurde.
Andrei Rînea
4
Sie sollten auch viewResult.ViewEngine.ReleaseView (controller.ControllerContext, viewResult.View)
sjmeverett
3
Es funktioniert großartig, aber ich möchte keine Ausnahmen in meinem Live-Code abfangen und rendern.
Pauloya
3
Wenn Sie es aus dem Controller heraus aufrufen, übergeben Sie es einfach thisals Controller-Argument. RenderPartialViewToString(this, "index", viewModel). Ich finde es albern, dass es keinen einfacheren Weg gibt, die View Engine einfach aufzurufen und eine Zeichenfolge zurückzugewinnen, aber in ASP.NET benötigt die View Engine einen Verweis auf die Controller-Instanz, um die View zu kompilieren. Ich bin jetzt ein NodeJS-Entwickler und View Engines in Node sind ganze separate Module, die Sie manuell oder mit einem MVC-Framework wie Express aufrufen können .
Chev
5
@PauloManuelSantos Ich stimme dir zu. Ich habe vor Jahren geschrieben und weiß nicht, was ich gedacht habe, indem ich die Fehlerbehandlung in die Antwort aufgenommen habe. Ich habe die Antwort aktualisiert, um den Versuch / Fang auszuschließen. Danke für die Rückmeldung.
Chev
4

Die akzeptierte Antwort von @Chev oben ist gut, aber ich wollte das Ergebnis einer bestimmten Aktion wiedergeben , nicht nur einer bestimmten Ansicht .

Außerdem musste ich in der Lage sein, Parameter an diese Aktion zu übergeben, anstatt mich auf das Injizieren eines Modells zu verlassen.

Also habe ich mir eine eigene Methode ausgedacht, die ich in die Basisklasse meiner Controller eingefügt habe (um sie allen zur Verfügung zu stellen):

    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);
        }
    }

Angenommen, ich habe eine Aktion namens Foo, die ein Modellobjekt und einige andere Parameter verwendet, die zusammen beeinflussen, welche Ansicht verwendet wird:

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

Wenn ich nun das Ergebnis des Aufrufs von action erhalten möchte Foo, kann ich das einfach ViewResultdurch Aufrufen der FooMethode abrufen und dann aufrufen RenderViewResultAsString, um den HTML-Text abzurufen:

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

    var html = this.RenderViewResultAsString(viewResult);
Gary McGill
quelle