ASP.NET CAPTCHA Customization C# Code Sample

The ASP.NET Captcha customization sample project shows how to customize BotDetect CAPTCHA behavior and appearance.

First Time Here?

Check the BotDetect Developer Crash Course for key integration steps.

BotDetect 3.0 allows user-defined customization of many Captcha options through a custom <botDetect> configuration section in the web.config file; some customizations also require code-behind changes.

Shown customizations include: CAPTCHA image color scheme, sound & reload icons and their tooltips, custom client-side handlers for BotDetect actions such as sound playing and Captcha reloading (resulting in simple message boxes on icon clicks in this sample), ...

The web.config file used in this sample project contains detailed descriptions and explanations of the many customizable options.

You can then use chosen customization options to configure BotDetect to precisely match your application requirements.

Download the BotDetect ASP.NET CAPTCHA Component and run this sample

Visual Studio 2012 / .NET 4.5

By default, the .NET 4.5 C# version of the ASP.NET Captcha customization sample project is installed at:
C:\Program Files\Lanapsoft\BotDetect 3 CAPTCHA Component\Asp.Net\v4.5\WebApp\CaptchaCustomizationSample\CSharp

You can also run it from the BotDetect Start Menu:
Programs > Lanapsoft > BotDetect 3 CAPTCHA Component > ASP.NET > DotNET 4.5 Web Applications > Run

The Visual Studio 2012 / .NET 4.5 source has no essential differences from the Visual Studio 2010 / .NET 4.0 source.

Visual Studio 2010 / .NET 4.0

By default, the .NET 4.0 C# version of the ASP.NET Captcha Customization sample project is installed at:
C:\Program Files\Lanapsoft\BotDetect 3 CAPTCHA Component\Asp.Net\v4.0\WebApp\CaptchaCustomizationSample\CSharp

You can also run it from the BotDetect Start Menu:
Programs > Lanapsoft > BotDetect 3 CAPTCHA Component > ASP.NET > DotNET 4.0 Web Applications > Run

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" 
  Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.
w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
  <title>BotDetect CAPTCHA Customization ASP.NET Sample</title>
  <link type="text/css" rel="Stylesheet" href="StyleSheet.css" />
</head>
<body>
  <form id="form1" runat="server">
  <h1>BotDetect CAPTCHA Customization ASP.NET Sample</h1>
  <fieldset>
    <legend>CAPTCHA Validation</legend>
    <p class="prompt"><label for="CaptchaCodeTextBox">Retype the 
    characters from the picture:</label></p>
    <BotDetect:Captcha ID="SampleCaptcha" runat="server" />
    <div class="validationDiv">
      <asp:TextBox ID="CaptchaCodeTextBox" runat="server"></asp:
      TextBox>
      <asp:Button ID="ValidateCaptchaButton" runat="server" />
      <asp:Label ID="CaptchaCorrectLabel" runat="server" 
      CssClass="correct"></asp:Label>
      <asp:Label ID="CaptchaIncorrectLabel" runat="server" 
      CssClass="incorrect"></asp:Label>
    </div>
  </fieldset>
  </form>
</body>
</html>

Default.aspx.cs

using System;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_PreRender(object sender, EventArgs e)
    {
        // initial page setup
        if (!IsPostBack)
        {
            // set control text
            ValidateCaptchaButton.Text = "Validate";
            CaptchaCorrectLabel.Text = "Correct!";
            CaptchaIncorrectLabel.Text = "Incorrect!";

            // these messages are shown only after validation
            CaptchaCorrectLabel.Visible = false;
            CaptchaIncorrectLabel.Visible = false;

            // choose the custom charset used for CAPTCHA code 
            generation
            // (various custom charsets can be defined in the web.
            config file)
            SampleCaptcha.CustomCharacterSetName = "CustomCharset1";

            // customize the CAPTCHA image color scheme
            SampleCaptcha.CustomDarkColor = System.Drawing.Color.
            DarkSlateBlue;
            SampleCaptcha.CustomLightColor = System.Drawing.Color.
            LightSkyBlue;

            SampleCaptcha.ImageSize = new System.Drawing.Size(150, 40);
            SampleCaptcha.CodeLength = 3;
        }

        // setup client-side input processing
        SampleCaptcha.UserInputClientID = CaptchaCodeTextBox.ClientID;

        // client-side CAPTCHA event custom handlers:
        // BotDetect.RegisterCustomHandler('PrePlaySound', handler)
        //   custom javascript handler executed before Captcha sounds 
        //   are played

        // BotDetect.RegisterCustomHandler('PreReloadImage', handler)
        //   custom javascript handler executed before Captcha images 
        //   are reloaded

        // BotDetect.RegisterCustomHandler('PostReloadImage', handler)
        //   custom javascript handler executed after Captcha images 
        //   are reloaded    

        string script = @"
        BotDetect.RegisterCustomHandler(
          'PrePlaySound',
          function() { 
            alert('PrePlaySound: ' + this.Id);
        });

        BotDetect.RegisterCustomHandler( 
          'PreReloadImage',
          function() { 
            alert('PreReloadImage: ' + this.Image.src + 
            ' AutoReload: ' + this.AutoReloading); });
        });

        BotDetect.RegisterCustomHandler(
          'PostReloadImage',
          function() { 
            alert('PostReloadImage: ' + this.Image.src); 
        });

        
        this.Page.ClientScript.RegisterStartupScript(this.GetType(), 
        "BotDetectCustomEventHandlers", script, true);

        if (IsPostBack)
        {
            // validate the Captcha to check we're not dealing with a 
            bot
            string code = CaptchaCodeTextBox.Text.Trim().ToUpper();
            bool isHuman = SampleCaptcha.Validate(code);
            CaptchaCodeTextBox.Text = null; // clear previous user 
            input

            if (isHuman)
            {
                CaptchaCorrectLabel.Visible = true;
                CaptchaIncorrectLabel.Visible = false;
            }
            else
            {
                CaptchaCorrectLabel.Visible = false;
                CaptchaIncorrectLabel.Visible = true;
            }
        }
    }
}

