Page.IsValid is always returning true

May 1, 2012 at 5:58 PM

Hi,

 I tried the first option (added captcha in a custom page). Page.IsValid is always returning true even i missed to fill the captcha text. Any clues?

Sep 11, 2012 at 9:40 AM

I know this is a late reply, but for anyone else that runs into this, I was able to duplicate this behavior as well and I found it was tied to the the option "TriggerControlId" of the reCaptcha user control.  When a submit is fired, a routine called TriggerControlCausedPostback() is fired which checks to see if the control the caused the post back event matched the one specified in the 'TriggerControlId' parameter. 

Unfortunately, the function does not account for the content placeholder prefixes that are added to the ids when the page is rendered, so the ID test always fails (see below).

//Internal Validation process

protected void reCAPTCHAValidate(object sender, ServerValidateEventArgs args)
        {
            if (TriggerControlCausedPostback())
            {
                args.IsValid = IsValid(_privateKey);
                return;
            }

            args.IsValid = true;    <-------Validation ALWAYS passes!!
        }

// Here' why

 internal bool TriggerControlCausedPostback()
        {
            string ctlId = Request.Params.Get("__EVENTTARGET");
            if (!string.IsNullOrEmpty(ctlId))
            {
                if (ctlId == _triggerControlId)  <--- if you set 'submitbutton' as the Trigger, it will fail because it could return 'ctrl00$PlaceHolderMain$submitbutton' at runtime
                    return true;
            }
            else
            {
                Control ctl = GetControl(Page.Controls, _triggerControlId);
                if (ctl != null && ctl is System.Web.UI.WebControls.Button)     <----- If this fails you get false
                    return true;
            }

            return false;
        }

/----------------------- end of analysis -------

I think it may be worth revisiting this later to see if it can be made a little more robust, but for now an easy work-a-round is to just identify what the run time ID will be when you are putting together the app page and put it into the 'TriggerControlId' parameter.

 <spable:reCAPTCHA runat="server" ID="reCaptchaContact"
                    PublicKey="<------------Your Public Key-------------------------->"
                    PrivateKey="<-----------Your Private Key------------------------->"
                    Theme="white"  TriggerControlId="ctl00$PlaceHolderMain$lbSubmitbtn" />

 

I not saying it's the best approach, but it works!

Nov 13, 2012 at 7:46 AM

Iv taken a slightly different approach and changed the recaptcha code where implemented to the following


            if (!string.IsNullOrEmpty(ctlId) && !string.IsNullOrEmpty(_triggerControlId))
            {
                if (ctlId.EndsWith(_triggerControlId))
                    return true;
            }

So it only uses this if statement if the triger control is not empty on the init, and then compares with a partial string.

Jun 5, 2013 at 3:45 PM
First of all many thanks to the one that coded this solution.

This is a late reply to the thread, but I think it might help to others.

I have implemented the user control in a webpart and found the same problem with the Page.IsValid returning always true. The issue I found in my implementation was that I was using an ImageButton instead of a regular Button, and the one commented by psiEnergos (the id name might change).

My solution was:

internal bool TriggerControlCausedPostback()
    {
        string ctlId = Request.Params.Get("__EVENTTARGET");
        if (!string.IsNullOrEmpty(ctlId))
        {
            if (ctlId == _triggerControlId)
                return true;
        }
        else
        {
            Control ctl = GetControl(Page.Controls, _triggerControlId);
                if (ctl != null && (ctl is System.Web.UI.WebControls.Button || ctl is System.Web.UI.WebControls.ImageButton)) <---------
                return true;              
        }

        return false;
    }
And

internal Control GetControl(ControlCollection controls, string id)
    {
        foreach (Control control in controls)
        {
            if (control.ID!=null && control.ID.Contains(id))      <----
                return control;

            Control foundControl = GetControl(control.Controls, id);
            if (foundControl != null)
                return foundControl;
        }

        return null;
    }
It compiled and worked perfect. I hope it helps to others.
Oct 16, 2013 at 1:44 PM
Hi,

I'm trying to modify and compile the solution but I get the following error:

"Cannot import the following key file: sharepointable.pfx. The key file may be password protected. To correct this, try to import the certificate again or manually install the certificate to the Strong Name CSP with the following key container name: VS_KEY_1E2473E48542B515"

Thank you,
Octavian