Wie leite ich mit dem POST-Verb zu einer Seite um?

131

Wenn Sie RedirectToActioninnerhalb eines Controllers anrufen , wird dieser automatisch über ein HTTP-GET umgeleitet. Wie kann ich explizit festlegen, dass ein HTTP-POST verwendet werden soll?

Ich habe eine Aktion, die sowohl GET- als auch POST-Anforderungen akzeptiert, und ich möchte RedirectToActionPOST verwenden und ihm einige Werte senden können.

So was:

this.RedirectToAction(
    "actionname",
    new RouteValueDictionary(new { someValue = 2, anotherValue = "text" })
);

Ich will die someValueund anotherValueWerte über eine HTTP - POST statt GET gesendet werden soll. Weiß jemand, wie man das macht?

Chris Pietschmann
quelle
Die Antwort von Jason funktioniert in den meisten Szenarien. Das einzige Problem, das ich sehe, ist, dass es unfallanfällig ist. Das Aufrufen einer Aktionsmethode umgeht direkt alle Filter, die auf die Aktion angewendet werden. Wenn also auf die Aktionsmethode eine Authentifizierung oder ein Zählerfilter angewendet wird, gehen diese Daten möglicherweise verloren. Das direkte Aufrufen einer Aktionsmethode funktioniert, sollte jedoch sorgfältig angewendet werden.
Amarnath Chatterjee

Antworten:

103

HTTP unterstützt keine Umleitung zu einer Seite mithilfe von POST. Wenn Sie irgendwo umleiten, teilt der HTTP-Header "Location" dem Browser mit, wohin er gehen soll, und der Browser stellt eine GET-Anforderung für diese Seite. Sie müssen wahrscheinlich nur den Code für Ihre Seite schreiben, um sowohl GET-Anforderungen als auch POST-Anforderungen zu akzeptieren.

Eli Courtwright
quelle
4
Neugierig, warum meine Antwort nicht akzeptiert wird, denke ich, dass meine Rhetorik solide ist. :) Andererseits bin ich vielleicht ein bisschen voreingenommen ...
Jason Bunting
14
Diese Antwort ist zwar grundsätzlich richtig, aber nicht vollständig. Siehe Jason Bunting Antwort unten für eine viel bessere Problemumgehung.
Adrian Grigore
160

Für Ihr spezielles Beispiel würde ich dies nur tun, da es Ihnen offensichtlich egal ist, ob der Browser die Weiterleitung erhält (indem Sie die Antwort akzeptieren, die Sie bereits akzeptiert haben):

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index() {
   // obviously these values might come from somewhere non-trivial
   return Index(2, "text");
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(int someValue, string anotherValue) {
   // would probably do something non-trivial here with the param values
   return View();
}

Das funktioniert einfach und es gibt kein lustiges Geschäft - so können Sie die Tatsache beibehalten, dass das zweite wirklich nur HTTP-POST-Anforderungen akzeptiert (außer in diesem Fall, der ohnehin unter Ihrer Kontrolle steht) und Sie müssen nicht Verwenden Sie auch TempData. Dies ist der Link, den Sie in Ihrer Antwort angegeben haben.

Ich würde gerne wissen, was daran "falsch" ist, wenn es etwas gibt. Wenn Sie wirklich eine Weiterleitung an den Browser gesendet haben möchten, funktioniert dies natürlich nicht, aber dann sollten Sie sich fragen, warum Sie versuchen würden, dies trotzdem zu konvertieren, da es mir seltsam erscheint.

Hoffentlich hilft das.

Jason Bunting
quelle
7
Wer weiß, warum Sie abgelehnt wurden. Dies ist eine sehr nützliche Methode.
Peter J
2
So habe ich auch dieses Problem immer gelöst. Ein Downvoting macht keinen Sinn.
Adrian Grigore
39
Ich habe abgestimmt, obwohl ich nicht damit einverstanden bin, Leute als Idioten zu bezeichnen, wenn man sie nicht kennt.
Jim Schubert
3
Ich bin kein Downvoter, aber die einzige Vorsicht dabei ist, wenn Sie eine Ansicht mit einem anderen Namen aufrufen oder wenn die Parameter wichtig sind, gehen sie verloren. Der Grund dafür ist, dass die URL die Aktion + Parameter vor der serverseitigen Umleitung widerspiegelt. Dies kann zu Verwirrung beim Benutzer führen, insbesondere wenn er die Seite aktualisiert und sich dann auf einer vorherigen Seite befindet (da bei der Aktualisierung die alte URL verwendet wurde). Diese Technik ist im Wesentlichen dem Server.Transfer von asp.net sehr ähnlich, und es sollten die gleichen Vorsichtsmaßnahmen getroffen werden.
AaronLS
15
Ich habe nicht per se herabgestimmt, aber ich kann Grund dafür sehen. Diese Methode verstößt gegen die vom MVC-Muster festgelegte Codierungskonvention. Es nur funktioniert , wenn die gleiche Aktion aufruft. Wenn es sich um eine andere Aktion handelt, werden die Routing-Werte selbst auf demselben Controller verschraubt und die falsche Ansicht wird zurückgegeben. Kurzum: Tu das nicht.
Erlando
21

Wenn Sie während einer Umleitung Daten zwischen zwei Aktionen übergeben möchten, ohne Daten in die Abfragezeichenfolge aufzunehmen, fügen Sie das Modell in das TempData-Objekt ein.

AKTION

TempData["datacontainer"] = modelData;

AUSSICHT

var modelData= TempData["datacontainer"] as ModelDataType; 

TempData soll eine sehr kurzlebige Instanz sein, und Sie sollten sie nur während der aktuellen und der nachfolgenden Anforderungen verwenden! Da TempData auf diese Weise funktioniert, müssen Sie sicher wissen, wie die nächste Anforderung aussehen wird. Nur wenn Sie zu einer anderen Ansicht umleiten, können Sie dies garantieren.

Daher ist das einzige Szenario, in dem die Verwendung von TempData zuverlässig funktioniert, die Umleitung.

Otto Kanellis
quelle
11

Probier diese

return Content("<form action='actionname' id='frmTest' method='post'><input type='hidden' name='someValue' value='" + someValue + "' /><input type='hidden' name='anotherValue' value='" + anotherValue + "' /></form><script>document.getElementById('frmTest').submit();</script>");
vicky
quelle
2
Hasse
Solch ein Hack, aber es war die einzige Möglichkeit, das zu tun, was ich wollte, ohne DRY zu verletzen oder mein gesamtes Setup neu zu verkabeln! Vielen Dank!
Jamheadart
6

Ich möchte die Antwort von Jason Bunting erweitern

so was

ActionResult action = new SampelController().Index(2, "text");
return action;

Und Eli wird hier sein, um eine Idee zu bekommen, wie man es generisch variabel macht

Kann alle Arten von Controllern bekommen

Yitzhak Weinberg
quelle