当保存到数据库需要很长时间时,如何防止点击双 post?
how to prevent double post on click, when it takes long time to save to db?
我的问题:
如果我有一个简单的 post 请求,我只是在编辑时更改数据库中的一些 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 秒还没有结束,用户可以向相同的编辑方法发送垃圾邮件 post 请求,因此只会保存最新的编辑。我想阻止这种情况。
我读了很多关于这个问题的资料。我当然可以在通过 jquery 提交时禁用提交按钮,但这不是一种解决问题的方法吗?在不禁用按钮的情况下是否还有其他解决方案,只需跳过 post 请求编号 2...x 并只考虑第一个?
HTTP 是无状态的。也就是说,具有相同数据的双 post 是完全有效的(根据传输)。
因此,您有 2 个选择:
- 客户端:禁用按钮,并限制请求。这根本不是 hacky。是迄今为止最常见的解决方案。
- 服务器端:每个会话都有某种监视器锁,因此同一个会话不能重新进入已经在执行的同一个块。
两者比较,我更喜欢客户端选项。不是 100% 安全,但 99% 是可以接受的。
双击问题通常在 UI 中解决,是的。如果您正在创建并控制 UI,那么使用 Javascript.
防止双击那里绝对不是 'hacky'
在我看来,您似乎想要防止有人以某种方式绕过您的 UI 代码来执行额外的点击操作。无论是 disabling/editing 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");
}
我的问题:
如果我有一个简单的 post 请求,我只是在编辑时更改数据库中的一些 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 秒还没有结束,用户可以向相同的编辑方法发送垃圾邮件 post 请求,因此只会保存最新的编辑。我想阻止这种情况。
我读了很多关于这个问题的资料。我当然可以在通过 jquery 提交时禁用提交按钮,但这不是一种解决问题的方法吗?在不禁用按钮的情况下是否还有其他解决方案,只需跳过 post 请求编号 2...x 并只考虑第一个?
HTTP 是无状态的。也就是说,具有相同数据的双 post 是完全有效的(根据传输)。
因此,您有 2 个选择:
- 客户端:禁用按钮,并限制请求。这根本不是 hacky。是迄今为止最常见的解决方案。
- 服务器端:每个会话都有某种监视器锁,因此同一个会话不能重新进入已经在执行的同一个块。
两者比较,我更喜欢客户端选项。不是 100% 安全,但 99% 是可以接受的。
双击问题通常在 UI 中解决,是的。如果您正在创建并控制 UI,那么使用 Javascript.
防止双击那里绝对不是 'hacky'在我看来,您似乎想要防止有人以某种方式绕过您的 UI 代码来执行额外的点击操作。无论是 disabling/editing 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");
}