ใน 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.FindPartialViewViewEngines.Engines.FindView


14
FindView ต้องการพารามิเตอร์อื่น ( masterName) ซึ่งคุณจะระบุค่าว่าง นอกจากนี้ฉันขอแนะนำให้บันทึกและกู้คืน (หลังจากแสดงผล) คอนโทรลเลอร์ ViewData.Model ในกรณีที่เมธอดถูกเรียกบนอินสแตนซ์คอนโทรลเลอร์ปัจจุบันและโมเดลได้รับการกำหนดก่อนการเรียก
Andrei Rînea

4
คุณควรเรียก viewResult.ViewEngine.ReleaseView (controller.ControllerContext, viewResult.View)
sjmeverett

3
มันใช้งานได้ดี แต่ฉันไม่ต้องการจับและแสดงข้อยกเว้นในโค้ดสดของฉัน
pauloya

3
หากคุณเรียกใช้จากภายในคอนโทรลเลอร์เองให้ส่งผ่านthisเป็นอาร์กิวเมนต์คอนโทรลเลอร์ RenderPartialViewToString(this, "index", viewModel). ฉันคิดว่ามันโง่ที่ไม่มีวิธีที่ง่ายกว่าในการเรียกใช้เอนจินมุมมองและรับสตริงกลับมา แต่ใน ASP.NET เอ็นจิ้นมุมมองต้องการการอ้างอิงไปยังอินสแตนซ์คอนโทรลเลอร์เพื่อรวบรวมมุมมอง ฉันพัฒนา nodeJS ในขณะนี้และดูเครื่องมือในโหนดเป็นโมดูลที่แยกต่างหากทั้งหมดที่คุณสามารถเรียกใช้ด้วยตนเองหรือกับกรอบ MVC เช่นด่วน
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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.