あなたはできる:
- DIV で画面をロックします。
- クリック後にボタンを無効にします。
- 「シンクロナイザー トークン」パターンを使用します。
オプション 1 と 2 は、1 回 (または複数回) のページのリロード (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