Recaptcha disappears during PostBack

2019-04-23 15:28发布

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.

7条回答
手持菜刀,她持情操
2楼-- · 2019-04-23 15:39

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
查看更多
仙女界的扛把子
3楼-- · 2019-04-23 15:41

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...  
查看更多
▲ chillily
4楼-- · 2019-04-23 15:44

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

查看更多
疯言疯语
5楼-- · 2019-04-23 15:48

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.

查看更多
手持菜刀,她持情操
6楼-- · 2019-04-23 15:59

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);
    }
}
查看更多
爱情/是我丢掉的垃圾
7楼-- · 2019-04-23 16:02

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);
}
查看更多
登录 后发表回答