How To Perform Built-In Ajax Validation of BotDetect ASP.NET CAPTCHA (BotDetect v3.0; deprecated)
First Time Here?
Check the BotDetect ASP.NET WebForms Captcha Quickstart for key integration steps.
After protecting your ASP.NET form with BotDetect Captcha validation, you can improve the user experience by allowing asynchronous Captcha validation. That way users get faster feedback when they enter an incorrect Captcha code, without affecting the rest of the page.
To make client-side processing easier, BotDetect exposes a client-side Validate()
function and several client-side events (PreAjaxValidate
, AjaxValidationFailed
, AjaxValidationPassed
, OnAjaxError
) which allow you to set up custom Ajax workflows with the minimum of hassle.
A simple example of BotDetect Ajax validation can be seen in the ASP.NET Built-In Ajax Captcha Validation Code Sample included in BotDetect installations. You can run it while following these instructions and see how each step has been implemented.
Table of Contents
- Ajax Captcha Validation Basics
- Call BotDetect Built-In Ajax Captcha Validation
- Implement the Asynchronous Captcha Validation Workflow
Ajax CAPTCHA Validation Basics
Before proceeding to actual Ajax Captcha validation code, there are several basic concerns to get out of the way.
Ajax CAPTCHA Validation Considerations
- This guide does not apply to ASP.NET Ajax. If you are using ASP.NET Ajax
UpdatePanel
s or similar Ajax wrappers, you most probably don't need to make any changes from the default BotDetect implementation. You can find out more about this use case by looking at the ASP.NET Ajax Captcha Code Sample included in BotDetect installations. - This guide does not apply to pages using the jQuery validate plugin. If you are using jQuery to validate your form fields, you can see how to integrate Captcha validation with it in the ASP.NET jQuery Validation Captcha Code Sample included in BotDetect installations.
- Pure client-side Captcha validation does absolutely nothing to stop bots, as explained in the BotDetect FAQ. Client-side validation does by no means replace server-side validation, but simply augments it. So you should always:
- First implement server-side Captcha validation (which provides security when dealing with bots), and
- Then add client-side Captcha validation on top (which provides usability when dealing with human visitors).
- The purpose of Ajax Captcha validation is to provide faster feedback when users enter an incorrect Captcha code, and it comes at the price of validating the Captcha twice when they enter it correctly. Handling of error cases (like failed Captcha validation) has a big impact on the overall usability of the form (since errors can easily frustrate or discourage users), so it's a good idea to "smooth-out" that part of the user experience.
Ajax CAPTCHA Validation Pre-Requisites
Regardless of the underlying server-side BotDetect Captcha implementation (ASP.NET Forms, ASP.NET MVC Applications, or other), Ajax Captcha validation will always use the BotDetect client-side interface.
We'll assume you have server-side BotDetect Captcha validation in place and working properly (if not, check the BotDetect Developer Crash Course or the appropriate detailed How To guide).
For demonstration purposes, we'll use the following simple Web Form code:<BotDetect:Captcha ID="SampleCaptcha" runat="server" /> <asp:TextBox ID="CaptchaCodeTextBox" runat="server" /> <asp:Button ID="ValidateCaptchaButton" runat="server" /> <asp:Label ID="CaptchaCorrectLabel" runat="server" /> <asp:Label ID="CaptchaIncorrectLabel" runat="server" />
The
For example, you can set it on eachUserInputClientID
property of the Captcha control must be set to the client-side identifier of the Captcha code input textbox. Details can be found in the BotDetect API reference.Page_PreRender
call in page code-behind:SampleCaptcha.UserInputClientID = CaptchaCodeTextBox.ClientID;
You need to be able to reference the
For example, in code-behind you could access it as:CaptchaId
property of the Captcha control on client-side, since BotDetect will automatically create a client-side Captcha object with this variable name.ValidateCaptchaButton.OnClientClick = String.Format("return {0} .Validate();", SampleCaptcha.CaptchaId);
Or you could use it directly in form source:<script type="text/javascript"> function ValidateForm() { return <%= SampleCaptcha.CaptchaId %>.Validate(); }
Another option is to access the client-side Captcha object through the Captcha code textbox. If you can access the textbox DOM element (by Id, class, etc.), BotDetect will automatically add a custom
Captcha
property pointing to the Captcha object.So for example, if you know that the client-side Id of the Captcha input textbox is
CaptchaCodeTextBox
, you could use:document.getElementById("CaptchaCodeTextBox").Captcha.Validate();
Call BotDetect Built-In Ajax CAPTCHA Validation
As shown above, firing Ajax validation of a BotDetect instance is as simple as calling the JavaScript Validate()
function of the client-side BotDetect object created automatically when BotDetect Captcha is added to the page.
Start Ajax CAPTCHA Validation From Client-Side Code
Captcha validation on the client-side can be started when the user finishes typing the Captcha code - depending on how your form handles client-side validation of other form fields, this could be either:
- the
onblur
handler of the Captcha code textbox:CaptchaCodeTextBox.Attributes["onblur"] = String.Format("{0}.Validate();", SampleCaptcha.CaptchaId);
- the
onclick
handler of the form submission button:ValidateCaptchaButton.OnClientClick = String.Format("return {0}.Validate();", SampleCaptcha.CaptchaId);
- the
onsubmit
handler of the form:form1.Attributes["onsubmit"] = String.Format("return {0}.Validate();", SampleCaptcha.CaptchaId);
- any other client-side event that fits your client-side form validation approach and Ajax framework of your choice.
In the first case, Captcha validation is a standalone action that just has to be called, while in the latter two it can be integrated with other form field validation.
For example, if the form asks the user to enter his username, password, and the Captcha code, the onclick
or onsubmit
handler would call a JavaScript validation function (e.g. ValidateForm()
), which performs basic validation of all three fields – calling the Validate()
function as the third validation step.
Use the Ajax CAPTCHA Validation Return Value
The client-side Validate()
function returns the Captcha validation result as a boolean value, but it's important to note that it's an Ajax call - i.e. performed asynchronously. The validation result can also be accessed as the ValidationResult
property of the client-side object. The basic asynchronous workflow is as follows:
- The
Validate()
function is called, it fires thePreAjaxValidate
client-side event, sends the Ajax Captcha validation Http request to the server, and immediately returnsfalse
. This return value can be used to prevent the whole form from being submitted to the server until the Ajax call returns. - When the Captcha validation response arrives from the server, the
ValidationResult
value is updated and eitherAjaxValidationFailed
orAjaxValidationPassed
is called automatically. - If the correct Captcha code was submitted for validation, the
Validate()
function will returntrue
when called again, allowing the form to be submitted to the server.
Implement the Asynchronous CAPTCHA Validation Workflow
Since Ajax Captcha validation is executed asynchronously, it can be examined as a series of discrete events. BotDetect exposes a simple interface that allows you to write JavaScript code called at each phase of this asynchronous workflow.
Your form (or a JavaScript include loaded with the form) needs to define four JavaScript functions, and tell BotDetect to use them during Ajax calls:
<script type="text/javascript"> function OnCaptchaValidate() { // TODO ... } function OnCaptchaIncorrect() { // TODO ... } function OnCaptchaCorrect() { // TODO ... } function OnAjaxError() { // TODO ... } BotDetect.RegisterCustomHandler('PreAjaxValidate', OnCaptchaValidate); BotDetect.RegisterCustomHandler('AjaxValidationFailed', OnCaptchaIncorrect); BotDetect.RegisterCustomHandler('AjaxValidationPassed', OnCaptchaCorrect); BotDetect.RegisterCustomHandler('AjaxValidationError', OnAjaxError); </script>
Since the BotDetect JavaScript include is added to the page as a part of the Captcha Html markup, these definitions need to be below it in form source, since BotDetect.RegisterCustomHandler()
won't be defined before it.
PreAjaxValidate Client-Side Event
PreAjaxValidate
happens on the client just before the Captcha validation Http request is sent to the server. Please note that this event won't happen if the Captcha input is empty – since in that case there is no need to send anything to the server to know Captcha validation failed, we skip directly to AjaxValidationFailed
.
Typical action performed in this phase are: resetting the Captcha validation status (hiding any previously displayed Captcha validation results and messages), showing the user that asynchronous Captcha validation is currently in progress, and temporarily disabling Captcha validation while the current attempt is in progress.
In the example we use the submit button to start Captcha validation and display the current status, and disable the button during validation to prevent multiple unnecessary clicks:
function OnCaptchaValidate() { // update display and disable the button document.getElementById('CaptchaCorrectLabel').style.display = 'none'; document.getElementById('CaptchaIncorrectLabel').style.display = 'none'; document.getElementById('ValidateCaptchaButton').disabled = true; document.getElementById('ValidateCaptchaButton').value = 'Validating...'; }
AjaxValidationFailed Client-Side Event
AjaxValidationFailed
is called on the client every time Ajax Captcha validation fails (returns false
) – when the user-input Captcha code is either empty or doesn't match the value stored on the server.
This event automatically reloads (changes) the Captcha image, since each failed Captcha validation attempt invalidates the Captcha code used.
Typical actions performed in this phase are: displaying an error message instructing the user to re-try the Captcha challenge, and re-enabling Captcha validation.
This is the case in which Ajax Captcha validation pays off, since the user gets feedback about the Captcha code mismatch faster than when submitting the whole form, and state of other form fields is left unchanged.
In the example, we display a warning and re-enable the submit button:
function OnCaptchaIncorrect() { // update display and enable the button for re-tries document.getElementById('CaptchaCorrectLabel').style.display = 'none'; document.getElementById('CaptchaIncorrectLabel').innerHTML = 'Incorrect! (client)'; document.getElementById('CaptchaIncorrectLabel').style.display = 'inline'; document.getElementById('ValidateCaptchaButton').disabled = false; document.getElementById('ValidateCaptchaButton').value = 'Validate'; }
AjaxValidationPassed Client-Side Event
AjaxValidationPassed
is called on the client every time Ajax Captcha validation succeeds (returns true
) – when the user-input Captcha code matches the value stored on the server.
Typical actions performed in this phase are: displaying a success indicator, and submitting the full form to the server for server-side validation.
Since the user already finished his Captcha input, we should automatically proceed to full-form submission to the server (unless validation of other form fields failed).
Automatically re-submitting the form can call the Validate()
function again, which will immediately return true
in this case – since we have the Captcha validation result on the client now, the function knows it doesn't need to make further Ajax calls.
In this scenario Captcha validation (server-side comparison with the stored Captcha code) will be called twice (once by Ajax from the client, and once by server-side form processing code). BotDetect will automatically recognize this case and allow the same Captcha code to pass validation twice (unlike attempts to validate the same Captcha code twice from server-side code).
The example updates the status messages and goes on to re-submit the form automatically. Submission will repeat the Validate()
function call, and since ValidationResult
is now set to true
, Validate()
will return true
as well and allow the form to be submitted to the server.
function OnCaptchaCorrect() { // update display document.getElementById('CaptchaCorrectLabel').innerHTML = 'Correct! (client)'; document.getElementById('CaptchaCorrectLabel').style.display = 'inline'; document.getElementById('CaptchaIncorrectLabel').style.display = 'none'; // automatically proceed to server-side validation document.getElementById('ValidateCaptchaButton').disabled = false; document.getElementById('ValidateCaptchaButton').focus(); document.getElementById('ValidateCaptchaButton').click(); }
AjaxValidationError Client-Side Event
AjaxValidationError
is called when the Ajax Captcha validation Http request returns an error response code (different than a 200 OK
response containing false
as the validation result!) or times out.
Ajax applications should always implement a fallback in case the Ajax request fails, otherwise they won't be robust enough for production deployments and will frustrate users instead of improving their experience.
Since Ajax validation is not possible, this event automatically sets the Ajax validation result to true
, simply to allow the form to proceed to server-side processing. If the Captcha code doesn't match, server-side validation will prevent the protected action. If this sounds counter-intuitive, just remember that Ajax validation is merely a user interface improvement that provides no security. Since the fast error feedback provided by Ajax validation is not possible in this case, we seamlessly downgrade the user experience to more robust full postbacks and ensure the form behaves properly in all cases.
The example code simply falls back to full form postback:
function OnAjaxError() { // fall back to server-side validation document.getElementById('ValidateCaptchaButton').disabled = false; document.getElementById('ValidateCaptchaButton').focus(); document.getElementById('ValidateCaptchaButton').click(); }
Please Note
The information on this page is out of date and applies to a deprecated version of BotDetect™ CAPTCHA (v3.0).
An up-to-date equivalent page for the latest BotDetect Captcha release (v4) is BotDetect v4 Captcha documentation index.
General information about the major improvements in the current BotDetect release can be found at the What's New in BotDetect v4.0 page.
Current BotDetect Versions
-
BotDetect ASP.NET CAPTCHA
2019-07-22v4.4.2 -
BotDetect Java CAPTCHA
2019-07-22v4.0.Beta3.7 -
BotDetect PHP CAPTCHA
2019-07-22v4.2.5