我有一个剃刀视图,它呈现一个html表单并将其发布到服务器。 如果表单值正确,则它将保存到数据库。 插入后,我会重定向到另一个用户可以进行进一步更改的视图。
现在用户可以点击浏览器后退按钮并重新提交表单以在db。中创建另一条记录。
如何防止在我的MVC应用中重复提交?
答案 0 :(得分:5)
一种解决方案是在表单加载时随机生成的表单上放置一个隐藏的“标记”字段。当您看到该令牌暂时返回到创建存储区时(例如,如果您正在使用会话,则在会话中)。如果再次看到同一个表格,您可以假设同一表格一起快速提交两次。
答案 1 :(得分:2)
创建一个cookie,以便在成功时表示该特定页面。如果使用cookie重放(浏览器现在会在每次请求时发送),您就知道不允许新的尝试。
答案 2 :(得分:2)
在处理发布请求后,将用户重定向到另一个HttpGet操作。 因此,当用户刷新浏览器时,不会再次调用post动作。
返回RedirectToAction(“YourActionMethod”);
答案 3 :(得分:2)
虽然可以进行客户端验证,但它不够安全。
我不确定这种方法是否适用于MVC 3,但我所做的是实现ActionFilterAttribute
这是实施:
public class PreventFrequentCallsAttribute : ActionFilterAttribute
{
public int DelayRequest = 5;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var request = filterContext.HttpContext.Request;
var cache = filterContext.HttpContext.Cache;
var originationInfo = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;
originationInfo += request.UserAgent;
var targetInfo = request.RawUrl + request.QueryString;
var hashValue = string.Join("", MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(originationInfo + targetInfo)).Select(s => s.ToString("x2")));
if (cache[hashValue] != null)
{
filterContext.Controller.ViewData.ModelState.AddModelError("ExcessiveRequests", "Excessive Request Attempts Detected.");
}
else
{
cache.Add(hashValue, originationInfo, null, DateTime.Now.AddSeconds(DelayRequest), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
}
base.OnActionExecuting(filterContext);
}
}
稍后,在目标控制器中,只需添加此属性:
[PreventFrequentCalls(3)]
public PartialViewResult LogOn(LogOnViewModel model)