Recaptcha disappears during PostBack

2019-04-23 15:33发布

问题:

I have seen a couple of other posts on here regarding the use of Recaptcha with ASP.net UpdatePanels but have not yet found an answer that solves my problem.

Here is my ASPX code :

<asp:UpdatePanel ID="updRecaptcha" runat="server" UpdateMode="Always">
 <ContentTemplate>
  <recaptcha:RecaptchaControl ID="btnrecaptcha" runat="server" Theme="clean" PrivateKey"<%$ Resources: General, CaptchaPrivateKey %>" PublicKey="<%$ Resources: General, CaptchaPublicKey %>" />        
  <asp:Label ID="recaptchaerror" runat="server" style="color: Red;"/>
 </ContentTemplate>
</asp:UpdatePanel>

So the Recaptcha control lives within a user control that uses several .Net validation controls (e.g. RequiredFieldValidator). I need to valdiate the Recaptcha and the ASP.net controls before allowing the process to continue.

If any of the validation fails (Recaptcha or .Net) then the Recaptcha control disappears. Looking at the HTML source, the control isn't loading at all after the Postback - eventhough I am telling the UpdatePanel to update.

I can't reload the page completely as this all appears as an overlay on top of the page and there are other form fields on the page behind.

Please help!

Edit:

From C# when the Recaptcha fails I am calling this code :

ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "InvalidRecaptcha", "alert('Recaptcha Failed');Recaptcha.reload();alert('Recaptcha Reloaded');", true);

Both of the alert statements fire but the Recaptcha still does not load.

回答1:

Forget the ScriptManager. All you need is this script in the page. Change accordingly for your identifiers:

<script type="text/javascript">
// RECAPTURE CODE FOR RELOADING AFTER INCORRECT ENTRY
if (typeof Sys != 'undefined') {
    var requestManager = Sys.WebForms.PageRequestManager.getInstance();
    requestManager.add_endRequest(function(sender, args) {

        $('<div id="recaptcha_widget_div"/>').appendTo('#recaptcha_widget_div2');

        if (typeof Recaptcha != 'undefined') {                                
            Recaptcha.create(recaptcha_key, "recaptcha_widget_div",
            {
                theme: "red",
                callback: Recaptcha.focus_response_field
            });
        }
    });
}



回答2:

The accepted solution did not work for me. Here is the answer that I have tried and is working:

ASP.Net, disappearing Recaptcha, UpdatePanels and Partial PostBacks: Fixed once and for all

Basically it involves creating a hidden div and using jquery to re-render the html. Also the blog post gives a nice little breakdown of the typical solutions (e.g., using RegisterClientScriptBlock with a simple reload) and why they fail.

<div runat="server" id="pbTarget" visible="false"></div>  
<recaptcha:RecaptchaControl ID="recaptcha" runat="server" Theme="clean" />  

code behind:

