Teilweise aus einem anderen Ordner rendern (nicht freigegeben)

256

Wie kann ich eine Ansicht einen Teil (Benutzersteuerung) aus einem anderen Ordner rendern lassen? Mit Vorschau 3 habe ich RenderUserControl mit dem vollständigen Pfad aufgerufen, aber mit einem Upgrade auf Vorschau 5 ist dies nicht mehr möglich. Stattdessen haben wir die RenderPartial-Methode, die mir jedoch nicht die gesuchte Funktionalität bietet.

Boris Callens
quelle

Antworten:

443

Fügen Sie einfach den Pfad zur Ansicht mit der Dateierweiterung hinzu.

Rasierer:

@Html.Partial("~/Views/AnotherFolder/Messages.cshtml", ViewData.Model.Successes)

ASP.NET-Engine:

<% Html.RenderPartial("~/Views/AnotherFolder/Messages.ascx", ViewData.Model.Successes); %>

Wenn dies nicht Ihr Problem ist, können Sie bitte Ihren Code einfügen, der früher mit RenderUserControl funktioniert hat?

Elijah Manor
quelle
19
Ich wünschte, wir könnten einfach / AnotherFolder / Messages
Simon_Weaver
4
@ Simon_Weaver Das können Sie erreichen. Eine Möglichkeit wäre, ViewEngine zu ändern und seine FindPartialViewMethode mit etwas wieif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Arnis Lapsa
2
Funktioniert auch in der MVC 3 Razor-Engine, aber wie oben benötigen Sie die Erweiterung (.cshtml).
Chris
Wenn es unter verschiedenen ist, müssten Sie Pfad "~ / Areas / TestArea / Views / Shared / _SomePartial.mobile.cshtml"
Sandeep Talabathula
Wie gehen Sie mit verschiedenen Kulturen dieser Teilansicht um (z. B. ~ / Views / AnotherFolder / Messages.en.cshtml)?
Jasdefer
29

