【发布时间】:2012-07-30 20:39:14
【问题描述】:
我正在使用 MVC C#。
有人可以举个例子说明为什么要使用
[HttpPost/HttpGet]
对于一个动作。一个主动者怎么能两者兼得——有什么实际用途?
【问题讨论】:
标签: asp.net-mvc model-view-controller
我正在使用 MVC C#。
有人可以举个例子说明为什么要使用
[HttpPost/HttpGet]
对于一个动作。一个主动者怎么能两者兼得——有什么实际用途?
【问题讨论】:
标签: asp.net-mvc model-view-controller
假设您有一个Login 操作,它为用户提供登录屏幕,然后在用户提交表单后接收用户名和密码:
public ActionResult Login() {
return View();
}
public ActionResult Login(string userName, string password) {
// do login stuff
return View();
}
MVC 没有得到明确的指示,说明哪个动作是哪个动作,尽管我们可以通过查看它来判断。如果将 [HttpGet] 添加到第一个动作,将 [HttpPost] 添加到部分动作,MVC 清楚地知道哪个动作是哪个。
为什么?见Request Methods。长短:当用户查看页面时,这是一个 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)].
【讨论】:
您不需要同时指定两者,除非您特别限制 other 动词(即您不想要 PUT 或 DELETE 等)。
与某些 cmets 不同,我也无法同时使用两个属性 [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 |
【讨论】:
在 Mvc 4 中你可以使用 AcceptVerbsAttribute,我认为这是一个非常干净的解决方案
[AcceptVerbs(WebRequestMethods.Http.Get, WebRequestMethods.Http.Post)]
public IHttpActionResult Login()
{
// Login logic
}
【讨论】:
你不能把它和属性结合起来。
但是您可以将两者都放在一个操作方法上,但您可以封装您的 逻辑到另一个方法中,并从两个动作中调用这个方法。
ActionName 属性允许有 2 个同名的 ActionMethod。
[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");
}
【讨论】: