POBIERZ i POST do tej samej akcji kontrolera w ASP.NET MVC

91

Chciałbym, aby jedna akcja odpowiadała zarówno na Gets, jak i Posty. Wypróbowałem następujące

[HttpGet]
[HttpPost]
public ActionResult SignIn()

To nie wydawało się działać. Jakieś sugestie ?

Cranialsurge
źródło
2
Aby wyjaśnić problem: akcja jest ignorowana. Każdy atrybut będzie wykluczał wszystkie inne metody żądań, więc akcja kończy się nieakceptowaniem żadnych metod żądań.
Guffa
W ASP.NET MVC2 i VisualStudio 2010 przykład OP (z „[AcceptVerbs (HttpVerbs.Get)]” itp.) Podaje błąd kompilacji: „Duplikat atrybutu AcceptVerbs”.
DaveD
4
@Dave Robisz [AcceptVerbs(HttpVerbs.Get|HttpVerbs.Post)]czy [AcceptVerbs(HttpVerbs.Get)][AcceptVerbs(HttpVerbs.Post)]? Nie wiem nic o tych atrybutach, ale jeśli robisz drugie, może to być przyczyną tego błędu.
Jared

Odpowiedzi:

134

Jest to możliwe przy użyciu atrybutu AcceptVerbs. Jest trochę bardziej rozwlekły, ale bardziej elastyczny.

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

Więcej o msdn .

Ryan Bair
źródło
3
Tak, ale co jeśli metoda używa parametrów (np. SignIn (parametry SingInParams) ... dla GET, są one pobierane z URI (więc [FromUri] musi być określone), a dla POST są pobierane z treści (więc [ FromBody]?
michal.jakubeczy
64

Akcje domyślnie odpowiadają zarówno na GET, jak i POST, więc nie musisz niczego określać:

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

W zależności od potrzeb można nadal wykonywać inną logikę w zależności od HttpMethod, działając na wartości HttpContext.Request.HttpMethod.

Kurt Schindler
źródło
5
to jest w porządku, dopóki nie spróbujesz użyć modeli widoku! w akcji post, którą zwykle podajesz w viewmodelu, próbowałem użyć opcjonalnego parametru i domyślnie ustawiono go na null, ale to nie działa.
JBeckton,
1
@JBeckton Zwykle mam metodę GET, która ma tylko parametry ciągu zapytania, SignIn(Guid? UserId)a POST ma model widoku SignIn(SomeVM vm)i oba wywołują udostępnioną metodę prywatną SignInHandleGetPost(...)... która może pobierać maszynę wirtualną, którą musi zainicjować metoda GET, lub opcjonalne parametry, lub cokolwiek wolisz do refaktoryzacji kodu, który można wykorzystać / udostępnić.
AaronLS
2
@JBeckton Właśnie wypróbowałem to teraz z przykładowym projektem ASP.NET MVC 4.6.1, z metodą AccountController.Login(String returnUrl, LoginViewModel model)i działa dobrze. modelma wartość null w przypadku GET i niezerową w przypadku POST. Jednak [ValidateForgeryToken]musi zostać zastąpiony, ponieważ ValidateForgeryTokenzgłasza wyjątek w żądaniach GET.
Dai
0
[HttpGet]
public ActionResult SignIn()
{
}

[HttpPost]
public ActionResult SignIn(FormCollection form)
{
}
Neil Outler
źródło
To nie jest to, czego szukam, to domyślna implementacja MVC z oddzielnymi metodami dla GET i POST poprzez przeciążenie funkcji. Nie jestem nowy w MVC, staram się, aby akcja GET odpowiadała również na niektóre zdarzenia POST oprócz standardowej akcji POST dla kolekcji formularzy.
Cranialsurge,
Następnie musisz postępować zgodnie z odpowiedzią Kurtsa. Żaden atrybut nie obsługuje obu. Jeśli próbujesz, aby żądania POST były kierowane do różnych działań, nie jest to możliwe. Twoje działanie będzie musiało wykonać przełączenie, którego szukasz.
Jeremy B.