MVC中的[HttpPost/HttpGet]是用于Action的。

55

我正在使用MVC C#。

有人可以举个例子说明为什么要使用它吗?

[HttpPost/HttpGet] 

怎么为操作同时设置两种状态?有什么实际用途吗?

4个回答

91

假设你有一个名为Login的操作,该操作提供用户登录界面,然后在用户提交表单后接收用户名和密码:

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

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

尽管我们能够通过查看代码区分每个操作,但MVC并没有明确指定每个操作是什么。如果您在第一个操作添加[HttpGet],并在第二个操作添加[HttpPost],MVC就可以清楚地知道每个操作的类型。

为什么?请参见请求方法。简单来说:当用户查看页面时,这是一种GET请求;当用户提交表单时,通常是一种POST请求。HttpGet和HttpPost只是限制操作适用的请求类型。

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

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

如果你的操作服务于多个动词的请求,你也可以结合使用请求方法属性:

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


谢谢你的回答。我明白你的意思并已相应地使用它。从网上的一些阅读中,我得出的印象是我们可以在同一个操作中使用 [HttpGet] 和 [HttpPost](不分开)。 - Nate Pet
4
刚刚尝试了MVC4。[HttpGet][HttpPost]无法生效,它只接受GET请求(或者首先写的那个动词)。然而,[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]可以正常工作。 - angularsen
@AndreasLarsen:也许考虑专门发布一个关于这个问题的问题,这样微软就可以看到它了。如果我能得到确认,那么我会编辑我的答案来解决这个问题。 - Jesse Hallam
1
我可以确认AndreasLarsen所报告的内容。您必须使用AcceptVerbs才能在方法上使用2个或更多的动词。 - Paul
@Kivin 我已经在MVC5中测试了[HttpGet,HttpPost],但两个动词都无法正常工作。drzaus的答案也证实了它不起作用。然而,[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]可以正常工作。 - Co7e
感谢 AcceptVerbs 的解决方案。不知何故,当我指定 [HttpGet] 和 [HttpOptions] 时无法正常工作。 - Aleksander Bethke

26

除非您明确限制其他动词(即不希望使用PUT或DELETE等),否则无需同时指定两者。

与某些评论相反,我也无法同时使用属性[HttpGet,HttpPost],但可以指定两种动词。

操作

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

结果

通过POSTMAN,格式由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                                                                                       |

好的例子。谢谢。 - Phiber

8
在Mvc 4中,您可以使用AcceptVerbsAttribute,我认为这是一个非常干净的解决方案。
[AcceptVerbs(WebRequestMethods.Http.Get, WebRequestMethods.Http.Post)]
public IHttpActionResult Login()
{
   // Login logic
}

6

您不能将这两个属性合并。

但是,您可以将两者放在一个操作方法中,但是您可以将逻辑封装到其他方法中,并从两个操作中调用此方法。

ActionName 属性允许使用相同名称的 2 个 ActionMethods。

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

3
不确定“你不能将这两个属性合并”的含义,但是你可以像另一个答案中所示那样合并属性。 - user146043
我尝试给一个操作添加 [HttpGet, HttpPost],但只有第一个属性起作用,所以对我来说这个答案是正确的。 - Marcin
1
[AcceptVerbs(HttpVerbs.Post|HttpVerbs.Get)] 可以使用。我刚试过了。然而,在同一个操作上同时使用 [HttpGet] 和 [HttpPost] 似乎只对第一个动词有效。 - angularsen
它并不是错误的,因为它可以工作,但使用acceptvebs可以将httppost和httpget结合起来,因此它是不必要的,正如之前所示。 - CubanTurin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接