MVC [HttpPost/HttpGet] for Action

asp.net MvcModel View-Controller

asp.net Mvc Problem Overview


I am using MVC C#.

Can somebody give an example on why one would use

[HttpPost/HttpGet] 

for an Action. How can an active have both - what is the practical use?

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

Let's say you have a Login action which provides the user with a login screen, then receives the user name and password back after the user submits the form:

public ActionResult Login() {
    return View();
}

public ActionResult Login(string userName, string password) {
    // do login stuff
    return View();
}

MVC isn't being given clear instructions on which action is which, even though we can tell by looking at it. If you add [HttpGet] to the first action and [HttpPost] to the section action, MVC clearly knows which action is which.

Why? See Request Methods. Long and short: When a user views a page, that's a GET request and when a user submits a form, that's usually a POST request. HttpGet and HttpPost just restrict the action to the applicable request type.

[HttpGet]
public ActionResult Login() {
    return View();
}

[HttpPost]
public ActionResult Login(string userName, string password) {
    // do login stuff
    return View();
}

You can also combine the request method attributes if your action serves requests from multiple verbs:

[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)].

Solution 2 - asp.net Mvc

You don't need to specify both at the same time, unless you're specifically restricting the other verbs (i.e. you don't want PUT or DELETE, etc).

Contrary to some of the comments, I was also unable to use both Attributes [HttpGet, HttpPost] at the same time, but was able to specify both verbs instead.

Actions

	private ActionResult testResult(int id)
	{
		return Json(new {
							// user input
							input = id,
							// just so there's different content in the response
							when = DateTime.Now,
							// type of request
							req = this.Request.HttpMethod,
							// differentiate calls in response, for matching up
							call = new StackTrace().GetFrame(1).GetMethod().Name
						},
						JsonRequestBehavior.AllowGet);
	}
	public ActionResult Test(int id)
	{
		return testResult(id);
	}
	[HttpGet]
	public ActionResult TestGetOnly(int id)
	{
		return testResult(id);
	}
	[HttpPost]
	public ActionResult TestPostOnly(int id)
	{
		return testResult(id);
	}
	[HttpPost, HttpGet]
	public ActionResult TestBoth(int id)
	{
		return testResult(id);
	}
	[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
	public ActionResult TestVerbs(int id)
	{
		return testResult(id);
	}

Results

via POSTMAN, formatting by markdowntables

| Method 	| URL                  	| Response                                                                               	|
|--------	|----------------------	|----------------------------------------------------------------------------------------	|
| GET    	| /ctrl/test/5         	| { "input": 5, "when": "/Date(1408041216116)/", "req": "GET", "call": "Test" }          	|
| POST   	| /ctrl/test/5         	| { "input": 5, "when": "/Date(1408041227561)/", "req": "POST", "call": "Test" }         	|
| PUT    	| /ctrl/test/5         	| { "input": 5, "when": "/Date(1408041252646)/", "req": "PUT", "call": "Test" }          	|
| GET    	| /ctrl/testgetonly/5  	| { "input": 5, "when": "/Date(1408041335907)/", "req": "GET", "call": "TestGetOnly" }   	|
| POST   	| /ctrl/testgetonly/5  	| 404                                                                                    	|
| PUT    	| /ctrl/testgetonly/5  	| 404                                                                                    	|
| GET    	| /ctrl/TestPostOnly/5 	| 404                                                                                    	|
| POST   	| /ctrl/TestPostOnly/5 	| { "input": 5, "when": "/Date(1408041464096)/", "req": "POST", "call": "TestPostOnly" } 	|
| PUT    	| /ctrl/TestPostOnly/5 	| 404                                                                                    	|
| GET    	| /ctrl/TestBoth/5     	| 404                                                                                    	|
| POST   	| /ctrl/TestBoth/5     	| 404                                                                                    	|
| PUT    	| /ctrl/TestBoth/5     	| 404                                                                                    	|
| GET    	| /ctrl/TestVerbs/5    	| { "input": 5, "when": "/Date(1408041709606)/", "req": "GET", "call": "TestVerbs" }     	|
| POST   	| /ctrl/TestVerbs/5    	| { "input": 5, "when": "/Date(1408041831549)/", "req": "POST", "call": "TestVerbs" }    	|
| PUT    	| /ctrl/TestVerbs/5    	| 404                                                                                    	|

Solution 3 - asp.net Mvc

In Mvc 4 you can use AcceptVerbsAttribute, I think this is a very clean solution

[AcceptVerbs(WebRequestMethods.Http.Get, WebRequestMethods.Http.Post)]
public IHttpActionResult Login()
{
   // Login logic
}

Solution 4 - asp.net Mvc

You cant combine this to attributes.

But you can put both on one action method but you can encapsulate your logic into a other method and call this method from both actions.

The ActionName Attribute allows to have 2 ActionMethods with the same name.

[HttpGet]
public ActionResult MyMethod()
{
    return MyMethodHandler();
}

[HttpPost]
[ActionName("MyMethod")]
public ActionResult MyMethodPost()
{
    return MyMethodHandler();
}

private ActionResult MyMethodHandler()
{
    // handle the get or post request
    return View("MyMethod");
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNate PetView Question on Stackoverflow
Solution 1 - asp.net MvcJesse HallamView Answer on Stackoverflow
Solution 2 - asp.net MvcdrzausView Answer on Stackoverflow
Solution 3 - asp.net MvcBen AndersonView Answer on Stackoverflow
Solution 4 - asp.net MvcdknaackView Answer on Stackoverflow