当保存到数据库需要很长时间时,如何防止双击
本文关键字:何防止 双击 长时间 保存 数据库 | 更新日期: 2024-10-20 23:40:52
我的问题:
如果我有一个简单的帖子请求,我只是在编辑时更改数据库中的一些Voodoo项目:
[HttpPost]
[ValidateAntiForgeryToken]
[SessionStateActionFilter]
public ActionResult Edit(MonkeyJar voodooMonkey)
{
if (!this.service.EditMonkey(voodooMonkey))
return RedirectToAction("Edit",voodooMonkey);
return RedirectToAction("Index");
}
假设EditMonkey需要1.5秒来响应,而这1.5秒还没有结束。用户可以将请求发送到相同的编辑方法,因此只保存更新的编辑。我想防止这种情况发生。
我读了很多关于这个问题的书。当然,我可以通过jquery在提交时禁用提交按钮,但这不是一种解决问题的方法吗?如果不禁用按钮,跳过第2…x个帖子请求,只考虑第一个请求,难道没有其他解决方案吗?
双击问题通常在UI中解决,是的。如果你正在创建并控制UI,那么使用Javascript阻止双击绝对不是"黑客"行为。
对我来说,这听起来像是你想防止有人以某种方式绕过你的UI代码来执行额外的点击操作。无论是禁用/编辑Javascript,糟糕的浏览器Javascript支持,还是其他什么。
您可以对会话状态执行某些操作。如果你一次只允许一次编辑,你可以这样做(伪代码):
[HttpPost]
[ValidateAntiForgeryToken]
[SessionStateActionFilter]
public ActionResult Edit(MonkeyJar voodooMonkey)
{
//Prevent double-submit
if (Session.IsEditActive)
{
//TODO: determine if you want to show an error, or just ignore the request
}
Session.IsEditActive = true;
try
{
if (!this.service.EditMonkey(voodooMonkey))
{
//I'm thinking you need this line here in case the Redirect does the Thread.Abort() before the finally gets called. (Is that possible? Too lazy to test. :) Probably a race condition--I'd keep it for a guaruntee)
Session.IsEditActive = false;
return RedirectToAction("Edit",voodooMonkey);
}
}
finally
{
//Ensure that we re-enable edits, even on errors.
Session.IsEditActive = false;
}
return RedirectToAction("Index");
}
Http是无状态的。也就是说,具有相同数据的双重帖子是完全有效的(根据运输)。
因此,这给你留下了两个选项:
- 客户端:禁用按钮,并限制请求。这一点也不生气。是迄今为止最常见的解决方案
- 服务器端:每个会话都有某种监视器锁,这样同一会话就不能重新进入已经执行的同一块
比较两者,我更喜欢客户端选项。不是100%安全,但99%可以接受。