Zeigen Sie eine Ansicht von einem anderen Controller in ASP.NET MVC an

248

Ist es möglich, eine Ansicht von einem anderen Controller anzuzeigen?

Sagen Sie zum Beispiel, ich habe eine CategoriesControllerund eine Category/NotFound.aspxAnsicht. Während CategoriesControllerich in der bin, kann ich leicht zurückkehren View("NotFound").

Sagen Sie jetzt, ich habe eine ProductsControllerund eine Aktion und Ansicht, um ein Produkt hinzuzufügen. Für diese Aktion muss jedoch eine Kategorie vorhanden sein, zu der das Produkt hinzugefügt werden kann. Zum Beispiel Products/Add/?catid=10.

Wenn ich die Kategorie basierend auf nicht finden kann catid, möchte ich die NotFoundAnsicht vom Categories-Controller anzeigen, anstatt eine CategoryNotFoundAnsicht unter dem Products-Controller zu erstellen .

Ist das möglich oder strukturiere ich die Dinge falsch? Gibt es eine gute Möglichkeit, dies zu tun?

dtc
quelle

Antworten:

283

Ja. Standardmäßig meldet sich ASP.NET MVC zuerst an. \Views\[Controller_Dir]\Wenn die Ansicht danach nicht gefunden wird, wird sie eingecheckt \Views\Shared.

Das freigegebene Verzeichnis dient speziell zum Freigeben von Ansichten für mehrere Controller. Fügen Sie einfach Ihre Ansicht zum Unterverzeichnis "Freigegeben" hinzu und los geht's.

Wenn Sie dies tun, können return View("~/Views/Wherever/SomeDir/MyView.aspx")Sie jede gewünschte Ansicht zurückgeben.

womp
quelle
Danke, das klingt nach der Lösung, die ich verwenden sollte. Ich frage mich immer noch, ob es möglich ist, eine Ansicht von einem anderen Controller anzuzeigen. Ich vermute, dies verstößt gegen eine Regel in MVC?
dtc
1
In der oben beschriebenen Situation sollten Sie den freigegebenen Ordner verwenden.
Jonathan Freeland
69
Ja, das ist auch möglich. Wenn Sie View zurückgeben ("~ / Views / Wherever / SomeDir / MyView.aspx"), können Sie jede gewünschte Ansicht zurückgeben. Dies verstößt an sich nicht gegen eine bestimmte Regel. Bei ASP.Net MVC dreht sich jedoch alles um "Konvention über Konfiguration". Mit anderen Worten, das Framework ist so aufgebaut, dass es unter Verwendung bestimmter Konventionen automatisch funktioniert, und Sie sollten es nach Möglichkeit verwenden.
Womp
1
Danke für die Erklärung. Ich wusste nicht, dass Views so genannt werden können. Das Shared Directory funktioniert natürlich perfekt :)
dtc
1
Ich war nicht in einem Controller, also musste ich verwenden new ViewResult { ViewName = "~/Views/Error/Unauthorised.cshtml" };und es funktionierte
Nacht - Reinstate Monica
162

Sie können verwenden:

return View("../Category/NotFound", model);

Es wurde in ASP.NET MVC 3 getestet, sollte aber auch in ASP.NET MVC 2 funktionieren.

Guillaume86
quelle
3
Funktioniert in MVC 2 und hat sich als die sauberste Lösung für eine ungewöhnliche Situation herausgestellt, mit der ich zu tun habe.
Todd Menier
3
Resharper meldet diesen Link als Fehler, funktioniert aber weiterhin.
CodeMonkeyKing
1
@CodeMonkeyKing - Resharper 7 (in VS2012) identifiziert einen Pfad, der als formatiert ist, korrekt "~/Views/Category/NotFound.cshtml".
Richard Ev
Bemerkenswert: Diese Lösung funktioniert mit Anzeigemodi, z. B. wenn Sie eine Ansicht "/Category/NotFound.Mobile.cshtml" hatten.
BenWillkommen
55

