GET et POST sur la même action de contrôleur dans ASP.NET MVC

91

J'aimerais qu'une seule action réponde à la fois aux Objets et aux Messages. J'ai essayé ce qui suit

[HttpGet]
[HttpPost]
public ActionResult SignIn()

Cela ne semblait pas fonctionner. Aucune suggestion ?

Cranialsurge
la source
2
Pour expliquer le problème: l'action est ignorée. Chaque attribut exclura toutes les autres méthodes de demande, donc l'action finit par n'accepter aucune méthode de demande du tout.
Guffa
Dans ASP.NET MVC2 et VisualStudio 2010, l'exemple de l'OP (avec «[AcceptVerbs (HttpVerbs.Get)]», etc.) donne l'erreur de compilation: «Dupliquer l'attribut 'AcceptVerbs'».
DaveD
4
@Dave Faites-vous [AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]ou [AcceptVerbs(HttpVerbs.Get)][AcceptVerbs(HttpVerbs.Post)]? Je ne sais rien de ces attributs, mais si vous faites le second, c'est peut-être pourquoi vous obtenez cette erreur.
Jared

Réponses:

134

Cela est possible en utilisant l'attribut AcceptVerbs. C'est un peu plus bavard mais plus flexible.

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

Plus d'informations sur msdn .

Ryan Bair
la source
3
Oui, mais que se passe-t-il si la méthode utilise des paramètres (par exemple SignIn (paramètres SingInParams) ... pour GET, ils sont tirés de l'URI (donc [FromUri] doit être spécifié) et pour POST, ils sont pris du corps (donc [ FromBody] doit être spécifié)?
michal.jakubeczy
64

Les actions répondent à la fois aux GET et aux POST par défaut, vous n'avez donc rien à spécifier:

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

En fonction de vos besoins, vous pouvez toujours exécuter une logique différente en fonction de HttpMethod en opérant sur la valeur HttpContext.Request.HttpMethod.

Kurt Schindler
la source
5
c'est bien jusqu'à ce que vous essayiez d'utiliser des modèles d'affichage! dans l'action de publication que vous passeriez généralement dans le viewmodel, j'ai essayé d'utiliser un paramètre facultatif et par défaut, il est nul mais cela ne fonctionne pas.
JBeckton
1
@JBeckton Habituellement, j'ai une méthode GET qui n'a que des paramètres de chaîne de requête SignIn(Guid? UserId)et POST a un modèle de vue SignIn(SomeVM vm)et les deux appellent une méthode privée partagée SignInHandleGetPost(...)... qui prend peut-être VM que la méthode GET doit initialiser, ou des paramètres facultatifs, ou tout ce que vous préférez faire pour refactoriser le code utilisable / partagé.
AaronLS
2
@JBeckton Je viens de l'essayer maintenant avec l'exemple de projet ASP.NET MVC 4.6.1, avec la méthode AccountController.Login(String returnUrl, LoginViewModel model)et cela fonctionne bien. modelest nul sur GET et non nul sur POST. Cependant, il [ValidateForgeryToken]doit être remplacé car ValidateForgeryTokenlève une exception sur les requêtes GET.
Dai
0
[HttpGet]
public ActionResult SignIn()
{
}

[HttpPost]
public ActionResult SignIn(FormCollection form)
{
}
Neil Outler
la source
Ce n'est pas ce que je recherche, c'est l'implémentation MVC par défaut d'avoir des méthodes séparées pour GET et POST via la surcharge de fonctions. Je ne suis pas nouveau dans MVC, j'essaie de faire en sorte que l'action GET réponde également à certains événements POST en plus de l'action POST standard pour la collection de formulaires.
Cranialsurge
Ensuite, vous devez suivre la réponse de Kurts. Aucun attribut ne gérera les deux. Si vous essayez de faire passer des requêtes POST à ​​des actions différentes, cela n'est pas possible. Votre action devra effectuer la commutation que vous recherchez.
Jeremy B.