Wie kann eine Teilansicht eines anderen Controllers von Controller zurückgegeben werden?

80

Ich habe eine XXX.cshtmlDatei in einem Views\ABCOrdner. Sein Controller istABC

Ich habe auch eine Aktionsmethode in meinem DEFController, die a zurückgibtPartialview("XXX" , xyzmodel)

Ich erhalte den Fehler "Ansicht nicht gefunden".

So rufen Sie diese Ansicht von einem anderen Controller aus auf

Vinit Patel
quelle

Antworten:

158

Normalerweise gehören die Ansichten zu einem bestimmten passenden Controller , der seine Datenanforderungen unterstützt, oder die Ansicht gehört in den Views/SharedOrdner, wenn sie von Controllern gemeinsam genutzt wird (daher der Name).

"Antwort" (aber nicht empfohlen - siehe unten):

Sie können auf Ansichten / Teilansichten eines anderen Controllers verweisen, indem Sie den vollständigen Pfad (einschließlich der Erweiterung) wie folgt angeben:

return PartialView("~/views/ABC/XXX.cshtml", zyxmodel);

oder ein relativer Pfad (keine Erweiterung), basierend auf der Antwort von @Max Toro

return PartialView("../ABC/XXX", zyxmodel);

ABER DAS IST KEINE GUTE IDEE

* Hinweis: Dies sind die einzigen zwei Syntaxen, die funktionieren . nicht ABC\\XXXoder ABC/XXXoder irgendeine andere Variation, da dies alles relative Pfade sind und keine Übereinstimmung finden.

Bessere Alternativen:

Sie können Html.Renderpartialstattdessen in Ihrer Ansicht verwenden, es ist jedoch auch die Erweiterung erforderlich:

Html.RenderPartial("~/Views/ControllerName/ViewName.cshtml", modeldata);

Verwendung @Html.Partialfür die Inline-Razor-Syntax:

@Html.Partial("~/Views/ControllerName/ViewName.cshtml", modeldata)

Sie können die ../controller/viewSyntax ohne Erweiterung verwenden (erneut @Max Toro):

@Html.Partial("../ControllerName/ViewName", modeldata)

Hinweis: Anscheinend RenderPartialist etwas schneller als Partial, aber das ist nicht wichtig.

Wenn Sie den anderen Controller tatsächlich aufrufen möchten, verwenden Sie:

@Html.Action("action", "controller", parameters)

Empfohlene Lösung: @ Html.Action

Meine persönliche Präferenz ist die Verwendung, @Html.Actionda jeder Controller seine eigenen Ansichten verwalten kann, anstatt auf Ansichten anderer Controller zu verweisen (was zu einem großen Spaghetti-ähnlichen Durcheinander führt).

Normalerweise übergeben Sie nur die erforderlichen Schlüsselwerte (wie jede andere Ansicht), z. B. für Ihr Beispiel:

@Html.Action("XXX", "ABC", new {id = model.xyzId })

Dadurch wird die ABC.XXXAktion ausgeführt und das Ergebnis an Ort und Stelle gerendert. Dadurch können die Ansichten und Controller separat in sich geschlossen bleiben (dh wiederverwendbar sein).

Update September 2014:

Ich bin gerade auf eine Situation gestoßen, in der ich @ Html.Action nicht verwenden konnte, aber einen Ansichtspfad basierend auf a actionund controllerNamen erstellen musste . Zu diesem Zweck habe ich diese einfache ViewErweiterungsmethode hinzugefügt , UrlHelperdamit Sie return sagen können PartialView(Url.View("actionName", "controllerName"), modelData):

public static class UrlHelperExtension
{
    /// <summary>
    /// Return a view path based on an action name and controller name
    /// </summary>
    /// <param name="url">Context for extension method</param>
    /// <param name="action">Action name</param>
    /// <param name="controller">Controller name</param>
    /// <returns>A string in the form "~/views/{controller}/{action}.cshtml</returns>
    public static string View(this UrlHelper url, string action, string controller)
    {
        return string.Format("~/Views/{1}/{0}.cshtml", action, controller);
    }
}
Codierung weg
quelle
4
@ Html.Action ist der richtige Weg
Arman
Ihr empfohlener Ansatz würde mich dazu bringen, Dienste aus der Sicht aufzurufen, um das Modell abzurufen, das mein Teil benötigt. Was ich nicht vermeiden möchte.
Raimonds
11

Das Steuerelement sucht in der folgenden Reihenfolge nach einer Ansicht:

  • Zuerst im freigegebenen Ordner
  • Dann in dem Ordner, der dem aktuellen Controller entspricht (in Ihrem Fall Views / DEF)

Da Sie xxx.cshtmlan diesen Speicherorten keine haben , wird der Fehler "Ansicht nicht gefunden" zurückgegeben.

Lösung: Sie können den vollständigen Pfad Ihrer Ansicht verwenden:

Mögen

 PartialView("~/views/ABC/XXX.cshtml", zyxmodel);
Arun Chandran C.
quelle
@TrueBlueAussie danke für die Korrektur. Du hast es gut erklärt. Es geht nicht darum, "best answer tick' and up-votesnur Teilen zu verdienen ... Wie auch immer, danke für deinen Punkt. :)
Arun Chandran C
Tatsächlich. Deshalb habe ich auch Ihren Eintrag bearbeitet, um ihn zu verbessern.
Gone Coding
6

Einfach könnte man verwenden:

PartialView("../ABC/XXX")
Max Toro
quelle
Ich war anfangs skeptisch gegenüber dieser Syntax, aber sie funktioniert einwandfrei, auch bei Standard-Controller-Aktionen. Haben Sie eine Referenz dazu?
Gone Coding