In meinem Fall habe ich MvcMailer (https://github.com/smsohan/MvcMailer) verwendet und wollte auf eine Teilansicht aus einem anderen Ordner zugreifen, der nicht in "Shared" enthalten war. Die oben genannten Lösungen haben nicht funktioniert, aber die Verwendung eines relativen Pfads hat funktioniert.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
Aaron Sherman
quelle
Ebenso @ Html.Partial ("../ Shared / _PartialView"), um den Shared-Ordner zu verwenden.
Curtis Yallop
11
Ich finde, dass dies ohne die Erweiterung .cshtml am Ende nicht funktioniert.
Luke
28

Wenn Sie diesen anderen Pfad häufig verwenden, können Sie dies dauerhaft beheben, ohne den Pfad ständig angeben zu müssen. Standardmäßig wird im Ordner "Ansicht" und im Ordner "Freigegeben" nach Teilansichten gesucht. Angenommen, Sie möchten eine hinzufügen.

Fügen Sie Ihrem Modellordner eine Klasse hinzu:

public class NewViewEngine : RazorViewEngine {

   private static readonly string[] NEW_PARTIAL_VIEW_FORMATS = new[] {
      "~/Views/Foo/{0}.cshtml",
      "~/Views/Shared/Bar/{0}.cshtml"
   };

   public NewViewEngine() {
      // Keep existing locations in sync
      base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(NEW_PARTIAL_VIEW_FORMATS).ToArray();
   }
}

Fügen Sie dann in Ihrer Datei Global.asax.cs die folgende Zeile hinzu:

ViewEngines.Engines.Add(new NewViewEngine());
Paul
quelle
6
Natürlich ist mir klar, dass diese Frage vor langer Zeit gestellt wurde. Ich dachte, ich würde es für zukünftige Googler und zukünftige Binger ergänzen.
Paul
- Funktioniert in .Net Core 2.2 nicht, da RazorViewEngine.PartialViewLocationFormats nicht vorhanden ist.
Demian Berisford-Maynard
7

Für ein Benutzersteuerelement mit dem Namen myPartial.ascx im Ordner Ansichten / Konto schreiben Sie Folgendes:

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
Rahatur
quelle
5

Ich habe eine Problemumgehung erstellt, die ziemlich gut zu funktionieren scheint. Ich habe festgestellt, dass für die Suche nach Aktionsnamen, die Suche nach Ansichten usw. in den Kontext eines anderen Controllers gewechselt werden muss. Um dies zu implementieren, habe ich eine neue Erweiterungsmethode erstellt für HtmlHelper:

public static IDisposable ControllerContextRegion(
    this HtmlHelper html, 
    string controllerName)
{
    return new ControllerContextRegion(html.ViewContext.RouteData, controllerName);
}

ControllerContextRegion ist definiert als:

internal class ControllerContextRegion : IDisposable
{
    private readonly RouteData routeData;
    private readonly string previousControllerName;

    public ControllerContextRegion(RouteData routeData, string controllerName)
    {
        this.routeData = routeData;
        this.previousControllerName = routeData.GetRequiredString("controller");
        this.SetControllerName(controllerName);
    }

    public void Dispose()
    {
        this.SetControllerName(this.previousControllerName);
    }

    private void SetControllerName(string controllerName)
    {
        this.routeData.Values["controller"] = controllerName;
    }
}

In einer Ansicht wird dies folgendermaßen verwendet:

@using (Html.ControllerContextRegion("Foo")) {
    // Html.Action, Html.Partial, etc. now looks things up as though
    // FooController was our controller.
}

Dies kann zu unerwünschten Nebenwirkungen führen, wenn Ihr Code erfordert, dass sich die controllerRoutenkomponente nicht ändert. In unserem Code scheint dieser Ansatz jedoch bisher keine negativen Auswirkungen zu haben.

Jacob
quelle
4

Die VirtualPathProviderViewEngine, auf der die WebFormsViewEngine basiert, soll die Zeichen "~" und "/" am Anfang des Pfads unterstützen, damit die obigen Beispiele funktionieren.

Ich habe festgestellt, dass Ihre Beispiele den Pfad "~ / Account / myPartial.ascx" verwenden, aber Sie haben erwähnt, dass sich Ihr Benutzersteuerelement im Ordner "Ansichten / Konto" befindet. Hast du es versucht

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>

oder ist das nur ein Tippfehler in deiner Frage?

Andrew Stanton-Krankenschwester
quelle
0

Sie sollten dies versuchen

~/Views/Shared/parts/UMFview.ascx

Platzieren Sie das ~/Views/vor Ihrem Code

mounir
quelle
0

Erstellen Sie eine benutzerdefinierte View Engine und verfügen Sie über eine Methode, die ein ViewEngineResult zurückgibt. In diesem Beispiel überschreiben Sie einfach das _options.ViewLocationFormatsund fügen Ihr Ordnerverzeichnis hinzu:

public ViewEngineResult FindView(ActionContext context, string viewName, bool isMainPage)
        {
            var controllerName = context.GetNormalizedRouteValue(CONTROLLER_KEY);
            var areaName = context.GetNormalizedRouteValue(AREA_KEY);

            var checkedLocations = new List<string>();
            foreach (var location in _options.ViewLocationFormats)
            {
                var view = string.Format(location, viewName, controllerName);
                if (File.Exists(view))
                {
                    return ViewEngineResult.Found("Default", new View(view, _ViewRendering));
                }
                checkedLocations.Add(view);
            }

            return ViewEngineResult.NotFound(viewName, checkedLocations);
        }

Beispiel: https://github.com/AspNetMonsters/pugzor

Demian Berisford-Maynard
quelle
-5

Versuchen Sie es mit RenderAction("myPartial","Account");

Siva Kandaraj
quelle
3
Bitte lesen Sie die Frage, während der Benutzer nach der Ansicht in einem anderen Ordner fragt. Wo befindet sich der Ordner in Ihrem Code?
Pamma