[asp.net-mvc] MVC [HttpPost/HttpGet] for Action

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?

This question is related to asp.net-mvc model-view-controller

The answer is


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
}

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                                                                                       |

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");
}