web-dev-qa-db-ja.com

ASP.Netダブルクリックの問題

私のASP.netページにわずかな問題があります。ユーザーが「送信」ボタンをダブルクリックすると、データベースに2回書き込まれます(つまり、imagebuttonで「onclick」メソッドを2回実行します)。

ユーザーが画像ボタンをクリックすると、画像ボタンだけが無効になるようにするにはどうすればよいですか?

私はもう試した:

<asp:ImageButton 
     runat="server" 
     ID="VerifyStepContinue" 
     ImageUrl=image src 
     ToolTip="Go" 
     TabIndex="98" 
     CausesValidation="true" 
     OnClick="methodName" 
     OnClientClick="this.disabled = true;" />

ただし、このOnClientClickプロパティは、ページの送信を完全に停止します。何か助けはありますか?

申し訳ありませんが、はい、私は検証コントロールを持っています...したがって、厄介な問題です。


これにまだ取り組んでいますが、今この時点まで:

ASPコード:

 <asp:TextBox ID="hidToken" runat="server" Visible="False" Enabled="False"></asp:TextBox>
 ...
 <asp:ImageButton runat="server" ID="InputStepContinue" Name="InputStepContinue" ImageUrl="imagesrc" ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="SubmitMethod" OnClientClick="document.getElementById('InputStepContinue').style.visibility='hidden';" />

