如何防止ASP.NET MVC 3中的重复表单提交?

时间:2011-06-01 21:34:23

标签: asp.net-mvc-3 form-submit

我有一个剃刀视图,它呈现一个html表单并将其发布到服务器。 如果表单值正确,则它将保存到数据库。 插入后,我会重定向到另一个用户可以进行进一步更改的视图。

现在用户可以点击浏览器后退按钮并重新提交表单以在db。中创建另一条记录。

如何防止在我的MVC应用中重复提交?

4 个答案:

答案 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)