你可以:
- 使用 DIV 锁定屏幕;
- 点击后禁用按钮;
- 使用“同步器令牌”模式;
选项 1 和 2 容易受到一个(或多个)页面重新加载 (F5) 的影响。选项 3 更稳健,理论上是万无一失的。
很快我将发布 1 和 3 的示例代码。
编辑:
“同步器令牌”的助手类
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;
namespace TestDivLockScreen
{
/// <summary>
/// Helper to "Synchronizer Token Pattern".
/// </summary>
public class SynchronizerToken
{
private static readonly string SESSION_KEY_TOKEN = "TestDivLockScreen.SynchronizedToken.SESSION_KEY_TOKEN";
/// <summary>
/// Returns a new token and positions it for validation of next request.
/// </summary>
/// <returns></returns>
public static string NewToken()
{
string token = Guid.NewGuid().ToString("N");
HttpContext.Current.Session.Add(SESSION_KEY_TOKEN, token);
return token;
}
/// <summary>
/// Returns the value of the current token. Renew if the current token is null.
/// </summary>
/// <returns></returns>
public static string CurrentToken()
{
string token = HttpContext.Current.Session[SESSION_KEY_TOKEN] as string;
if (string.IsNullOrEmpty(token))
{
token = NewToken();
}
return token;
}
/// <summary>
/// Checks if the token matches the token of last call to NewToken.
/// The removal of the token is only made after a new call NewToken.
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public static bool IsCurrentToken(string token)
{
string currentToken = HttpContext.Current.Session[SESSION_KEY_TOKEN] as string;
if (currentToken == null)
{
return false;
}
else
{
if (currentToken.Equals(token))
{
return true;
}
else
{
return false;
}
}
}
/// <summary>
/// Do the same as IsCurrentToken. However loads a new "token value"
/// in the session. Is "Thread Safe"!
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public static bool IsCurrentTokenRenew(string token)
{
lock (HttpContext.Current.Session)
{
string currentToken = CurrentToken();
NewToken();
if (currentToken.Equals(token))
{
return true;
}
else
{
return false;
}
}
}
}
}
在页面上定义一个隐藏字段:
<asp:HiddenField ID="HdfSyncToken" runat="server" />
关于后面的代码:
protected void Pre_Render(object sender, EventArgs e)
{
//repositioning token
this.HdfSyncToken.Value = SynchronizerToken.CurrentToken();
//Refresh GridView
this.GrvRecords.DataSource = this.Records;
this.GrvRecords.DataBind();
}
protected void BtnInsertST_Click(object sender, EventArgs e)
{
//Abort second execution for the same value of the token
if (!SynchronizerToken.IsCurrentTokenRenew(this.HdfSyncToken.Value))
{
ClientScript.RegisterStartupScript(this.GetType(), "alert", "<script type='text/javascript'>alert('Request has already been answered!');</script>");
}
//Insert Record (token validation OK)
else
{
this.InsertRecord();
}
}
完整源码(VS2005):q_11402631.7z