C#コード:

         private Random
    random = new Random();


    protected void Page_Load(object sender, EventArgs e)
    {
        //Use a Token to make sure it has only been clicked once.
        if (Page.IsPostBack)
        {
            if (double.Parse(hidToken.Text) == ((double)Session["NextToken"]))
            {
                InputMethod();
            }
            else
            {
                // double click
            }
        }

        double next = random.Next();

        hidToken.Text = next + "";
        Session["NextToken"] = next;

実際には...これはほぼ機能します。ダブルクリックの問題はほぼ修正されています(イェーイ!)画像はまだ隠されていません。

23
David Archer

一般的なアプローチは2つあります。

サーバーサイド

  1. ページの読み込み時に、トークンを生成し(System.Randomを使用)、セッションに保存して、非表示のフォームフィールドに書き込みます
  2. 送信時に、非表示のフォームフィールドがセッション変数と等しいことを確認します(before再設定)
  3. 仕事する

クライアントサイド

あなたが持っているものと似ていますが、おそらくボタンを非表示にして、「送信」のようなテキストに置き換えます。

クライアント側で注意すべき重要な点は、ユーザーが「エスケープ」を押すことで投稿をキャンセルできることです。そのため、ここで何をすべきかを検討する必要があります(トークンがどれだけ進んでいるかによって、トークンは使用されないため、ボタンを無効/非表示から戻す必要があります)。

完全な例は次のとおりです。

C#(実際の動作を確認するためのコードが含まれています):

<html>
<head runat="server">
    <title>double-click test</title>
    <script language="c#" runat="server">
    private Random
        random = new Random();

    private static int
        TEST = 0;

    public void Page_Load (object sender, EventArgs ea)
    {
        SetToken();
    }

    private void btnTest_Click (object sender, EventArgs ea)
    {
        if( IsTokenValid() ){
            DoWork();
        } else {
            // double click
            ltlResult.Text = "double click!";
        }
    }

    private bool IsTokenValid ()
    {
        bool result = double.Parse(hidToken.Value) == ((double) Session["NextToken"]);
        SetToken();
        return result;
    }

    private void SetToken ()
    {
        double next = random.Next();

        hidToken.Value       = next + "";
        Session["NextToken"] = next;
    }


    private void DoWork ()
    {
        TEST++;
        ltlResult.Text = "DoWork(): " + TEST + ".";
    }
    </script>
</head>
<body>
    <script language="javascript">
        var last = null;
        function f (obj)
        {
            obj.src = "http://www.gravatar.com/avatar/4659883ec420f39723c3df6ed99971b9?s=32&d=identicon&r=PG";
            // Note: Disabling it here produced strange results. More investigation required.
            last = obj;
            setTimeout("reset()", 1 * 1000);
            return true;
        }

        function reset ()
        {
            last.src = "http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG";
            last.disabled = "false";
        }
    </script>
    <form id="form1" runat="server">
        <asp:HiddenField runat="server" ID="hidToken" />
        <asp:ImageButton runat="server" ID="btnTest"
            OnClientClick="return f(this);"
            ImageUrl="http://www.gravatar.com/avatar/495ce8981a5127a9fd24bd72e7e3664a?s=32&d=identicon&r=PG" OnClick="btnTest_Click" />
        <pre>Result: <asp:Literal runat="server" ID="ltlResult" /></pre>
    </form>
</body>
</html>
21
Noon Silk

ページに検証がある場合、ボタンのクライアント側を無効にするのは少し注意が必要です。検証が失敗した場合、ボタンを無効にしないでください。クライアント側のイベントハンドラーを追加するスニペットは次のとおりです。

private void BuildClickOnceButton(WebControl ctl)

{

System.Text.StringBuilder sbValid = new System.Text.StringBuilder();

sbValid.Append("if (typeof(Page_ClientValidate) == 'function') { ");

sbValid.Append("if (Page_ClientValidate() == false) { return false; }} ");

sbValid.Append(ctl.ClientID + ".value = 'Please wait...';");

sbValid.Append(ctl.ClientID + ".disabled = true;");

// GetPostBackEventReference obtains a reference to a client-side script 
// function that causes the server to post back to the page.

sbValid.Append(ClientScript.GetPostBackEventReference(ctl, ""));

sbValid.Append(";");

ctl.Attributes.Add("onclick", sbValid.ToString());

}

詳細については、これを参照してください asp.netスレッド

Update:上記のコードは、コードビハインドにOnClientClickハンドラーを追加するために使用されます。次のように、aspxマークアップにJavaScriptを記述することもできます。

<script type="text/javascript">
function disableButton(button)
{
    // if there are client validators on the page
    if (typeof(Page_ClientValidate) == 'function') 
    {
        // if validation failed return false
        // this will cancel the click event
        if (Page_ClientValidate() == false) 
        { 
            return false; 
        }
    }

    // change the button text (does not apply to an ImageButton)
    //button.value = "Please wait ...";
    // disable the button
    button.disabled = true;

    // fire postback
    __doPostBack(button.id, '');
}
</script>

<asp:ImageButton runat="server" ID="VerifyStepContinue" ImageUrl="button.png" 
    ToolTip="Go" TabIndex="98" CausesValidation="true" OnClick="methodName" 
    OnClientClick="return disableButton(this);" />
6
jrummell

サーバーにアクセスする前にクライアントクリックに非表示フィールドを設定することで、これを解決しました。

次に、サーバーで非表示フィールドを確認し、値がたとえば「FALSE」の場合、アクションを実行できるかできないかを示します。

3
David Basarab

Silkyのクライアント側の応答と同様に、私は通常、2番目のボタンが無効になって非表示になっていることを除いて、同じように見える2つのボタンを作成します。通常のボタンのOnClientClickは、2つのボタンの表示スタイルを入れ替えて、通常のボタンを非表示にし、無効なボタンを表示します。

0
Matt Hamsmith

簡単な修正を行いたいだけの場合は、それを非表示にして、イベントのない別のボタンを表示します

<asp:Button ID="RedeemSubmitButton" runat="server" Text="Submit to Redeem" OnClick="RedeemSubmitButton_Click" OnClientClick="hideit();" />
<asp:Button ID="RedeemSubmitButtonDisabled" style="display:none;" runat="server" Text="please wait" OnClientClick="javascript:alert('please wait, processing');"  />
<script>
 function hideit() {



        var btn = $get('<%= this.RedeemSubmitButton.ClientID %>');
        var btn2 = $get('<%= this.RedeemSubmitButtonDisabled.ClientID %>');
        if (btn != null)
        {

            btn.style.display = 'none';
            btn2.style.display = 'block'
        }
 }
    </script>

ダブルクリック機能は、JavaScriptを介してクライアント側で実装できる同じ要求の処理を防ぐためのサーバー側の実装です。この機能の主な目的は、同じリクエストが2回処理されないようにすることです。サーバー側の実装は、繰り返される要求を識別することによってこれを行います。ただし、理想的な解決策は、これがクライアント側で発生しないようにすることです。

クライアントにリクエストを送信できるようにするHTMLコンテンツでは、小さな検証JavaScriptを使用して、リクエストがすでに送信されているかどうかを確認し、送信されている場合は、オンラインショッパーがリクエストを再度送信できないようにすることができます。このJavaScript検証関数は、グローバルフラグをチェックして、リクエストが送信されたかどうかを確認します。リクエストを再送信しません。サーバーでダブルクリック機能が無効になっている場合は、JSPページとHTMLページでこのJavaScript防止を実装することを強くお勧めします。

次の例では、フォームオブジェクトのonSubmit()アクションを使用して、フォームが複数回送信されるのを防ぎます。

...
<script>
var requestSubmitted = false;
       function submitRequest() {
              if (!requestSubmitted ) {
                     requestSubmitted  = true;
                     return true;
              }
              return false;
       }
</script>
...

       <FORM method="POST" action="Logon" onSubmit="javascript:submitRequest()">
              ......
       </FORM> 
0
Tarik