23

我的 ASP.net 页面有一点问题。如果用户双击“提交”按钮,它将两次写入数据库(即对图像按钮执行两次“onclick”方法)

我怎样才能做到这一点,如果用户点击图像按钮,只有图像按钮被禁用?

我试过了:

<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;

实际上......这几乎可以工作。双击问题几乎是固定的(耶!)虽然图像仍然没有隐藏。

4

6 回答 6

21

一般的方法是双重的。

服务器端

  1. 在页面加载时,生成一个令牌(使用System.Random),将其保存在会话中,并将其写入隐藏的表单字段
  2. 提交时,检查隐藏的表单字段是否等于会话变量(再次设置之前
  3. 做工作

客户端

与您所拥有的类似,但可能只是隐藏按钮,并将其替换为“提交”之类的文本。

客户端需要注意的重要一点是,用户可以通过点击“escape”来取消帖子,所以你应该考虑在这里做什么(取决于它们有多远,令牌不会被使用,所以你'需要将按钮从禁用/隐藏状态恢复)。

完整示例如下:

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>
于 2009-09-30T13:57:37.977 回答
6

如果您在页面上有验证,禁用按钮客户端会有点棘手。如果验证失败,您不想禁用该按钮。这是添加客户端事件处理程序的片段:

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 线程

更新:上面的代码将用于在后面的代码中添加 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);" />
于 2009-09-30T14:11:04.453 回答
3

我已经通过在点击服务器之前在客户端点击上设置一个隐藏字段来解决这个问题。

然后在服务器中检查隐藏字段,如果该值是例如“FALSE”,这可能意味着我可以或不能执行该操作。

于 2009-09-30T13:58:44.037 回答
0

与 Silky 的客户端响应类似,我通常会制作两个看起来相似的按钮,只是第二个按钮被禁用和隐藏。普通按钮的 OnClientClick 交换两个按钮的显示样式,使普通按钮隐藏,显示禁用按钮。

于 2009-09-30T14:31:40.107 回答
0

双击功能是一种服务器端实现,用于防止处理相同的请求,可以通过 JavaScript 在客户端实现。该功能的主要目的是防止两次处理相同的请求。服务器端实现通过识别重复的请求来做到这一点;但是,理想的解决方案是防止这种情况发生在客户端。

在发送到允许他们提交请求的客户端的 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> 
于 2009-10-01T09:15:28.840 回答
0

对于那些只想快速修复的人,只需隐藏它并显示另一个没有事件的按钮

<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>
于 2016-06-20T17:20:26.910 回答