实现原理:
刷新提交表单,实际提交的是上一次正常提交的表单,所以要做一个标志,判断出是新表单还是上一次的旧表单就可以分辨出是否进行了重复提交操作。
实现方法:
在页面上放置一个Hidden域,当页面第一次载入时,在Session里面保存一个标志,同时,把这个标志保存到页面上的Hidden里面。
提交表单时,判断表单中提交上来的Hidden和Session中的标志是否一致。注意,在每次提交表单的处理之后,要更新Session里面的标志。
1、前端页面代码
注意:
1)、GetSessionToken()函数是为了获得Session里面保存的标志。
2)、Hidden使用了非服务器控件,这是因为使用服务器控件,并在后台直接获取Session的标志并赋值给这个Hidden的时候,刷新提交到服务器的 表单中的Hidden的值也发生了改变,猜想是服务器控件的话,表单里面的值是保持同步的。
2、后台代码:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Security.Cryptography;
using System.Text;
public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //第一次载入的时候,生成一个初始的标志
        if (null == Session["Token"])
        {
            SetToken();
        }
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        if (Request.Form.Get("hiddenTestN").Equals(GetToken()))
        {
            lblMessage.ForeColor = System.Drawing.Color.Blue;
            lblMessage.Text = "正常提交表单";
            SetToken();//别忘了最后要更新Session中的标志
        }
        else
        {
            lblMessage.ForeColor = System.Drawing.Color.Red;
            lblMessage.Text = "刷新提交表单";
        }
    }
    //获得当前Session里保存的标志
    public string GetToken()
    {
        if (null != Session["Token"])
        {
            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;
    } 
}
注意:
1)、在页面第一次载入的时候要生成标志,以后就不用了。
2)、在表单处理的函数的最后,记得要更新标志。
3)、标志选用了当前SessionID加上当前时间毫秒值,基本可以避免标志重复,然后进行MD5,可以缩短下标志。