ASP.NET MVC Razor: Cách hiển thị HTML của Razor Partial View bên trong hành động của bộ điều khiển


97

Cách tạo HTML của một chế độ xem từng phần đã cho trên công cụ xem ASP.NET đã được biết đến .

Nhưng nếu chức năng này được sử dụng trên chế độ xem một phần dao cạo thì nó không hoạt động, vì ngoại lệ cho biết chế độ xem một phần không bắt nguồn từ "UserControl".

Làm thế nào để sửa lỗi kết xuất để hỗ trợ chế độ xem một phần dao cạo?

Tôi cần cái này vì tôi tạo các email tạo thành dạng xem một phần này ...

CẬP NHẬT:

Mã không thành công (@mcl):

public string RenderPartialToString(string controlName, object viewData)
    {
        ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
        viewPage.Url = this.GetUrlHelper();

        string fullControlName = "~/Views/Email/" + controlName + ".ascx";

        viewPage.ViewData = new ViewDataDictionary(viewData);
        viewPage.Controls.Add(viewPage.LoadControl(fullControlName));

        StringBuilder sb = new StringBuilder();
        using (StringWriter sw = new StringWriter(sb))
        {
            using (HtmlTextWriter tw = new HtmlTextWriter(sw))
            {
                viewPage.RenderControl(tw);
            }
        }
        return sb.ToString();
    }

1
Bạn có thể hiển thị mã bạn có cho đến nay tạo ra ngoại lệ không?
mlibby

Câu trả lời:


154
@Html.Partial("nameOfPartial", Model)

Cập nhật

protected string RenderPartialViewToString(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = ControllerContext.RouteData.GetRequiredString("action");

    ViewData.Model = model;

    using (StringWriter sw = new StringWriter()) {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

Có, đây là cách bạn hiển thị một phần bên trong một khung nhìn. Nhưng làm thế nào để hiển thị nó bên trong một hành động của bộ điều khiển?
Peter Stegnar

Tuyệt vời là nó bây giờ! Hoạt động với ký hiệu Razon và ASP.
Peter Stegnar

2
Một câu hỏi con: Làm thế nào để hiển thị dạng xem trong phạm vi Bộ điều khiển khác sau đó là hiện tại? Cho phép nói rằng nó nằm trong phạm vi "EmailController" (Thư mục xem email)?
Peter Stegnar

1
Đây là một giải pháp tuyệt vời. Tôi có nhu cầu chính xác với email và đã chọn sử dụng cái này.
uadrive

2
@AmeyKhadatkar: không. jquery là phía máy khách, chế độ xem được tạo ở phía máy chủ trước khi được gửi đến trình duyệt.
jgauffin

8

Mặc dù các câu trả lời đầy đủ đã được đưa ra, tôi muốn đề xuất một giải pháp ít dài dòng hơn, có thể được sử dụng mà không cần các phương thức trợ giúp có sẵn trong lớp bộ điều khiển MVC. Sử dụng thư viện của bên thứ ba có tên "RazorEngine", bạn có thể sử dụng tệp .Net IO để lấy nội dung của tệp dao cạo và gọi

string html = Razor.Parse(razorViewContentString, modelObject);

Tải thư viện của bên thứ ba tại đây .


5

Bạn cũng có thể sử dụng RenderView Controller extensiontừ đây ( nguồn )

và sử dụng nó như thế này:

public ActionResult Do() {
var html = this.RenderView("index", theModel);
...
}

nó hoạt động cho dao cạocác chế độ xem biểu mẫu web


Đã kiểm tra liên kết. @ChurkNorris là tác giả của ASP.net MVC Awesome , là một sản phẩm thương mại từ phiên bản 2.0 (hiện tại là bản phát hành mới nhất vào ngày 12 tháng 3 năm 2012). Phiên bản 1.9 (bản phát hành mới nhất ngày 9 tháng 6 năm 2011) vẫn là mã nguồn mở, nhưng có thể sẽ không được phát triển thêm nữa. Bất kỳ ngã ba của 1.9 ra khỏi đó?
Joel Purra

@Omu: RenderView bị vô hiệu. Xem msdn.microsoft.com/en-us/library/…
roland

@Roland đây là một phần mở rộng bộ điều khiển tùy chỉnh
Omu

1

Tôi thấy rằng ai đó đang tự hỏi làm thế nào để làm điều đó cho bộ điều khiển khác.

Trong trường hợp của tôi, tôi có tất cả các mẫu email của mình trong thư mục Chế độ xem / Email, nhưng bạn có thể sửa đổi điều này để chuyển vào bộ điều khiển mà bạn có các chế độ xem được liên kết.

public static string RenderViewToString(Controller controller, string viewName, object model)
    {
        var oldController = controller.RouteData.Values["controller"].ToString();

        if (controller.GetType() != typeof(EmailController))
            controller.RouteData.Values["controller"] = "Email";

        var oldModel = controller.ViewData.Model;
        controller.ViewData.Model = model;
        try
        {
            using (var sw = new StringWriter())
            {
                var viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName,
                                                                           null);

                var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);

                //Cleanup
                controller.ViewData.Model = oldModel;
                controller.RouteData.Values["controller"] = oldController;

                return sw.GetStringBuilder().ToString();
            }
        }
        catch (Exception ex)
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

            throw ex;
        }
    }

Về cơ bản những gì điều này làm là lấy một bộ điều khiển, chẳng hạn như AccountController và sửa đổi nó để nghĩ rằng đó là một EmailController để mã sẽ hiển thị trong Views/Emailthư mục. Cần phải làm điều này vì FindViewphương thức không lấy một đường dẫn thẳng lên làm tham số, nó muốn a ControllerContext.

Sau khi hoàn thành việc hiển thị chuỗi, nó sẽ trả AccountController trở lại trạng thái ban đầu để đối tượng Response sử dụng.


1

mã tuyệt vời; gợi ý nhỏ: nếu đôi khi bạn phải bỏ qua nhiều dữ liệu hơn và không chỉ mô hình chế độ xem ..

 if (model is ViewDataDictionary)
 {
     controller.ViewData = model as ViewDataDictionary;
 } else {
     controller.ViewData.Model = model;
 }

2
Bạn chưa hoàn thành câu trả lời của bạn
poohdedoo

0

Mượn câu trả lời @jgauffin làm tiện ích mở rộng HtmlHelper:

public static class HtmlHelperExtensions
{
    public static MvcHtmlString RenderPartialViewToString(
        this HtmlHelper html, 
        ControllerContext controllerContext, 
        ViewDataDictionary viewData,
        TempDataDictionary tempData,
        string viewName, 
        object model)
    {
        viewData.Model = model;
        string result = String.Empty;

        using (StringWriter sw = new StringWriter())
        {
            ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName);
            ViewContext viewContext = new ViewContext(controllerContext, viewResult.View, viewData, tempData, sw);
            viewResult.View.Render(viewContext, sw);

            result = sw.GetStringBuilder().ToString();
        }

        return MvcHtmlString.Create(result);
    }
}

Cách sử dụng trong chế độ xem dao cạo:

Html.RenderPartialViewToString(ViewContext, ViewData, TempData, "Search", Model)

1
Bạn có thể giải thích sự khác biệt khi sử dụng @ Html.Partial (string partViewName, object model, ViewDataDictionary viewData)? Những lợi ích vì nó yêu cầu HtmlHelper là gì?
bkqc
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.