Web.config

<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.
NetConfiguration/v2.0">
   <configSections>
    <!-- Register the BotDetect configuration section-->
    <section name="botDetect" requirePermission="false" 
      type="BotDetect.Configuration.BotDetectConfigurationSection, BotDetect"/>
  </configSections>
  
  <!-- BotDetect Captcha settings can be configured in this section -->
  <botDetect>
    <!-- Captcha code settings -->
    <!-- Captcha code timeout in seconds - the Captcha can only be successfuly
       solved within the specified time after generation. This is an optional
       security improvement that narrows the window of opportunity for attacks
       based on re-using the Captcha image on another site controlled by the
       attacker, or similar human-solver-based attacks on Captcha-protected
       forms. -->
    <captchaCodes timeout="120">
      <!-- Defines custom character sets for Captcha code generation. You can 
         then map the custom character sets defined here to appropriate Captcha 
         control instances by name in code-behind or .aspx designer. -->
      <characterSets>
        <!-- Full charset specification, defining all 3 code styles. -->
        <characterSet name="CustomCharset1" alpha="A,B,C,D,E" 
          numeric="1,2,3,4" alphanumeric="A,B,C,D,1,2,3"/>
        <!-- If you don't want to distinguish between code styles, you can 
           specify the alphanumeric characters only and they will be used for all 
           Captcha codes regardless of the codeStyle value set. -->
        <characterSet name="CustomCharset2" alphanumeric="A,B,C,D"/>
      </characterSets>
      <!-- Test mode, set to "true" during automated testing of your page to 
         make the Captcha trivially solvable (always use the "TEST" code). Be 
         careful not to enable this on production websites since it will allow
         trivial Captcha bypassing for bots but human users will still -->
         have to solve it. -->
      <testMode enabled="false"/>
    </captchaCodes>
    <!-- Captcha image settings -->
    <captchaImage>
      <!-- Custom Captcha image alt text / title -->
      <captchaImageTooltip>
        <localizedString value="CAPTCHA Image Custom Universal Tooltip" />
        <localizedString locale="es" 
          value="CAPTCHA Image  Custom Spanish Tooltip"/>
      </captchaImageTooltip>
      <!-- The Captcha image is also a link to a locale-dependent help page; 
         with customizable properties:
            - enabled: (true|false) turns the help link on or off
            - mode: (image|text) controls how the link is displayed -->
      <helpLink enabled="true" mode="text">
        <!-- absolute or application-relative help page Urls -->
        <helpPage>
          <localizedString value="~/captcha.html" />
          <localizedString locale="es" 
            value="http://es.captcha.com/captcha.html" />
        </helpPage>
        <!-- text used in the help link -->
        <helpText>
          <localizedString value="Custom CAPTCHA Help Link Text" />
          <localizedString locale="es" 
            value="Custom Spanish CAPTCHA Help Link Text" />
        </helpText>
      </helpLink>
    </captchaImage>
    <!-- Captcha sound settings -->
    <captchaSound enabled="true">
      <!-- Captcha sounds in BotDetect 3.0 require locale-dependent 
         pronunciation SoundPackage (.bdsp) files. Some default SoundPackages
         are included in all BotDetect installations, and pronunciations for
         additional languages can be downloaded from the Downloads section
         of the BotDetect website. There are several optional SoundPackage 
         settings:
           - folderPath: Custom sound packages folder. You can reuse a single
               location for all ASP.NET applications using BotDetect
               Captcha on the same server, and don't have to copy the
               SoundPackage files to each and every application's Bin
               folder.
           - warnAboutMissingSoundPackages: If the required SoundPackage in not
               deployed, the sound icon is not clickable and displays
               a warning tooltip by default. If you want to disable
               this warning and simply not display the sound Captcha
               icon at all for locales whose pronunciations are not
               deployed with the application, set this property to "false". -->
      <soundPackages folderPath="C:\Program Files (x86)\Lanapsoft\BotDetect 3 
        CAPTCHA Component\Asp.Net\BotDetectSounds" 
      warnAboutMissingSoundPackages="false"/>
      <!-- Custom sound Captcha icon image & titles -->
      <soundIcon filePath="~/CustomSoundIcon.gif" iconWidth="22">
        <soundIconTooltip>
          <localizedString value="Sound Icon Custom Universal Tooltip"/>
          <localizedString locale="es" 
            value="Sound Icon Custom Spanish Tooltip"/>
        </soundIconTooltip>
      </soundIcon>
    </captchaSound>
    <!-- Captcha reloading settings -->
    <captchaReloading enabled="true">
      <!-- Custom reload Captcha icon image & titles -->
      <reloadIcon filePath="http://captcha.com/images/refresh.png" 
      iconWidth="17">
        <reloadIconTooltip>
          <localizedString value="Reload Icon Custom Universal Tooltip"/>
          <localizedString locale="es" 
            value="Reload Icon Custom Spanish Tooltip"/>
        </reloadIconTooltip>
      </reloadIcon>
      <!-- Captcha images are automatically reloaded when the Captcha code 
         expires (as set in the <captchaCodes timeout="value"> element, 
         or the ASP.NET Session timeout), but only within  a certain interval
         from their first  generation. This allows you to have a short Captcha
         code timeout (e.g. 2 minutes) to narrow the window of opportunity
         for Captcha reusing on other sites or human-solver-powered bots,
         and actual visitors can still fill out your form at their own pace
         and without rushing (since the  Captcha image will be reloaded
         automatically when it is no longer valid).
         Since we don't want infinite sessions when the user leaves the form 
         open in a background browser tab over the weekend (for example), we
         set a reasonable upper limit on the auto-reload period (e.g. 2 
         hours = 7200 seconds). -->
      <autoReloadExpiredCaptchas enabled="true" timeout="7200"/>
    </captchaReloading>
    <!-- Captcha user input textbox client ID can be registered for each 
       Captcha control instance in code-behind or the .aspx designer,
       with several client-side options then becoming available.
       - autoUppercase: Anything the users type in the input textbox will be 
           uppercased on the fly, since Captcha validation is not and should
           not be case-sensitive. This is a small usability improvement 
           that helps communicate that fact to the users clearly.
       - autoClear: The input texbox will be cleared on all Reload icon clicks 
           and auto-reloads, since any previous input in the textbox will be 
           invalidated by Captcha reloading. This is a small usability
           improvement that helps users avoid having to delete the previous
           input themselves.
       - autoFocus: The input texbox will be assigned focus on all Captcha
           Sound and Captcha Reload icon clicks, allowing the users to more
           easily type in the code as they hear it or as the new image loads.
           This does not apply to auto-reloading of expired Captchas, since
           the user might be filling out another field on the form when the
           auto-reload starts and shouldn't be distracted. -->
    <captchaUserInput autoUppercase="true" autoClear="true" autoFocus="true"/>
    <!-- Custom Captcha HttpHandler path, in case the default
       "BotDetectCaptcha.ashx" doesn't suit your application. You can
       customize both the filename and the extension, but you must ensure
       the IIS mapping for the custom extension is set to be processed by
       the ASP.NET runtime. For example, you can use the ".jpg" extension
       only if you re-map ".jpg" requests to be handled by ASP.NET in your
       application's virtual folder, instead of the default IIS file
       system mapping for ".jpg" files. -->
    <captchaUrls requestPath="CaptchaCustomPath.ashx"/>
    <!-- Custom SessionID encryption password, used to secure the SessionID
       value  that has to be passed in the sound Captcha querystring to avoid
       sound mismatch problems in some older browsers. The SessionID is never
       passed in plaintext querystring to avoid Session hijacking or spoofing
       attacks, and you should specify your own unique encryption password to
       secure it properly. -->
    <captchaEncryption encryptionPassword="SecretEncryptionPassword"/>
    <!-- Custom Captcha Http request validator, allowing only a certain number
       of repeated requests with identical querystrings. Human users in
       normal browsers will always use unique querystrings to access Captcha
       images and sounds (the way the Captcha control works guarantees this),
       while simple bots will often repeat the same request in short time
       intervals. This is a simple measure that increases Captcha security
       by stopping to serve Captcha images and sounds to such obvious bots
       (Captcha is used for bot detection, and in such a case we can detect
       that a bot is involved even without wasting resources on generating
       more Captcha images or sounds). -->
    <captchaRequestFilter enabled="true" allowedRepeatedRequests="3"/>
    <!-- Should Captcha SessionState persistence diagnostics be run on all
       control renders and Http requests. Allows Session troubleshooting,
       detectiong the following conditions:
         - IsSessionHttpModuleRunning (full trust only)
         - IsCustomSessionIdManagerIncluded (full trust only)
         - IsSessionStateEmpty
         - IsNewSession (on PostBack and all HttpHandler requests)
         - IsCaptchaPersistenceEmpty (for initialized CaptchaControls only) -->
    <captchaSessionTroubleshooting enabled="true"/>
    <!-- Should Captcha HttpHandler diagnostics be run on all control
       renders. This is useful while developing your page, but can be turned
       off for production deployments after you ensure the Captcha image
       is showing properly.-->
    <captchaHttpHandlerTroubleshooting enabled="true"/>
    <!-- Should BotDetect also add the remote JavaScript include loaded from the 
       captcha.com server. Currently used only for stats, but planned to develop into 
       additional Captcha functionality -->
    <captchaRemoteScript enabled="true" />
  </botDetect>

  
  <system.web>
    <httpHandlers>
      <!-- Register the HttpHandler used for BotDetect Captcha 
      requests-->
      <add verb="GET" path="CaptchaCustomPath.ashx" 
	  type="BotDetect.Web.CaptchaHandler, BotDetect"/>
    </httpHandlers>
    <!-- Register a custom SessionIDManager for BotDetect Captcha 
    requests, which will prevent sound Captcha mismatch problems in 
    some older browsers and media players-->
    <sessionState mode="InProc" cookieless="AutoDetect" timeout="20" 
      sessionIDManagerType="BotDetect.Web.CustomSessionIdManager, BotDetect"/>
    <!-- Session state is required for BotDetect storage; you can also 
    turn if off globally and only enable for BotDetect-protected pages 
    if you prefer-->
    <pages enableSessionState="true">
      <controls>
        <!-- Register the BotDetect tag prefix for easier use in all 
        pages-->
        <add assembly="BotDetect" namespace="BotDetect.Web.UI" 
        tagPrefix="BotDetect"/>
      </controls>
    </pages>
    <compilation debug="true" targetFramework="4.0">
    </compilation>
    <trace enabled="false" localOnly="true"/>
    <httpCookies httpOnlyCookies="true"/>
    <trust level="Medium" originUrl=""/>
    <authentication mode="None"/>
    <customErrors mode="RemoteOnly"></customErrors>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <handlers>
      <!-- Register the HttpHandler used for BotDetect Captcha 
      requests (IIS 7.0+)-->
      <remove name="BotDetectCaptchaHandler"/>
      <add name="BotDetectCaptchaHandler" 
      preCondition="integratedMode" verb="GET" 
	  path="CaptchaCustomPath.ashx" 
	  type="BotDetect.Web.CaptchaHandler, BotDetect"/>
    </handlers>
  </system.webServer>
</configuration>

Visual Studio 2008 / .NET 3.5

By default, the .NET 3.5 C# version of the ASP.NET Captcha customization sample project is installed at:
C:\Program Files\Lanapsoft\BotDetect 3 CAPTCHA Component\Asp.Net\v3.5\WebApp\CaptchaCustomizationSample\CSharp

You can also run it from the BotDetect Start Menu:
Programs > Lanapsoft > BotDetect 3 CAPTCHA Component > ASP.NET > DotNET 3.5 Web Applications > Run

The Visual Studio 2008 / .NET 3.5 source has no essential differences from the Visual Studio 2010 / .NET 4.0 source.

Visual Studio 2005 / .NET 2.0

By default, the .NET 2.0 C# version of the ASP.NET Captcha customization sample project is installed at:
C:\Program Files\Lanapsoft\BotDetect 3 CAPTCHA Component\Asp.Net\v2.0\WebApp\CaptchaCustomizationSample\CSharp

You can also run it from the BotDetect Start Menu:
Programs > Lanapsoft > BotDetect 3 CAPTCHA Component > ASP.NET > DotNET 2.0 Web Applications > Run

The Visual Studio 2005 / .NET 2.0 source has no essential differences from the Visual Studio 2010 / .NET 4.0 source.