In ASP.NET MVC können Sie ganz einfach ein umleitendes ActionResult zurückgeben:
return RedirectToAction("Index");
or
return RedirectToRoute(new { controller = "home", version = Math.Random() * 10 });
Dies führt tatsächlich zu einer HTTP-Umleitung, was normalerweise in Ordnung ist. Bei Verwendung von Google Analytics führt dies jedoch zu großen Problemen, da der ursprüngliche Referer verloren geht und Google nicht weiß, woher Sie stammen. Dadurch gehen nützliche Informationen wie Suchmaschinenbegriffe verloren.
Nebenbei bemerkt hat diese Methode den Vorteil, dass alle Parameter entfernt werden, die möglicherweise aus Kampagnen stammen, aber ich kann sie dennoch serverseitig erfassen. Wenn Sie sie in der Abfragezeichenfolge belassen, werden Lesezeichen gesetzt oder Twitter oder Blog ein Link, den sie nicht sollten. Ich habe dies mehrmals gesehen, als Leute Links zu unserer Website mit Kampagnen-IDs getwittert haben.
Wie auch immer, ich schreibe einen "Gateway" -Controller für alle eingehenden Besuche auf der Site, den ich möglicherweise an verschiedene Orte oder alternative Versionen weiterleiten kann.
Im Moment interessiert mich Google vorerst mehr (als versehentliches Lesezeichen), und ich möchte in der Lage sein, jemanden zu senden, der /
die Seite besucht , die er erhalten würde, wenn er zu /home/7
dieser Version 7 einer Homepage gehen würde.
Wie ich bereits sagte Wenn ich dies tue, verliere ich die Fähigkeit von Google, den Referer zu analysieren:
return RedirectToAction(new { controller = "home", version = 7 });
Was ich wirklich will, ist ein
return ServerTransferAction(new { controller = "home", version = 7 });
Dadurch bekomme ich diese Ansicht ohne eine clientseitige Weiterleitung. Ich glaube nicht, dass so etwas existiert.
Derzeit ist das Beste, was ich mir einfallen lassen kann, die gesamte Controller-Logik HomeController.Index(..)
in meiner GatewayController.Index
Aktion zu duplizieren . Das heißt , ich musste umziehen 'Views/Home'
in 'Shared'
so war es zugänglich. Es muss einen besseren Weg geben ?? ..
quelle
ServerTransferAction
wollten Sie replizieren? Ist das eine tatsächliche Sache? (konnte keine Informationen darüber finden ... danke für die Frage, übrigens, die Antwort unten ist hervorragend)if
Aussage einfach zu verlockend.RouteBase
damit Sie Ihreif
Anweisung dort platzieren können, anstatt alles nach hinten zu biegen, um von einem Controller zum anderen zu springen?Antworten:
Wie wäre es mit einer TransferResult-Klasse? (basierend auf Stans Antwort )
Aktualisiert: Funktioniert jetzt mit MVC3 (unter Verwendung von Code aus Simons Beitrag ). Es sollte (konnte es nicht testen) auch in MVC2 funktionieren, indem geprüft wird, ob es in der integrierten Pipeline von IIS7 + ausgeführt wird oder nicht.
Für volle Transparenz; In unserer Produktionsumgebung haben wir das TransferResult nie direkt verwendet. Wir verwenden ein TransferToRouteResult, das wiederum das TransferResult ausführt. Folgendes läuft tatsächlich auf meinen Produktionsservern.
Und wenn Sie T4MVC verwenden (wenn nicht ... tun!) , Kann diese Erweiterung nützlich sein.
Mit diesem kleinen Juwel können Sie tun
quelle
Bearbeiten: Aktualisiert, um mit ASP.NET MVC 3 kompatibel zu sein
Vorausgesetzt, Sie verwenden IIS7, scheint die folgende Änderung für ASP.NET MVC 3 zu funktionieren. Vielen Dank an @nitin und @andy für den Hinweis, dass der ursprüngliche Code nicht funktioniert hat.
Edit 4/11/2011: TempData bricht mit Server.TransferRequest ab MVC 3 RTM ab
Der folgende Code wurde geändert, um eine Ausnahme auszulösen - aber derzeit keine andere Lösung.
Hier ist meine Modifikation basierend auf Markus 'modifizierter Version von Stans ursprünglichem Beitrag. Ich habe einen zusätzlichen Konstruktor hinzugefügt, um ein Routenwertwörterbuch zu verwenden - und es in MVCTransferResult umbenannt, um Verwirrung zu vermeiden, dass es sich möglicherweise nur um eine Umleitung handelt.
Ich kann jetzt Folgendes für eine Umleitung tun:
Meine modifizierte Klasse:
quelle
Sie können stattdessen Server.TransferRequest auf IIS7 + verwenden.
quelle
Ich habe kürzlich herausgefunden, dass ASP.NET MVC Server.Transfer () nicht unterstützt, daher habe ich eine Stub-Methode erstellt (inspiriert von Default.aspx.cs).
quelle
Könnten Sie nicht einfach eine Instanz des Controllers erstellen, zu dem Sie umleiten möchten, die gewünschte Aktionsmethode aufrufen und dann das Ergebnis zurückgeben? Etwas wie:
quelle
otherController.ControllerContext = this.ControllerContext;
Ich wollte die aktuelle Anforderung an einen anderen Controller / eine andere Aktion umleiten, während der Ausführungspfad genau so bleibt, als ob dieser zweite Controller / diese zweite Aktion angefordert worden wäre. In meinem Fall würde Server.Request nicht funktionieren, da ich weitere Daten hinzufügen wollte. Dies entspricht dem aktuellen Handler, der ein anderes HTTP-GET / POST ausführt und dann die Ergebnisse an den Client überträgt. Ich bin mir sicher, dass es bessere Möglichkeiten geben wird, dies zu erreichen, aber hier ist, was für mich funktioniert:
Ihre Vermutung ist richtig: Ich habe diesen Code eingegeben
und ich verwende es, um Entwicklern Fehler anzuzeigen, während es in der Produktion eine regelmäßige Umleitung verwendet. Beachten Sie, dass ich keine ASP.NET-Sitzung, Datenbank oder andere Methoden zum Übergeben von Ausnahmedaten zwischen Anforderungen verwenden wollte.
quelle
Anstatt eine Serverübertragung zu simulieren, kann MVC weiterhin einen Server ausführen.TransferRequest :
quelle
Instanzieren Sie einfach den anderen Controller und führen Sie seine Aktionsmethode aus.
quelle
Sie können den anderen Controller neu starten und die Aktionsmethode aufrufen, die das Ergebnis zurückgibt. Dazu müssen Sie Ihre Ansicht jedoch in den freigegebenen Ordner legen.
Ich bin mir nicht sicher, ob Sie dies mit Duplikat gemeint haben, aber:
Bearbeiten
Eine andere Möglichkeit könnte darin bestehen, eine eigene ControllerFactory zu erstellen. Auf diese Weise können Sie bestimmen, welcher Controller erstellt werden soll.
quelle
Kümmert sich das Routing nicht nur um dieses Szenario für Sie? Für das oben beschriebene Szenario können Sie einfach einen Routenhandler erstellen, der diese Logik implementiert.
quelle
Für alle, die ausdrucksbasiertes Routing verwenden und nur die oben genannte TransferResult-Klasse verwenden, ist hier eine Controller-Erweiterungsmethode, die den Trick ausführt und TempData beibehält. TransferToRouteResult ist nicht erforderlich.
quelle
Server.TransferRequest
ist in MVC völlig unnötig . Dies ist eine veraltete Funktion, die nur in ASP.NET erforderlich war, da die Anforderung direkt auf eine Seite kam und es eine Möglichkeit geben musste, eine Anforderung auf eine andere Seite zu übertragen. Moderne Versionen von ASP.NET (einschließlich MVC) verfügen über eine Routing-Infrastruktur, die so angepasst werden kann, dass sie direkt an die gewünschte Ressource weitergeleitet wird. Es macht keinen Sinn, die Anforderung einen Controller erreichen zu lassen, nur um sie auf einen anderen Controller zu übertragen, wenn Sie die Anforderung einfach direkt an den Controller und die gewünschte Aktion senden können.Da Sie auf die ursprüngliche Anfrage antworten, müssen Sie nichts in einen
TempData
anderen Speicher stecken, um die Anfrage an den richtigen Ort weiterzuleiten. Stattdessen gelangen Sie mit intakter ursprünglicher Anforderung zur Controller-Aktion. Sie können auch sicher sein, dass Google diesen Ansatz gutheißt, da er vollständig auf der Serverseite erfolgt.Während Sie mit beiden
IRouteConstraint
und einiges tun könnenIRouteHandler
, ist der leistungsstärkste Erweiterungspunkt für das Routing dieRouteBase
Unterklasse. Diese Klasse kann erweitert werden, um sowohl eingehende Routen als auch die Generierung ausgehender URLs bereitzustellen. Dies macht sie zu einem One-Stop-Shop für alles, was mit der URL und der von der URL ausgeführten Aktion zu tun hat.Um Ihrem zweiten Beispiel zu folgen und von
/
nach zu gelangen/home/7
, benötigen Sie lediglich eine Route, die die entsprechenden Routenwerte hinzufügt.Wenn Sie jedoch zu Ihrem ursprünglichen Beispiel zurückkehren, in dem Sie eine zufällige Seite haben, ist dies komplexer, da sich die Routenparameter zur Laufzeit nicht ändern können. Es könnte also mit einer
RouteBase
Unterklasse wie folgt gemacht werden.Welche können im Routing registriert werden wie:
Beachten Sie im obigen Beispiel, dass es möglicherweise sinnvoll ist, auch ein Cookie zu speichern, das die Homepage-Version aufzeichnet, auf die der Benutzer gekommen ist, damit er bei seiner Rückkehr dieselbe Homepage-Version erhält.
Beachten Sie auch, dass Sie mit diesem Ansatz das Routing so anpassen können, dass Abfragezeichenfolgenparameter berücksichtigt werden (diese werden standardmäßig vollständig ignoriert) und entsprechend zu einer geeigneten Controller-Aktion weitergeleitet.
Zusätzliche Beispiele
quelle
Server.TransferRequest
es in MVC nicht "völlig unnötig".Keine Antwort an sich, aber eindeutig wäre die Anforderung nicht nur, dass die eigentliche Navigation die entsprechende Funktionalität von Webforms Server.Transfer () "ausführt", sondern dass all dies im Unit-Test vollständig unterstützt wird.
Daher sollte das ServerTransferResult wie ein RedirectToRouteResult "aussehen" und hinsichtlich der Klassenhierarchie so ähnlich wie möglich sein.
Ich denke darüber nach, indem ich mir Reflector anschaue und die RedirectToRouteResult-Klasse und auch die verschiedenen Controller-Basisklassenmethoden mache und diese dann über Erweiterungsmethoden zum Controller "hinzufüge". Vielleicht könnten dies statische Methoden innerhalb derselben Klasse sein, um das Herunterladen zu vereinfachen?
Wenn ich dazu komme, werde ich es veröffentlichen, sonst könnte mich vielleicht jemand anderes schlagen!
quelle
Dies habe ich erreicht, indem ich den
Html.RenderAction
Helfer in einer Ansicht nutzte :Und in meinem Controller:
quelle