1.使用Session,避免用户重复提交(F5刷新时)
0.起因
当用户上传文件后F5刷新浏览器会导致文件的重复提交和相关程序的重复执行。
1.实现原理
由于刷新提交表单,实际上提交的就是上一次正常提交的表单,所以我们只要做一个标志,判断出是新表单还是上一次的旧表单就可以分辨出是否进行了重复提交操作。
2.实现方法
在页面上放置一个Hidden域,当页面第一次载入的时候,在Session里面保存一个标志,同时,把这个标志保存到页面上的Hidden里面。
在提交表单时,判断表单中提交上来的Hidden和Session中的标志是否一致,就可以知道是正常的提交表单,还是刷新页面导致的重复提交。
需要注意的是,在每次提交表单的处理之后,要更新Session里面的标志。
3.调试后发现的实现原理
Session值 | Hidden值 | |
第一次页面载入后 | 初试化为A | 初始化为A |
第一次提交表单后 | 由A变成B | 由A变成B |
F5刷新页面时 | 用B去进行比较 | 用A去进行比较 |
F5刷新页面后 | 初始化为C | 初始化为C |
第二次提交表单时 | 用C比较 | 用C比较 |
也就是说F5刷新页面,到这一句时
if(Request.Form.Get("hiddenTestN").Equals(GetToken()))
GetToken()获取的是Session已经更新后的值 B
Request.Form.Get("hiddenTestN")获取的是Hidden以前的值 A
而真正的提交表单时,Request.Form.Get("hiddenTestN")也获取的是Hidden更新后的值 B
4.代码
前台
<asp:FileUploadID="FileUploadChange"runat="server"CssClass="col-lg-3"/> <asp:ButtonID="ButtonUploadChange"runat="server"CausesValidation="false"CssClass="btn btn-primary"OnClick="ButtonUploadChange_Click"Text="上传"ToolTip="仅允许上传.csv文件"/> <input id="hiddenTest" type="hidden" value="<%=GetToken() %>" name="hiddenTestN"/>
后台
using System.Web.Security; public partial class Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { if ( Session["Token"]==null ) { SetToken(); } } } //获得当前Session里保存的标志 public string GetToken() { if (Session["Token"] != null) { return Session["Token"].ToString(); } else { return string.Empty; } } //生成标志,并保存到Session private void SetToken() { Session.Add("Token", UserMd5(Session.SessionID + DateTime.Now.Ticks.ToString())); } //这个函数纯粹是为了让标志稍微短点儿,一堆乱码还特有神秘感,另外,这个UserMd5函数是网上找来的现成儿的 protected string UserMd5(string str1) { string cl1 = str1; string pwd = ""; MD5 md5 = MD5.Create(); // 加密后是一个字节类型的数组 byte[] s = md5.ComputeHash(Encoding.Unicode.GetBytes(cl1)); // 通过使用循环,将字节类型的数组转换为字符串,此字符串 是常规字符格式化所得 for (int i = 0; i < s.Length; i++) { // 将得到的字符串使用十六进制类型格式。格式后的字符是 小写的字母,如果使用大写(X)则格式后的字符是大写字符 pwd = pwd + s[i].ToString("X"); } return pwd; } protected void ButtonUploadChange_Click(object sender, EventArgs e) { if (Request.Form.Get("hiddenTestN").Equals(GetToken())) { // 此处写按钮执行的具体代码 SetToken();//别忘了最后要更新Session中的标志 } else { Response.Redirect(Request.RawUrl);//手动给用户刷新页面 } } }
每个上传按钮都要写成这种格式
protected void BtnUpload(object sender, EventArgs e) { if (Request.Form.Get("hiddenTestN").Equals(GetToken())) { // 此处写按钮执行的具体代码 SetToken();//别忘了最后要更新Session中的标志 } else { Response.Redirect(Request.RawUrl); } }