webentwicklung-frage-antwort-db.com.de

ASP.NET MVC Razor: Wie wird der HTML-Code einer Rasierer-Teilansicht in der Controller-Aktion dargestellt?

Wie man einen HTML-Code einer bestimmten Teilansicht auf der ASP.NET-Ansichts-Engine generiert ist bekannt .

Wenn diese Funktion jedoch für die Rasierer-Teilansicht verwendet wird, funktioniert sie nicht, da die Teilansicht ausnahmsweise nicht von "UserControl" stammt.

Wie kann ich das Rendering so korrigieren, dass es die Teilansicht von Rasierern unterstützt?

Ich brauche das, weil ich E-Mails aus diesen Teilansichten generiere ...

UPDATE:

Code, der fehlschlägt (@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();
    }
96
Peter Stegnar
@Html.Partial("nameOfPartial", Model)

Update

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

Obwohl bereits ausreichende Antworten gegeben wurden, möchte ich eine weniger ausführliche Lösung vorschlagen, die ohne die in einer MVC-Controller-Klasse verfügbaren Hilfsmethoden verwendet werden kann. Mit einer Fremdanbieter-Bibliothek namens "RazorEngine" können Sie die .Net-Datei IO verwenden, um den Inhalt der Rasiererdatei abzurufen und abzurufen

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

Besorgen Sie sich die Drittanbieter-Bibliothek hier .

8
Scott Terry

Sie können auch den RenderView Controller extension von hier ( source ) verwenden.

und benutze es so:

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

es funktioniert für razor und web-forms viewengines

5
Omu

Ich habe gesehen, dass sich jemand gefragt hat, wie man es für einen anderen Controller macht.

In meinem Fall hatte ich alle meine E-Mail-Vorlagen im Ordner Ansichten/E-Mail, aber Sie können dies ändern, um den Controller zu übergeben, in dem Sie Ansichten haben.

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

Im Wesentlichen müssen Sie dazu einen Controller wie AccountController verwenden und ihn so anpassen, dass er ein EmailController ist, damit der Code im Ordner Views/Email angezeigt wird. Dies ist notwendig, da die FindView-Methode keinen direkten Pfad als Parameter hat, sondern eine ControllerContext

Nach dem Rendern der Zeichenfolge wird der AccountController wieder in den Ausgangszustand versetzt, der vom Response-Objekt verwendet werden soll.

1
The Muffin Man

großer Code; kleiner tipp: wenn man manchmal mehr daten umgehen muss und nicht nur das viewmodel .. 

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

Ausleihe von @jgauffin als HtmlHelper-Erweiterung: 

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

Verwendung in einer Rasiermesseransicht:

Html.RenderPartialViewToString(ViewContext, ViewData, TempData, "Search", Model)
0
jmb-mage