GET und POST an dieselbe Controller-Aktion in ASP.NET MVC

90

Ich möchte, dass eine einzige Aktion sowohl auf Gets als auch auf Posts reagiert. Ich habe folgendes versucht

[HttpGet]
[HttpPost]
public ActionResult SignIn()

Das schien nicht zu funktionieren. Irgendwelche Vorschläge ?

Cranialsurge
quelle
2
So erklären Sie das Problem: Die Aktion wird ignoriert. Jedes Attribut schließt alle anderen Anforderungsmethoden aus, sodass die Aktion überhaupt keine Anforderungsmethoden akzeptiert.
Guffa
In ASP.NET MVC2 und VisualStudio 2010 gibt das OP-Beispiel (mit "[AcceptVerbs (HttpVerbs.Get)]" usw.) den Kompilierungsfehler "Duplicate 'AcceptVerbs' attribute".
DaveD
4
@ Dave Machst du [AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]oder [AcceptVerbs(HttpVerbs.Get)][AcceptVerbs(HttpVerbs.Post)]? Ich weiß nichts über diese Attribute, aber wenn Sie die Sekunde ausführen, erhalten Sie möglicherweise diesen Fehler.
Jared

Antworten:

132

Dies ist mit dem Attribut AcceptVerbs möglich. Es ist etwas ausführlicher, aber flexibler.

[AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]
public ActionResult SignIn()
{
}

Mehr zu msdn .

Ryan Bair
quelle
3
Ja, aber was ist, wenn die Methode Parameter verwendet (z. B. SignIn (SingInParams-Parameter) ... für GET werden sie vom URI übernommen (daher muss [FromUri] angegeben werden) und für POST vom Body übernommen (also [) FromBody] muss angegeben werden)?
michal.jakubeczy
64

Aktionen reagieren standardmäßig sowohl auf GETs als auch auf POSTs, sodass Sie nichts angeben müssen:

public ActionResult SignIn()
{
    //how'd we get here?
    string method = HttpContext.Request.HttpMethod;
    return View();
}

Abhängig von Ihren Anforderungen können Sie je nach HttpMethod immer noch unterschiedliche Logik ausführen, indem Sie den Wert HttpContext.Request.HttpMethod verwenden.

Kurt Schindler
quelle
5
Dies ist in Ordnung, bis Sie versuchen, Ansichtsmodelle zu verwenden! In der Post-Aktion, die Sie normalerweise im Ansichtsmodell übergeben würden, habe ich versucht, einen optionalen Parameter zu verwenden und ihn standardmäßig auf null zu setzen, aber das funktioniert nicht.
JBeckton
1
@JBeckton Normalerweise habe ich eine GET-Methode, die nur Abfragezeichenfolgenparameter enthält, SignIn(Guid? UserId)und POST hat ein Ansichtsmodell SignIn(SomeVM vm)und beide rufen eine gemeinsam genutzte private Methode auf SignInHandleGetPost(...)... die möglicherweise eine VM benötigt, die von der GET-Methode initialisiert werden muss, oder optionale Parameter oder was auch immer Sie bevorzugen zum Refactoring des wiederverwendbaren / gemeinsam genutzten Codes.
AaronLS
2
@JBeckton Ich habe es gerade mit dem ASP.NET MVC 4.6.1-Beispielprojekt versucht, mit der Methode AccountController.Login(String returnUrl, LoginViewModel model)und es funktioniert gut. modelist bei GET null und bei POST nicht null. Allerdings [ValidateForgeryToken]muss überschriebenen sein , weil ValidateForgeryTokeneine Ausnahme auf GET - Anfragen führt.
Dai
0
[HttpGet]
public ActionResult SignIn()
{
}

[HttpPost]
public ActionResult SignIn(FormCollection form)
{
}
Neil Outler
quelle
Das ist nicht das, wonach ich suche, das ist die Standard-MVC-Implementierung mit getrennten Methoden für GET und POST über Funktionsüberladung. Ich bin nicht neu in MVC. Ich versuche, dass die GET-Aktion zusätzlich zur Standard-POST-Aktion für die Formularsammlung auch auf bestimmte POST-Ereignisse reagiert.
Cranialsurge
Dann müssen Sie der Antwort der Kurten folgen. Kein Attribut kann beides verarbeiten. Wenn Sie versuchen, POST-Anforderungen für verschiedene Aktionen zu verwenden, ist dies nicht möglich. Ihre Aktion muss den gewünschten Wechsel durchführen.
Jeremy B.