Di MVC3 Razor, bagaimana cara mendapatkan html tampilan yang diberikan di dalam tindakan?

90

Apakah ada yang tahu cara mendapatkan html yang dihasilkan dari tampilan di dalam suatu tindakan?

Apakah seperti ini:

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

Jawaban:

152

Saya menggunakan metode statis di kelas yang saya sebut Utilities.Commonsaya meneruskan pandangan kembali ke klien sebagai properti objek JSON terus-menerus sehingga saya perlu membuatnya menjadi string. Ini dia:

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

Ini akan berfungsi untuk tampilan penuh serta tampilan parsial, cukup ubah ViewEngines.Engines.FindPartialViewke ViewEngines.Engines.FindView.

Chev
sumber
14
FindView membutuhkan parameter lain ( masterName) yang akan Anda tentukan null. Juga saya sarankan untuk menyimpan dan memulihkan (setelah rendering) controller.ViewData.Model jika metode ini dipanggil pada instance controller saat ini dan model telah ditetapkan sebelum panggilan ini.
Andrei Rînea
4
Anda juga harus memanggil viewResult.ViewEngine.ReleaseView (controller.ControllerContext, viewResult.View)
sjmeverett
3
Ini berfungsi dengan baik, tetapi saya tidak ingin menangkap dan membuat pengecualian dalam kode langsung saya.
pauloya
3
Jika Anda memanggilnya dari dalam pengontrol itu sendiri maka teruskan saja thissebagai argumen pengontrol. RenderPartialViewToString(this, "index", viewModel). Saya pikir itu konyol bahwa tidak ada cara yang lebih mudah untuk hanya memanggil mesin tampilan dan mendapatkan kembali string, tetapi di ASP.NET mesin tampilan perlu referensi ke contoh pengontrol untuk mengkompilasi tampilan. Saya seorang pengembang nodeJS sekarang dan mesin tampilan di node adalah seluruh modul terpisah yang dapat Anda panggil secara manual atau dengan kerangka kerja MVC seperti express .
Chev
5
@PauloManuelSantos Saya setuju dengan Anda. Saya menulis ini bertahun-tahun yang lalu dan saya tidak tahu apa yang saya pikirkan dengan memasukkan penanganan kesalahan dalam jawabannya. Saya telah memperbarui jawaban untuk mengecualikan coba / tangkap. Terima kasih untuk umpan baliknya.
Chev
4

The diterima jawaban dengan @Chev di atas adalah baik, tapi aku ingin membuat hasil yang spesifik tindakan , bukan hanya tertentu pandangan .

Selain itu, saya harus bisa meneruskan parameter ke tindakan itu daripada mengandalkan menyuntikkan model.

Jadi saya datang dengan metode saya sendiri, yang saya masukkan ke dalam kelas dasar pengontrol saya (membuatnya tersedia untuk mereka semua):

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

Misalkan saya memiliki tindakan bernama Fooyang mengambil objek model dan beberapa parameter lain, yang bersama-sama mempengaruhi tampilan apa yang akan digunakan:

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

Sekarang, jika saya ingin mendapatkan hasil dari memanggil tindakan Foo, saya cukup mendapatkan ViewResultdengan memanggil Foometode, dan kemudian memanggil RenderViewResultAsStringuntuk mendapatkan teks HTML:

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

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