views:

314

answers:

3

Hey, I have a master page which contains a Login control so that the user can login/logout from any page. However, a couple of content pages require a Recaptcha control. This causes problems because when I try and log in on a page that has the Recaptcha control, the system expects me to enter the words. I'm aware of the lack of validation groups in the Recaptcha control, and the fact that you can't have multiple forms on an ASP.NET page. Is there a way to work around this? A 'hacky' way I can think of, is in the "Login" event, check the page for a Recaptcha control. If one exists, then disable it, otherwise continue. However, that just seems quite inefficient especially when there are quite a few pages and most won't have a Recaptcha control.

A: 

What you should do is the following:

<form runat="server"></form>

Should be wrapped around your entire page content, in your case on the master page since the login is there as well.

From this point on you can just drop a recaptcha control on any page that derives from the given master page. You do not need another <form runat="server"></form> tag anywhere.

You have to understand that the recaptcha control is neither bound to a html form submit button, nor to any other specific button. Every time the page posts back the recaptcha sets the Page.IsValid flag.

Sadly recaptcha does not follow the ASP.NET standards by using triggered validation combined with validation groups.
So to prevent recaptcha to validate every time, you have to set: SkipRecaptcha = true

This causes recaptcha to not validate. So now the login scenario is covered. When you want actually use the recaptcha functionality you just set SkipRecaptcha = false and call Page.Validate(). Afterwards you can continue as before with Page.IsValid.

A cleaner and better approach would be to rewrite the recaptcha control to make use of the BaseValidator class. This would allow you to specify a validation group on the recaptcha control and the button that submits the inputs you want to protect via recaptcha. The button press will then only cause a validation of the specified validation group.
Additionally you either have to specify a validation group for the login button or set CausesValidation = false. If no validation group is set and the button would be pressed all validation groups are validated automatically.
This is however quite advanced, so that even the recaptcha guys gave it up, there is still an old version in the source control though. There is no guarantee of that version still working. Let us know how you decided.

ntziolis
BaseValidator class is derived from a Label control, which reCAPTCHA is not.
Adrian Godong
I never said that it would, my first approach would have been to create a composite control with all the controls necessary for the recaptcha to work and the simply add an additional control that handles validation and for ease of implementation derives from the BaseValidatior class (and btw. **the old version actually derived from BaseValidator**)
ntziolis
The way reCAPTCHA is rendered does not justify having child controls (it's composed by one <SCRIPT> tag and, optionally, one <NOSCRIPT> tag). Assuming there exist a child validation control that is derived from BaseValidator, this control will not be used at all but for it's ValidationGroup property. I would argue that this would be an overkill for just a feature (which there is a simple workaround). If you have further discussion, you should join the reCAPTCHA group and continue over there.
Adrian Godong
+2  A: 

The workaround for this problem is as follows:

  1. Set ValidationGroup to the Login button. reCAPTCHA control will not validate when a button with ValidationGroup set to non-empty is clicked.
  2. On pages that require reCAPTCHA validation, keep the button's ValidationGroup value to non-empty (otherwise, the login fields will be validated as well), but call RecaptchaControl.Validate() manually on the subroutine.

Discussion thread on the official reCAPTCHA dev mailing list.

Adrian Godong
ntziolis
I stand corrected. The server-side code does not work with the above workaround but the client-side code does. I have committed a fix to the repository to fix this issue.There is also a test page (test/ValidationGroup.aspx) to illustrate the usage.
Adrian Godong
Thats great! I'll try it out very soon, thx for the fix.
ntziolis
A: 

I'm not 100% sure this is related, but I had a problem with the ReCaptcha control firing on every postback - The IsValid property logic was flawed. I fixed this particular issue: http://code.google.com/p/recaptcha/issues/detail?id=56#c3

Unfortunately, the ReCaptcha project has stagnated somewhat, and no fixes have made it into the release for some time.

Milky Joe