最近我开始使用 MVC,在此之前我使用“经典”ASP.NET。
在使用 Ruby on Rails (RoR) 之后,我想知道如何在 MVC 中实现类似于 RoR 操作方式的 POST 请求处理。在 RoR 中,您使用 Post
方法,因此您只需要一个 View 的函数。
在 ASP.NET MVC 中,我需要为 GET
和 POST
使用 2 个单独的函数,因此我需要对相同的数据进行两次初始化,但我没有这样做喜欢在我的代码中重复一些东西。
如何在一种方法中检查请求是否为 POST
?
更新:
找到解决方案:我必须使用 Request.HttpMethod。
谢谢!
最佳答案
我遇到这个问题想知道同样的事情。下面是我的情况和我使用的解决方案的详细描述(它利用了此处提供的其他答案)。我最初尝试使用两个单独的方法方法,但是当这些方法的方法签名变得相同时我遇到了问题。
我有一个显示报表数据的页面。在页面顶部有一个包含一些字段的表单,允许用户指定报告参数,例如开始日期、结束日期等。
我最初是通过创建两个单独的方法来处理 Get 和 Post 方法来解决这个问题的。 post 方法会将浏览器重定向到 get 方法,以便将指定的任何参数添加到查询字符串中,这样浏览器就不会通过对话框提示用户说它将重新发送他们输入的数据如果他们刷新。注意:我后来意识到我可以通过将我的表单元素的方法属性设置为“获取”来实现这一点,但我认为理想情况下 Controller 不应该知道 View 是如何实现的,所以在我看来这是无关紧要的。
在开发这两种方法时,我最终发现自己处于方法签名变得相同的情况。此外,我的这两种方法的代码变得几乎相同,所以我决定将它们合并为一个方法并只检查请求动词,这样当请求不是“Get”时我可以做一些稍微不同的事情。下面显示了我的两种方法的提炼示例:
// this will not compile because the method signatures are the same
public ActionResult MyReport(DateRangeReportItem report)
{
// if there are no validation errors and the required report parameters are completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// retrieve report data and populate it on the report model
report.Result = GetReportData(report.CreateReportParameters());
}
return View(report);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
if (ModelState.IsValid && report.ParametersAreComplete)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
else
{
// there were validation errors, or the report parameters are not yet complete
return View(report);
}
}
为什么我要接受一个模型对象作为我的 get 方法的参数?原因是我想利用已经内置到模型对象中的验证逻辑。如果有人使用查询字符串中已指定的所有参数直接导航到我的页面,那么我想继续检索报告数据并将其显示在页面上。但是,如果查询字符串中指定的参数无效,那么我也希望页面上出现验证错误。通过将我的模型对象作为参数,MVC 框架将自动尝试填充它并捕获任何验证错误,而无需我进行任何额外的工作。
我使用针对此问题发布的其他答案在我的项目中的基 Controller 类上创建 RequestHttpVerb 属性:
public HttpVerbs RequestHttpVerb
{
get { return (HttpVerbs)Enum.Parse(typeof(HttpVerbs), this.Request.HttpMethod, true); }
}
所以最后我的综合方法如下所示:
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult MyReport(DateRangeReportItem report)
{
// check if there are any validation errors in the model
// and whether all required report parameters have been completed
if (ModelState.IsValid && report.ParametersAreComplete)
{
// this is unnecessary if the form method is set to "Get"
// but within the controller I do not know for sure if that will be the case in the view
if (HttpVerbs.Get != this.RequestHttpVerb)
{
// redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
// this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
}
// there were no validation errors and all required report parameters are complete
// retrieve report data and populate that data on the model
report.Result = GetReportData(report.CreateReportParameters());
}
// display the view with the report object
// Any model state errors that occurred while populating the model will result in validation errors being displayed
return View(report);
}
这是我目前解决问题的方法。我宁愿不必检查 Request.HttpMethod 属性来确定我是否需要执行重定向,但我没有看到我的问题的另一种解决方案。我本来可以保留两个单独的方法来处理 Get 和 Post 请求,但是相同的方法签名阻止了这种情况。我宁愿重命名我的 Post 操作处理程序方法以避免方法签名冲突,并使用某种机制向 MVC 框架指示我重命名的方法仍应处理“MyReport”操作,但我不知道任何此类机制在 MVC 框架中。
关于c# - 在 ASP.NET MVC 中处理发布请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2321043/