protected void btnSubmit_Click(object sender, EventArgs e)  
{  
  recaptcha.Validate();  
  if (!Page.IsValid || !recaptcha.IsValid)  
  {  
    pbTarget.Visible = true;  
    ScriptManager.RegisterClientScriptBlock(  
      recaptcha,  
      recaptcha.GetType(),  
      "recaptcha",  
      "Recaptcha._init_options(RecaptchaOptions);"  
      + "if ( RecaptchaOptions && \"custom\" == RecaptchaOptions.theme )"  
      + "{"  
      + "  if ( RecaptchaOptions.custom_theme_widget )"  
      + "  {"  
      + "    Recaptcha.widget = Recaptcha.$(RecaptchaOptions.custom_theme_widget);"  
      + "    Recaptcha.challenge_callback();"  
      + "  }"  
      + "} else {"  
      + "  if ( Recaptcha.widget == null || !document.getElementById(\"recaptcha_widget_div\") )"  
      + "  {"  
      + "    jQuery(\"#" + pbTarget.ClientID + "\").html('<div id=\"recaptcha_widget_div\" style=\"display:none\"></div>');"  
      + "    Recaptcha.widget = Recaptcha.$(\"recaptcha_widget_div\");"  
      + "  }"  
      + "  Recaptcha.reload();"  
      + "  Recaptcha.challenge_callback();"  
      + "}",  
      true  
    );  

    return;  
  }  
  else  
  {  
    //normal page processing here...  


回答3:

If you are using Recaptcha 2.0 this is your Javascript

 <script type="text/javascript">
    function CaptchaReload() {
          Recaptcha.create("yourpublicKey", 'yourRecaptchadiv', {
          theme: 'white',
          callback: grecaptcha.reset()

        });
      }

This is your recaptcha Div

<div class="g-recaptcha" data-sitekey="yourPublicKey"></div>

Then at end of postback event call the Javascript

 protected void txtEmail_TextChanged(object sender, EventArgs e)
{
    if (txtEmail.Text != string.Empty)
    {
        ValidateEmail();
        ScriptManager.RegisterStartupScript(this, this.GetType(), "CaptchaReload", "$.getScript(\"https://www.google.com/recaptcha/api.js\", function () {});", true);
    }
}


回答4:

Surprisingly, I didn't need to apply the RegisterClientScriptBlock call to make it work. I just use:

UpdateMode="Always"

for the updatepanel and on the server side I call:

updatePanel.Update();

This also prevents the captcha from displaying a new challenge.



回答5:

My answer is basically the same as "User" (that worked !), but to help anyone using VB. I would have commented there, but I have zippo rep... (hope this isn't too much of an infraction, and that it helps someone out)

I ported the meat of this to VB.NET:

pbTarget.Visible = True
        Dim _sb As New StringBuilder
        With _sb
            .Append("Recaptcha._init_options(RecaptchaOptions);")
            .Append("if ( RecaptchaOptions && ""custom"" == RecaptchaOptions.theme )")
            .Append("{")
            .Append("  if ( RecaptchaOptions.custom_theme_widget )")
            .Append("  {")
            .Append("    Recaptcha.widget = Recaptcha.$(RecaptchaOptions.custom_theme_widget);")
            .Append("    Recaptcha.challenge_callback();")
            .Append("  }")
            .Append("} else {")
            .Append("  if ( Recaptcha.widget == null || !document.getElementById(""recaptcha_widget_div"") )")
            .Append("  {")
            .Append("    jQuery(""#")
            .Append(pbTarget.ClientID)
            .Append(""").html('<div id=""recaptcha_widget_div"" style=""display:none""></div>');")
            .Append("    Recaptcha.widget = Recaptcha.$(""recaptcha_widget_div"");")
            .Append("  }")
            .Append("  Recaptcha.reload();")
            .Append("  Recaptcha.challenge_callback();")
            .Append("}")
        End With
        ScriptManager.RegisterClientScriptBlock(recaptcha, recaptcha.[GetType](), "recaptcha", _sb.ToString, True)


回答6:

I was able to make it work using version 2.1.0.0 of the reCAPTCHA library for .NET with webforms, script manager and inside an update panel.

First, in the .aspx page outside of the update panel I'm loading the Google reCAPTCHA library:

<script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit" 
            async defer></script>

Second, in the .aspx page inside the update panel I added a div that will work as the target panel to load the reCAPTCHA:

<div runat="server" id="pbTarget" visible="false"></div>
<cc1:Recaptcha ID="recaptcha" runat="server" Theme="Clean" />

Third, in the code behind at the end of my postback event I registered a startup script to render the reCAPTCHA in my target panel

Private Sub cmdSubmit_Click(sender As Object, e As EventArgs) Handles cmdSubmit.Click
    pbTarget.Visible = True
    ScriptManager.RegisterStartupScript(
        UpdatePanel1,
        UpdatePanel1.GetType(),
        "loadCaptcha",
        "grecaptcha.render('" & pbTarget.ClientID & "', {'sitekey': 'YourKey' });",
End Sub


回答7:

You need to reload reCaptcha control with javascript, try this:

protected void Button1_Click(object sender, EventArgs e)
{
     btnrecaptcha.Validate();
     if(IsValid && updRecaptcha.IsValid}
     {
          //Some logic here
     }
     ScriptManager.RegisterClientScriptBlock(Page, Page.GetType(), "CaptchaReload", "Recaptcha.reload();", true);
}