Ja es ist möglich. Geben Sie eine RedirectToAction()Methode wie folgt zurück:

return RedirectToAction("ActionOrViewName", "ControllerName");
Doncadavona
quelle
1
Ich glaube, dies sollte als RedirectToAction ("ActionOrView", "Controller", null) gehen, da ansonsten der zweite Parameter routeValues ​​ist
Zoran P.
In diesem Fall müssen Sie die Aktion jedoch im Gegensatz zur View-Lösung tatsächlich in den Controller schreiben.
Tobbenb3
@ tobbenb3 Das ist eine viel bessere Lösung als das Hardcodieren eines Ergebnisses. In beiden Fällen sollten Sie keine Pfadzeichenfolge übergeben.
Perustaja
34

Hast du es versucht RedirectToAction?

Paul Johnson
quelle
1
Ich würde sagen, dass dies die MVC für alle ist, die die Ansicht in den freigegebenen Ordnern nicht möchten. Beachten Sie, dass bei allen anderen Lösungen (z. B. Verwendung direkter Pfade) jeder, der versucht, die Ansichten neu zu faktorisieren, dies nicht berücksichtigen muss dass es auch in einem anderen Controller verwendet wird, was zu unvorhersehbarem Verhalten führt
yoel halb
4
wie wäre es ohne umleiten?
Glücklicher
viel bessere Lösung als die Ansicht in freigegebene Ordner zu verschieben
juFo
Diese Lösung erfordert eine Aktion auf dem Controller. View (directPath) rendert die Ausgabe ohne Aktion. Wenn Sie eine Aktion hinzufügen, müssen Sie darüber nachdenken, sie vor dem direkten Zugriff über die URL zu verbergen. Dadurch wird ein Schritt im Browserverlauf usw. generiert. Aber ja, das ist mein Weg.
Jan Zahradník
3
RedirectToAction sendet einen 302-Antwortcode an den Browser. Dies ist nicht angemessen, wenn Sie versuchen, eine nicht gefundene 404-Seite anzuzeigen. Das heißt, diese Lösung scheint zu funktionieren, wird aber Suchmaschinen verwirren.
NightOwl888
20

Ja, du kannst. Geben Sie eine Aktion wie folgt zurück:

return RedirectToAction("View", "Name of Controller");

Ein Beispiel:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees");

Dieser Ansatz ruft die GET-Methode auf

Sie können auch Werte an folgende Aktionen übergeben:

return RedirectToAction("Details/" + id.ToString(), "FullTimeEmployees", new {id = id.ToString(), viewtype = "extended" });
Ignacio Chiazzo
quelle
Wie würde ich ein Objekt mit diesem Ansatz senden?
Djeroen
Werfen Sie einen Blick @ Djeroen
Ignacio Chiazzo
5
Sie geben keine Ansicht zurück, sondern rufen eine Aktion auf.
0014
Vor allem war für mich hilfreich.
Anil Shrestha
5

Sie können auch einen beliebigen Controller über JavaScript / jQuery aufrufen . Angenommen, Sie haben einen Controller, der 404 oder eine andere Benutzersteuerung / Seite zurückgibt. Dann können Sie bei einer Aktion aus Ihrem Client-Code eine Adresse aufrufen, die Ihren Controller auslöst und das Ergebnis im HTML- Format zurückgibt. Ihr Client-Code kann dieses zurückgegebene Ergebnis übernehmen und an einer beliebigen Stelle auf Ihrer Seite ablegen ...

Marko
quelle
Ich wusste das nicht. Das klingt so, als würde ich es in Zukunft verwenden. Ja, mvc rockt :)
dtc
1

Mit diesem Code können Sie jeden Controller erhalten:

var controller = DependencyResolver.Current.GetService<ControllerB>();
controller.ControllerContext = new ControllerContext(this.Request.RequestContext, 
controller);
Yair GR
quelle
Übersetzung: Mit diesem Code können Sie jeden Controller erhalten: [Code], Grüße,
Robert Columbia
3
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Nic3500