GET e POST para a mesma ação do controlador na ASP.NET MVC

90

Eu gostaria que uma única ação respondesse tanto a Gets quanto a Posts. Eu tentei o seguinte

[HttpGet]
[HttpPost]
public ActionResult SignIn()

Isso não pareceu funcionar. Alguma sugestão ?

Surto craniano
fonte
2
Para explicar o problema: A ação é ignorada. Cada atributo excluirá todos os outros métodos de solicitação, portanto, a ação acaba não aceitando nenhum método de solicitação.
Guffa
Na ASP.NET MVC2 e VisualStudio 2010, o exemplo do OP (com "[AcceptVerbs (HttpVerbs.Get)]", etc) dá o erro de compilação: "Duplicar atributo 'AcceptVerbs'".
DaveD
4
@Dave Você está fazendo [AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]ou [AcceptVerbs(HttpVerbs.Get)][AcceptVerbs(HttpVerbs.Post)]? Não sei nada sobre esses atributos, mas se você está fazendo o segundo, pode ser por isso que está recebendo esse erro.
Jared,

Respostas:

132

Isso é possível usando o atributo AcceptVerbs. É um pouco mais prolixo, mas mais flexível.

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

Mais no msdn .

Ryan Bair
fonte
3
Sim, mas e se o método usar parâmetros (por exemplo, SignIn (parâmetros SingInParams) ... para GET, eles são retirados do URI (então [FromUri] deve ser especificado) e para POST eles são retirados do corpo (então [ FromBody] deve ser especificado)?
michal.jakubeczy
64

As ações respondem a GETs e POSTs por padrão, então você não precisa especificar nada:

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

Dependendo da sua necessidade, você ainda pode executar lógicas diferentes dependendo do HttpMethod, operando no valor HttpContext.Request.HttpMethod.

Kurt Schindler
fonte
5
isso é bom até você tentar usar modelos de visualização! na ação post que você normalmente passaria no viewmodel, tentei usar um parâmetro opcional e padronizá-lo como null, mas isso não funciona.
JBeckton
1
@JBeckton Normalmente eu tenho um método GET que tem apenas parâmetros de string de consulta SignIn(Guid? UserId)e POST tem modelo de visão SignIn(SomeVM vm)e ambos chamam um método privado compartilhado SignInHandleGetPost(...)... que pode levar VM que o método GET deve inicializar, ou parâmetros opcionais, ou o que você preferir fazer para refatorar o código reutilizável / compartilhado.
AaronLS
2
@JBeckton Acabei de tentar agora com o projeto de amostra ASP.NET MVC 4.6.1, com o método AccountController.Login(String returnUrl, LoginViewModel model)e funciona bem. modelé nulo em GET e não nulo em POST. No entanto, [ValidateForgeryToken]precisa ser substituído porque ValidateForgeryTokenlança uma exceção nas solicitações GET.
Dai
0
[HttpGet]
public ActionResult SignIn()
{
}

[HttpPost]
public ActionResult SignIn(FormCollection form)
{
}
Neil Outler
fonte
Não é isso que estou procurando, essa é a implementação MVC padrão de ter métodos separados para GET e POST por meio de sobrecarga de função. Não sou novo no MVC, estou tentando fazer com que a ação GET também responda a determinados eventos POST, além da ação POST padrão para a coleção de formulários.
Cranialsurge
Então você precisa seguir a resposta de Kurts. Nenhum atributo irá lidar com ambos. Se você estiver tentando fazer com que as solicitações POST sejam direcionadas para ações diferentes, isso não é possível. Sua ação terá que realizar a troca que você está procurando.
Jeremy B.