Trong MVC3 Razor, làm cách nào để lấy html của một chế độ xem được kết xuất bên trong một hành động?


90

Có ai biết cách lấy html được tạo của một chế độ xem bên trong một hành động không?

Nó giống như thế này:

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

Câu trả lời:


152

Tôi sử dụng một phương thức tĩnh trong một lớp mà tôi gọi là Utilities.Commontôi chuyển các khung nhìn trở lại máy khách dưới dạng thuộc tính của các đối tượng JSON liên tục vì vậy tôi cần phải kết xuất chúng thành một chuỗi. Đây rồi:

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

Điều này sẽ hoạt động đối với chế độ xem toàn bộ cũng như chế độ xem một phần, chỉ cần thay đổi ViewEngines.Engines.FindPartialViewthành ViewEngines.Engines.FindView.


14
FindView cần một tham số khác ( masterName) mà bạn sẽ chỉ định null. Ngoài ra, tôi khuyên bạn nên lưu và khôi phục (sau khi kết xuất) controller.ViewData.Model trong trường hợp phương thức được gọi trên phiên bản bộ điều khiển hiện tại và mô hình đã được chỉ định trước cuộc gọi này.
Andrei Rînea

4
Bạn cũng nên gọi viewResult.ViewEngine.ReleaseView (controller.ControllerContext, viewResult.View)
sjmeverett

3
Nó hoạt động tốt, nhưng tôi không muốn bắt và đưa ra các ngoại lệ trong mã trực tiếp của mình.
pauloya

3
Nếu bạn đang gọi nó từ bên trong chính bộ điều khiển thì chỉ cần chuyển thislàm đối số bộ điều khiển. RenderPartialViewToString(this, "index", viewModel). Tôi nghĩ thật là ngớ ngẩn khi không có cách nào dễ dàng hơn để gọi công cụ xem và lấy lại một chuỗi, nhưng trong ASP.NET, công cụ xem cần tham chiếu đến cá thể bộ điều khiển để biên dịch chế độ xem. Bây giờ tôi là một nhà phát triển nodeJS và các công cụ xem trong node là toàn bộ các mô-đun riêng biệt mà bạn có thể gọi theo cách thủ công hoặc với một khuôn khổ MVC như express .
Chev

5
@PauloManuelSantos Tôi đồng ý với bạn. Tôi đã viết điều này nhiều năm trước và tôi không biết mình đang nghĩ gì khi bao gồm xử lý lỗi trong câu trả lời. Tôi đã cập nhật câu trả lời để loại trừ thử / bắt. Cảm ơn vì bạn đã phản hồi.
Chev

4

Câu trả lời được chấp nhận bởi @Chev ở trên là tốt, nhưng tôi muốn hiển thị kết quả của một hành động cụ thể , không chỉ một chế độ xem cụ thể .

Ngoài ra, tôi cần có khả năng truyền các tham số cho hành động đó thay vì dựa vào việc đưa vào một mô hình.

Vì vậy, tôi đã nghĩ ra phương pháp của riêng mình, mà tôi đặt vào lớp cơ sở của bộ điều khiển của mình (cung cấp cho tất cả chúng):

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

Giả sử tôi có một hành động được gọi là Foolấy một đối tượng mô hình và một số tham số khác, cùng ảnh hưởng đến chế độ xem sẽ được sử dụng:

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

Bây giờ, nếu tôi muốn nhận kết quả của hành động gọi Foo, tôi có thể chỉ cần lấy ViewResultbằng cách gọi Foophương thức, sau đó gọi RenderViewResultAsStringđể nhận văn bản HTML:

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

    var html = this.RenderViewResultAsString(viewResult);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.