2009-09-30 10 views
23

ayant un léger problème avec une page ASP.net de la mienne. Si un utilisateur double-clique sur un bouton "Soumettre", il écrira deux fois dans la base de données (c'est-à-dire exécute deux fois la méthode 'onclick' sur le bouton image)ASP.Net double-cliquez sur le problème

Comment puis-je faire en sorte que si un utilisateur clique sur le bouton image, juste le bouton image est désactivé?

J'ai essayé:

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

Mais cette propriété OnClientClick arrête complètement la page d'être soumis! De l'aide?

Désolé, oui, j'ai des contrôles de validation ... d'où le problème icky.


Travailler sur ce encore, jusqu'à ce point maintenant:

code 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';" /> 

code 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 fait ... cela fonctionne presque. Le problème du double clic est à peu près corrigé (yay!) L'image n'est quand même pas cachée.

Répondre

21

L'approche générale est double.

Serverside:

  1. Sur la charge de la page, générer un jeton (en utilisant System.Random), l'enregistrer dans la session, et les écrire sur un champ de formulaire caché
  2. Sur soumettre, vérifiez que le champ caché est égal à la variable de session (avant mise à nouveau)
  3. Travaillez

Clientside:

Similaire à ce que vous avez, mais probablement de simplement masquer le bouton, et le remplacer par du texte comme «soumission». Le point important à noter, côté client, est que l'utilisateur peut annuler le post en tapant 'escape', donc vous devriez considérer ce qu'il faut faire ici (en fonction de la longueur du jeton ne sera pas utilisé) , vous devrez donc désactiver le bouton pour le désactiver).

Exemple complet suit:

C# (inclut le code pour le voir en action):

<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

Il n'y a aucun moyen simple et intégré de gérer ce problème dans ASP.Net? – MusiGenesis

+0

MusiGenesis: Tout ce que je sais est que j'ai maintenant 7777 rep et je ne veux jamais un peu plus (http://www.ffonline.com/media/guides/ff7/ffvii_faq_lucky7.txt) (Et non). –

3

J'ai résolu ce problème en établissant un champ caché sur le clic client avant de frapper le serveur.

Puis dans le serveur je vérifie le champ caché et si la valeur est par exemple quelque chose 'FAUX' qui pourrait signifier que je peux ou ne peux pas de l'action.

6

Si vous avez une validation sur la page, la désactivation du côté client du bouton devient un peu difficile. Si la validation échoue, vous ne voulez pas désactiver le bouton. Voici un extrait qui ajoute le gestionnaire d'événements côté client:

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

} 

Voir cette asp.net thread pour plus d'informations.

Mise à jour: le code ci-dessus serait utilisé pour ajouter le gestionnaire OnClientClick dans le code derrière. Vous pouvez aussi écrire le javascript dans votre balisage ASPX comme ceci:

<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

Cela ressemble à ce que je suis après, mais je ne sais pas trop comment travailler avec ça ... quelles variables devrais-je changer pour le mien? J'ai regardé le post du forum et ça semble être juste, mais je ne peux pas vraiment y arriver. –

+0

J'ai mis à jour ma réponse avec un exemple. J'espère que cela t'aides! – jrummell

+0

Encore une fois, ne fonctionne pas ... quand j'essaie d'utiliser cela, il désactive tout encore. –

0

similaires à la réponse du côté client de Silky, je fais généralement deux boutons qui se ressemblent, sauf que le deuxième bouton est désactivé et caché. OnClientClick du bouton normal permute les styles d'affichage des deux boutons de sorte que le bouton normal soit masqué et le bouton désactivé affiché.

0

La fonctionnalité de double-clic est une implémentation côté serveur qui empêche le traitement de la même requête qui peut être implémentée côté client via JavaScript. L'objectif principal de la fonctionnalité est d'empêcher le traitement de la même demande deux fois. L'implémentation côté serveur le fait en identifiant la demande répétée; Cependant, la solution idéale est d'éviter que cela se produise du côté du client.

Dans le contenu HTML envoyé au client qui lui permet de soumettre des demandes, un petit JavaScript de validation peut être utilisé pour vérifier si la demande a déjà été soumise et si oui, empêcher l'acheteur en ligne de soumettre à nouveau la demande. Cette fonction de validation JavaScript vérifiera le drapeau global pour voir si la demande a été soumise et, si oui, ne renvoie pas la demande. Si la fonctionnalité de double-clic est désactivée sur le serveur, il est fortement recommandé que les pages JSP et HTML implémentent cette prévention JavaScript.

L'exemple suivant empêche la forme d'être soumis plus d'une fois en utilisant l'action onSubmit() de l'objet de formulaire:

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

Le code onsubmit devrait ressembler à ceci: onsubmit = "return submitRequest()". –

0

pour ceux qui veulent juste faire une solution rapide, juste le cacher et affiche un autre bouton qui n'a aucun événement

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