2009-09-30 20 views
23

teniendo un pequeño problema con una página de ASP.net. Si un usuario hiciera doble clic en un botón "enviar", escribirá en la base de datos dos veces (es decir, realizará el método 'onclick' en el botón imagen dos veces)ASP.Net haga doble clic en el problema

¿Cómo puedo hacer para que si un usuario hace clic en el botón imagen, solo el botón imagen está deshabilitado?

que he probado:

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

Pero esta propiedad OnClientClick se detiene por completo la página se presenten! ¿Alguna ayuda?

Lo sentimos, sí, tengo controles de validación ... de ahí el problema icky.


Trabajando en esto todavía, hasta este punto ahora:

código

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

En realidad ... esta casi funciona. El problema del doble clic es bastante fijo (¡yay!). Sin embargo, la imagen aún no está oculta.

Respuesta

21

El enfoque general es doble.

Serverside:

  1. En la carga de la página, generar un token (usando System.Random), guardarlo en la sesión, y grabarla en un campo de formulario oculto
  2. en enviar, verificar que el campo de formulario oculto es igual a la variable de sesión ( antes de colocarla de nuevo)
  3. hacer el trabajo

ClientSide:

Similar a lo que tiene, pero probablemente sólo ocultar el botón, y sustituirlo por un texto como 'sometimiento'.

Lo importante a tener en cuenta, del lado del cliente, es que el usuario puede cancelar la publicación presionando 'escape', por lo que debe considerar qué hacer aquí (dependiendo de qué tan avanzado esté el token no se usará) , por lo que tendrá que volver a desactivar el botón/ocultarlo.

Ejemplo completo sigue:

C# (incluye código para verlo en acción):

<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> 
+0

+1. nice ....... –

+2

¿No hay una forma simple e integrada de manejar este problema en ASP.Net? – MusiGenesis

+0

MusiGenesis: Todo lo que sé es que ahora tengo 7777 rep y nunca quiero un solo bit más (http://www.ffonline.com/media/guides/ff7/ffvii_faq_lucky7.txt) (Y no). –

3

He resuelto esto estableciendo un campo oculto en el cliente haga clic antes de llegar al servidor.

Luego en el servidor verifico el campo oculto y si el valor es, por ejemplo, algo 'FALSO' que podría significar que puedo o no puedo de la acción.

6

Si tiene validación en la página, deshabilitar el botón del lado del cliente se vuelve un poco complicado. Si la validación falla, no desea deshabilitar el botón. He aquí un fragmento que se suma el controlador de eventos del lado del cliente:

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

} 

ver este asp.net thread para obtener más información.

Actualización: el código anterior se usará para agregar el controlador OnClientClick en el código de atrás. También podría escribir el código JavaScript en su margen de beneficio aspx, así:

<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);" /> 
+0

Esto parece lo que busco, pero no estoy muy seguro de cómo trabajar con esto ... ¿qué variables tendría que cambiar para las mías? Miré la publicación del foro y parece estar bien, pero no puedo entenderlo. –

+0

Actualicé mi respuesta con un ejemplo. ¡Espero que esto ayude! – jrummell

+0

Una vez más, no funciona ... cuando trato de usar esto, todavía deshabilita todo. –

0

similares a la respuesta del lado del cliente de sedoso, por lo general hacen dos botones que parecen iguales, excepto que el segundo botón se desactiva y oculta. OnClientHaga clic en el botón normal y cambia los estilos de visualización de los dos botones para que el botón normal esté oculto y se muestre el botón desactivado.

0

La característica de doble clic es una implementación del lado del servidor para evitar el procesamiento de la misma solicitud que se puede implementar en el lado del cliente a través de JavaScript. El objetivo principal de la característica es evitar el procesamiento de la misma solicitud dos veces. La implementación del lado del servidor hace esto al identificar la solicitud repetida; sin embargo, la solución ideal es evitar que esto ocurra en el lado del cliente.

En el contenido HTML enviado al cliente que les permite enviar solicitudes, se puede utilizar una pequeña validación de JavaScript para verificar si la solicitud ya se ha enviado y, de ser así, evitar que el comprador vuelva a enviar la solicitud. Esta función de validación de JavaScript verificará el indicador global para ver si la solicitud se ha enviado y, si es así; no vuelve a enviar la solicitud Si la función de doble clic está desactivada en el servidor, se recomienda encarecidamente que las páginas JSP y HTML implementen esta prevención JavaScript.

el siguiente ejemplo se evita que la forma se presenten más de una vez utilizando la acción onSubmit() del objeto formulario:

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

El código de envío debe ser así: onsubmit = "return submitRequest()". –

0

para aquellos que sólo quieren hacer un arreglo rápido, simplemente ocultarlo y mostrar otro botón que no tiene eventos

<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> 
Cuestiones relacionadas