防止双重提交

我有一个ASP.NET MVC 3应用程序,它有一个名为Create的后置操作:

 [HttpPost] public virtual ActionResult Create(Issues issues) { if (ModelState.IsValid) { context.Issues.Add(issues); context.SaveChanges(); return RedirectToAction("Index"); } return View(issues); } 

如果我错误地双击提交按钮,它将创建2x问题。 有没有办法防止这种情况,没有使用javascript和禁用按钮,我认为使用RedirectToAction的全部用途是通过使用Post / Redirect / Get设计模式来防止这种情况?

您提到的模式(发布/重定向/获取设计模式)会阻止页面刷新双重发布,因为最后一个操作是GET,而不是POST。

如果您想防止双重发布的双击,您可以:

 1. Disable the button after click 2. Maintain a unique index on 'Issues' and look for duplicates 3. Maintain something in session that gives you an indication of a double post 

还有一些方法……我认为禁用按钮可能是最简单的,因为你无论如何都要重定向到另一个页面。

轻松解决!

单击时禁用提交按钮。 结束。

 $('submitButtonId').click(function(){ $(this).prop('disabled', true); $(this).attr('disabled', 'disabled'); // for jQuery versions < 1.6. }); 

我能想到的最简单的方法是使用Session:

 if (ModelState.IsValid) { DateTime now = DateTime.Now; if (Session["LastAdd"] == null || (now - (DateTime)Session["LastAdd"]).TotalMilliseconds > 1000) { //first time, or more than a second passed since last addition context.Issues.Add(issues); context.SaveChanges(); Session["LastAdd"] = now; } return RedirectToAction("Index"); } 

当您向用户显示表单时,可以生成IssueId,然后在Create方法中检查您是否已经存在此类ID的问题,例如,跳过此类请求。

PRG模式不会阻止这种情况,因为其中的P动作需要时间(通常是这种情况)并且用户可以再次提交表单(通过点击或浏览器刷新),这将导致PRG模式“失败”。

请注意,恶意用户还可以通过快速连续运行多个httppost来绕过所有客户端测量。

上述所有方法的解决方案是使用以下方法检查服务器端的重复提交,如我自己所述。

为方便起见,我引述:

“如果您在表单中使用隐藏的防伪标记(如您所愿),则可以在首次提交时缓存防伪标记,并在需要时从缓存中删除标记,或者在设置的数量后使缓存条目到期时间。

然后,您将能够针对缓存检查每个请求是否已提交特定表单,如果有,则拒绝它。“