Подтвердить что ты не робот

ASP.NET MVC Razor: как визуализировать Razor Partial View HTML внутри действия контроллера

Как сгенерировать HTML-код данного частичного представления в ASP.NET-режиме просмотра известен.

Но если эта функция используется для частичного просмотра бритвы, она не работает, поскольку исключение говорит, что частичный вид не получается из "UserControl".

Как исправить рендеринг для поддержки частичного просмотра бритвы?

Мне нужно это, потому что я создаю электронные письма из этих частичных представлений...

UPDATE:

Неверный код (@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();
    }
4b9b3361

Ответ 1

@Html.Partial("nameOfPartial", Model)

Обновление

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

Ответ 2

Хотя уже были даны адекватные ответы, я хотел бы предложить менее подробное решение, которое можно использовать без вспомогательных методов, доступных в классе контроллера MVC. Используя стороннюю библиотеку под названием "RazorEngine", вы можете использовать .Net файл IO для получения содержимого файла бритвы и вызова

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

Получить стороннюю библиотеку здесь.

Ответ 3

Вы также можете использовать RenderView Controller extension из здесь (source)

и используйте его следующим образом:

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

он работает для просмотров бритвы и веб-форм

Ответ 4

Я видел, что кто-то задавался вопросом, как это сделать для другого контроллера.

В моем случае у меня были все мои шаблоны электронной почты в папке Views/Email, но вы можете изменить это, чтобы передать его в контроллер, в котором у вас есть представления, связанные.

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

По сути, это делает контроллер, например AccountController, и модифицирует его, чтобы считать его почтовым контроллером, чтобы код выглядел в папке Views/Email. Это необходимо сделать, потому что метод FindView не принимает прямой путь в качестве параметра, он хочет ControllerContext.

После того, как вы сделали рендеринг строки, он вернет AccountController обратно в исходное состояние, которое будет использоваться объектом Response.

Ответ 5

отличный код; маленький намек: если вам иногда приходится обходить больше данных, а не только viewmodel..

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

Ответ 6

Заимствование @jgauffin отвечает как расширение 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);
    }
}

Использование в режиме бритвы:

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