以前也研究過,始終沒找到好的辦法,看了微軟Msdn上的解決方案,使用後發現存在較多漏洞,考慮的情況太少,如頁面加載後沒有提交,始終刷新,在同一瀏覽器打開多個各選項卡,每個選項卡打開同一頁面或不同頁面,以下是我的解決方案,
public class RefreshServe : System.Web.UI.Page
{
private static ILog log = LogManager.GetLogger(typeof(RefreshServe));
private readonly string REFRESH_TICKET_NAME = "__RefreshTicketArray";
private readonly string HIDDEN_FIELD_NAME = "__RefreshHiddenField";
private readonly string HIDDEN_PAGE_GUID = "__RefreshPageGuid";
/// <summary>
/// 爲True表示頁面刷新,False爲正常提交
/// </summary>
public bool IsPageRefreshed
{
get
{
if (IsPostBack && !CheckRefreshFlag())
{
log.Debug("刷新了頁面");
return true;
}
else
{
log.Debug("正常提交");
return false;
}
}
}
/// <summary>
/// 呈現前更新標識
/// </summary>
/// <param name="e"></param>
protected override void OnPreRender(EventArgs e)
{
log.Debug("執行OnPreRender");
base.OnPreRender(e);
UpdateRefreshFlag();
}
/// <summary>
/// 更新標識,正常提交都刪除該次提交的時間,並生產當前新的時間
/// </summary>
private void UpdateRefreshFlag()
{
#region Session模式
////設置頁面唯一標識
//SetCurPageGuid();
//DataTable RefreshSign = GetRefreshSession();
//string pageGuid = GetCurPageGuid();
//DataRow newRow;
//if (RefreshSign.Rows.Count > 0)
//{
// DataRow[] existRow = RefreshSign.Select("GUID='none'");
// if (existRow.Length > 0)
// {
// foreach (DataRow row in existRow)
// row.Delete();
// log.Debug("找到爲none標識的行並刪除");
// }
// existRow = RefreshSign.Select("GUID='" + pageGuid + "'");
// if (existRow.Length > 0)
// {
// foreach (DataRow row in existRow)
// row.Delete();
// log.Debug("找到爲" + pageGuid + "標識的行並刪除");
// }
//}
//string submitTime = DateTime.Now.ToString("hhmmss.fffff");
////當前提交時間保存到隱藏域
//ClientScript.RegisterHiddenField(HIDDEN_FIELD_NAME, submitTime);
////同時添加到DataTable列表中
//newRow = RefreshSign.NewRow();
//newRow["submitTime"] = submitTime;
//newRow["GUID"] = pageGuid;
//log.Debug("即將要新增的票證:submitTime:" + submitTime + " Guid:" + pageGuid.ToString());
//RefreshSign.Rows.Add(newRow);
//log.Debug("UpdateRefreshFlag中當前DataTable中存在的記錄數爲:" + RefreshSign.Rows.Count);
//foreach (DataRow row in RefreshSign.Rows)
//{
// log.Info("row['submitTime']:" + row["submitTime"] + " row['GUID']:" + row["GUID"]);
//}
#endregion
#region Cookie模式
//註冊頁面唯一標識並返回
string pageGuid = SetCurPageGuid();
HttpCookie cookie = GetRefreshTicket();
if (cookie.Values.Count > 0)
{
cookie.Values.Remove(pageGuid);
log.Debug("當前清除的cookie變是:" + pageGuid);
}
string submitTime = DateTime.Now.ToString("hhmmss.fffff");
//當前提交時間保存到隱藏域
ClientScript.RegisterHiddenField(HIDDEN_FIELD_NAME, submitTime);
log.Debug("即將要新增的時間:submitTime:" + submitTime + " Guid:" + pageGuid.ToString());
cookie.Values.Add(pageGuid, submitTime);
log.Debug("UpdateRefreshFlag中當前Cookie中存在的記錄數爲:" + cookie.Values.Count);
for (int i = 0; i < cookie.Values.Count; i++)
log.Info("cookie[" + cookie.Values.GetKey(i) + "]:" + cookie.Values[i]);
Response.AppendCookie(cookie);
#endregion
}
/// <summary>
/// 驗證是否刷新
/// </summary>
/// <returns></returns>
private bool CheckRefreshFlag()
{
#region Session模式
//DataTable RefreshSign = GetRefreshSession();
//if (RefreshSign.Rows.Count == 0)//第一次訪問頁面
//{
// log.Debug("第一次訪問頁面");
// return true;
//}
//else
//{
// bool flag = RefreshSign.Rows.IndexOf(RefreshSign.Rows.Find(GetCurSubmitTime())) > -1;//當前提交時間是否存在
// if (flag)
// log.Debug("提交時間存在");
// else
// log.Debug("無效的提交時間");
// return flag;
//}
#endregion
HttpCookie cookie = GetRefreshTicket();
string pageGuid = GetCurPageGuid();
if (cookie.Values.Count > 0)
{
bool flag;
if (cookie.Values[pageGuid] != null)
flag = cookie.Values[pageGuid].IndexOf(GetCurSubmitTime()) > -1;
else
flag = true;//防止出現異常,總是可以提交
if (flag)
log.Debug("提交時間存在,可以提交");
else
log.Debug("無效的提交時間");
return flag;
}
return true;
}
/// <summary>
/// 得到已保存的提交時間,沒有新建,有返回
/// </summary>
/// <returns></returns>
private HttpCookie GetRefreshTicket()
{
#region Session模式,返回值改爲DataTable
//DataTable RefreshSession;
//if (Session[REFRESH_TICKET_NAME] == null)
//{
// RefreshSession = new DataTable("RefreshSession");
// DataColumn newColumn;
// newColumn = new DataColumn("submitTime", System.Type.GetType("System.String"));
// RefreshSession.Columns.Add(newColumn);
// DataColumn[] columnArray = new DataColumn[1];
// columnArray[0] = newColumn;
// RefreshSession.PrimaryKey = columnArray;
// newColumn = new DataColumn("GUID", System.Type.GetType("System.String"));
// RefreshSession.Columns.Add(newColumn);
// Session[REFRESH_TICKET_NAME] = RefreshSession;
// log.Debug("Session不存在,初始化");
//}
//else
//{
// RefreshSession = Session[REFRESH_TICKET_NAME] as DataTable;
// log.Debug("讀取已存在的Session,當前DataTable中存在的記錄數爲:" + RefreshSession.Rows.Count);
// foreach (DataRow row in RefreshSession.Rows)
// {
// log.Info("row['submitTime']:" + row["submitTime"] + " row['GUID']:" + row["GUID"]);
// }
//}
//return RefreshSession;
#endregion
#region Cookie模式,返回值爲Cookie
HttpCookie cookie;
if (Request.Cookies[REFRESH_TICKET_NAME] == null)
{
cookie = new HttpCookie(REFRESH_TICKET_NAME);
Response.AppendCookie(cookie);
log.Debug("Cookie不存在,初始化");
}
else
{
cookie = Request.Cookies[REFRESH_TICKET_NAME];
log.Debug("讀取已存在的Cookie,當前Cookie中存在的記錄數爲:" + cookie.Values.Count + "具體有如下幾條:");
for (int i = 0; i < cookie.Values.Count; i++)
log.Info("cookie[" + cookie.Values.GetKey(i) + "]:" + cookie.Values[i]);
}
return cookie;
#endregion
}
/// <summary>
/// 獲取當前提交時間
/// </summary>
/// <returns></returns>
private string GetCurSubmitTime()
{
string submitTime = Request.Params[HIDDEN_FIELD_NAME] == null ? "" : Request.Params[HIDDEN_FIELD_NAME].ToString();
log.Debug("執行GetCurSubmitTime:submitTime爲:" + submitTime);
return submitTime;
}
/// <summary>
/// 設置頁面唯一標識,通過Guid標識來區分每個頁面自己的提交時間
/// </summary>
private string SetCurPageGuid()
{
string guid;
if (!IsPostBack)
{
if (Request.Params[HIDDEN_PAGE_GUID] == null)
{
guid = System.Guid.NewGuid().ToString();
log.Debug("SetCurPageGuid註冊了一個新的標識:" + guid);
}
else
guid = GetCurPageGuid();
}
else
{
guid = GetCurPageGuid();
}
ClientScript.RegisterHiddenField(HIDDEN_PAGE_GUID, guid);
return guid;
}
/// <summary>
/// 得到當前頁面的唯一標識
/// </summary>
/// <returns></returns>
private string GetCurPageGuid()
{
string pageGuid = Request.Params[HIDDEN_PAGE_GUID] == null ? "none" : Request.Params[HIDDEN_PAGE_GUID].ToString();
log.Debug("執行GetCurPageGuid()後Page_GUID爲:" + pageGuid);
return pageGuid;
}
需要刷新判斷功能時新頁面只需繼續該類就可,通過引用屬性IsPageRefreshed識別"爲真表示刷新,假則是正常提交",將數據庫的操作寫在
if(!IsPageRefreshed)
{
數據庫操作
}
即可,如果是刷新不會執行,代碼中註釋部分使用的是Session方式保存票證,因爲session比較容易丟失且佔內存,所以使用cookie,
有什麼好建議請大家提議. 轉載請註明出自http://www.cnblogs.com/xiaobier,謝謝.