ASP.NET MVC 1.0 Application Template CAPTCHA VB.NET Code Sample (BotDetect v3.0; deprecated)

The ASP.NET MVC 1.0 application template Captcha sample project shows how to use the BotDetect CAPTCHA MvcCaptcha control in ASP.NET MVC 1.0 web applications.

First Time Here?

Check the BotDetect ASP.NET MVC Captcha Quickstart for key integration steps.

Starting with the default ASP.NET MVC 1.0 Visual Studio 2008 project template, the sample includes all code required to add CAPTCHA validation to the Account controller Register action.

The sample remembers when the CAPTCHA is successfully solved within a single registration, and doesn't display it again if there are errors with other form values (the username, for example).

You can get a new CAPTCHA using the Register action link in the top right corner of the page, and see the explanation in the Account controller code.

→ ASP.NET MVC version:

→ .NET programming language:

  • C#
  • VB.NET

Installed Location

By default, the .NET 3.5 VB.NET version of the ASP.NET MVC 1.0 application template Captcha sample project is installed at:
C:\Program Files\Lanapsoft\BotDetect 3 CAPTCHA Component\Asp.Net\v3.5\WebApp\AspNetMVC10CaptchaSample\VBNet

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

Views\Account\Register.aspx

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" 
Inherits="System.Web.Mvc.ViewPage" %>

<%@ Import Namespace="AspNetMvc10CaptchaSampleVBNet" %>

<asp:Content ID="registerTitle" ContentPlaceHolderID="TitleContent" 
runat="server">
    Register
</asp:Content>

<asp:Content ID="BotDetectStylesheets" ContentPlaceHolderID="includes" 
  runat="server">
    <link href="<%= BotDetect.Web.CaptchaUrls.Absolute.LayoutStyleSheetUrl %>" 
      rel="stylesheet" type="text/css" />
</asp:Content>

<asp:Content ID="registerContent" ContentPlaceHolderID="MainContent" 
runat="server">
    <h2>Create a New Account</h2>
    <p>
        Use the form below to create a new account. 
    </p>
    <p>
        Passwords are required to be a minimum of <%=Html.Encode(
        ViewData("PasswordLength"))%> characters in length.
    </p>
    <p>
        <%= Html.ValidationSummary("Account creation was unsuccessful. 
        Please correct the errors and try again.") %>
    </p>

    <% Using Html.BeginForm()%>
        <div>
            <fieldset id="RegisterFields">
                <legend>Account Information</legend>
                <p>
                    <label for="username">Username:</label>
                    <%= Html.TextBox("username") %>
                    <%= Html.ValidationMessage("username") %>
                </p>
                <p>
                    <label for="email">Email:</label>
                    <%= Html.TextBox("email") %>
                    <%= Html.ValidationMessage("email") %>
                </p>
                <p>
                    <label for="password">Password:</label>
                    <%= Html.Password("password") %>
                    <%= Html.ValidationMessage("password") %>
                </p>
                <p>
                    <label for="confirmPassword">Confirm password:<
                    /label>
                    <%= Html.Password("confirmPassword") %>
                    <%= Html.ValidationMessage("confirmPassword") %>
                </p>
                
                <%  Dim registrationCaptcha As BotDetect.Web.UI.Mvc.
                    MvcCaptcha = _
                      CaptchaHelper.GetRegistrationCaptcha()
                    
                    If (Not registrationCaptcha.IsSolved) Then%>
                <%= Html.Captcha(registrationCaptcha) %>
                <p>
                    <label for="captchaCode">Please retype the 
                    characters from the picture:</label>
                    <%= Html.TextBox("captchaCode")%>
                    <%= Html.ValidationMessage("captchaCode")%>
                </p>
                <% End If%>
                
                <p>
                    <input type="submit" value="Register" />
                </p>
            </fieldset>
        </div>
    <% End Using %>
</asp:Content>

BotDetect stylesheets are included in the generated page Header using the includes content placeholder defined in the Master page.

To keep View code simple, we delegate MvcCaptcha instance creation to a helper class, and use it along with Model fields to generate the required markup using straightforward HtmlHelper calls.

Since we want to avoid re-displaying the Captcha challenge to users after they solve it, we only call the markup generation code if the IsSolved property is not set by a previous successful Captcha validation.

Views\Shared\Site.Master

<%@ Master Language="VB" Inherits="System.Web.Mvc.ViewMasterPage" %>

<!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 runat="server">
    <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" />
    </title>
    <link href="../../Content/Site.css" rel="stylesheet" 
    type="text/css" />
    <asp:ContentPlaceHolder id="includes" runat="server"></asp:
    ContentPlaceHolder>
</head>

<body>
    <div class="page">

        <div id="header">
            <div id="title">
                <h1>BotDetect CAPTCHA ASP.NET MVC 1.0 Sample</h1>
            </div>
              
            <div id="logindisplay">
                <% Html.RenderPartial("LogOnUserControl")%>            
            </div> 
            
            <div id="menucontainer">
            
                <ul id="menu">              
                    <li><%= Html.ActionLink("Home", "Index", "Home")%>
                    </li>
                    <li><%=Html.ActionLink("About", "About", "Home")%>
                    </li>
                </ul>
            
            </div>
        </div>

        <div id="main">
            <asp:ContentPlaceHolder ID="MainContent" runat="server" />

            <div id="footer">
            </div>
        </div>
    </div>
</body>
</html>

To allow easy inclusion of BotDetect stylesheets into Views which require them, the includes content placeholder should be declared in the Master page header.

Controllers\AccountController.vb

Imports System.Globalization
Imports System.Security.Principal
Imports BotDetect.Web.UI.Mvc

<HandleError()> _
Public Class AccountController
    Inherits System.Web.Mvc.Controller

    Private _formsAuth As IFormsAuthentication
    Private _service As IMembershipService

    ' This constructor is used by the MVC framework to instantiate the 
    controller using
    ' the default forms authentication and membership providers.

    Sub New()
        Me.New(Nothing, Nothing)
    End Sub

    ' This constructor is not used by the MVC framework but is instead 
    provided for ease
    ' of unit testing this type. See the comments at the end of this 
    file for more
    ' information.

    Sub New(ByVal formsAuth As IFormsAuthentication, ByVal service As 
    IMembershipService)
        _formsAuth = If(formsAuth, New FormsAuthenticationService())
        _service = If(service, New AccountMembershipService())
    End Sub

    ReadOnly Property FormsAuth() As IFormsAuthentication
        Get
            Return _formsAuth
        End Get
    End Property

    ReadOnly Property MembershipService() As IMembershipService
        Get
            Return _service
        End Get
    End Property

    Function LogOn() As ActionResult

        ViewData("Title") = "Log On"

        Return View()
    End Function

    <AcceptVerbs(HttpVerbs.Post)> _
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.
    Design", "CA1054:UriParametersShouldNotBeStrings", _
            Justification:="Needs to take same parameter type as 
            Controller.Redirect()")> _
    Function LogOn(ByVal userName As String, ByVal password As String, 
    ByVal rememberMe As Boolean, ByVal returnUrl As String) As 
    ActionResult

        ViewData("Title") = "Log On"

        If Not ValidateLogOn(userName, password) Then
            ViewData("rememberMe") = rememberMe
            Return View()
        End If

        FormsAuth.SignIn(userName, rememberMe)
        If Not String.IsNullOrEmpty(returnUrl) Then
            Return Redirect(returnUrl)
        Else
            Return RedirectToAction("Index", "Home")
        End If

    End Function

    Function LogOff() As ActionResult

        FormsAuth.SignOut()

        Return RedirectToAction("Index", "Home")
    End Function

    Function Register() As ActionResult

        ViewData("Title") = "Register"
        ViewData("PasswordLength") = MembershipService.
        MinPasswordLength

        ' when the View is accessed directly and not posted, we clear 
        ' any remembered CAPTCHA solving state. 
        ' The users only have to solve the CAPTCHA once within a 
        ' single registration, but if they reload the Register 
        ' page later, it is shown again. 
        ' Otherwise, they could register an unlimited number of 
        ' accounts within a single Session after solving the 
        ' CAPTCHA only once.
        MvcCaptcha.ResetCaptcha("RegistrationCaptcha")

        Return View()
    End Function

    <AcceptVerbs(HttpVerbs.Post)> _
    <CaptchaValidation("captchaCode", "RegistrationCaptcha", "Your 
      input doesn't match displayed characters.")> _
    Function Register(ByVal userName As String, ByVal email As String, 
    ByVal password As String, ByVal confirmPassword As String) As 
    ActionResult

        ViewData("Title") = "Register"
        ViewData("PasswordLength") = MembershipService.
        MinPasswordLength

        If ValidateRegistration(userName, email, password, 
        confirmPassword) Then
            ' Attempt to register the user
            Dim createStatus As MembershipCreateStatus = 
            MembershipService.CreateUser(userName, password, email)

            If createStatus = MembershipCreateStatus.Success Then
                FormsAuth.SignIn(userName, False)
                Return RedirectToAction("Index", "Home")
            Else
                ModelState.AddModelError("_FORM", ErrorCodeToString(
                createStatus))
            End If
        End If

        Return View()
    End Function

    <Authorize()> _
    Function ChangePassword() As ActionResult

        ViewData("Title") = "Change Password"
        ViewData("PasswordLength") = MembershipService.
        MinPasswordLength

        Return View()
    End Function

    <Authorize()> _
    <AcceptVerbs(HttpVerbs.Post)> _
    <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.
    Design", "CA1031:DoNotCatchGeneralExceptionTypes", _
            Justification:="Exceptions result in password not being 
            changed.")> _
    Function ChangePassword(ByVal currentPassword As String, ByVal 
    newPassword As String, ByVal confirmPassword As String) As 
    ActionResult

        ViewData("Title") = "Change Password"
        ViewData("PasswordLength") = MembershipService.
        MinPasswordLength

        If Not ValidateChangePassword(currentPassword, newPassword, 
        confirmPassword) Then
            Return View()
        End If

        Try
            If MembershipService.ChangePassword(User.Identity.Name, 
            currentPassword, newPassword) Then
                Return RedirectToAction("ChangePasswordSuccess")
            Else
                ModelState.AddModelError("_FORM", "The current 
                password is incorrect or the new password is invalid.")
                Return View()
            End If
        Catch ex As Exception
            ModelState.AddModelError("_FORM", "The current password is 
            incorrect or the new password is invalid.")
            Return View()
        End Try
    End Function

    Function ChangePasswordSuccess() As ActionResult

        ViewData("Title") = "Change Password"

        Return View()
    End Function

    Protected Overrides Sub OnActionExecuting(ByVal filterContext As 
    System.Web.Mvc.ActionExecutingContext)
        If TypeOf filterContext.HttpContext.User.Identity Is 
        WindowsIdentity Then
            Throw New InvalidOperationException("Windows 
            authentication is not supported.")
        End If
    End Sub

#Region "Validation Methods"

    Private Function ValidateChangePassword(ByVal currentPassword As 
    String, ByVal newPassword As String, ByVal confirmPassword As 
    String) As Boolean
        If String.IsNullOrEmpty(currentPassword) Then
            ModelState.AddModelError("currentPassword", "You must 
            specify a current password.")
        End If

        If newPassword Is Nothing OrElse newPassword.Length < 
        MembershipService.MinPasswordLength Then
            ModelState.AddModelError("newPassword", String.Format(
            CultureInfo.CurrentCulture, _
                                                   "You must specify a 
                                                   new password of {0} 
                                                   or more characters.
                                                   ", _
                                                   MembershipService.
                                                   MinPasswordLength))
        End If

        If Not String.Equals(newPassword, confirmPassword, 
        StringComparison.Ordinal) Then
            ModelState.AddModelError("_FORM", "The new password and 
            confirmation password do not match.")
        End If

        Return ModelState.IsValid
    End Function

    Private Function ValidateLogOn(ByVal userName As String, ByVal 
    password As String) As Boolean
        If String.IsNullOrEmpty(userName) Then
            ModelState.AddModelError("username", "You must specify a 
            username.")
        End If

        If String.IsNullOrEmpty(password) Then
            ModelState.AddModelError("password", "You must specify a 
            password.")
        End If

        If Not MembershipService.ValidateUser(userName, password) Then
            ModelState.AddModelError("_FORM", "The username or 
            password provided is incorrect.")
        End If

        Return ModelState.IsValid
    End Function

    Private Function ValidateRegistration(ByVal userName As String, 
    ByVal email As String, ByVal password As String, ByVal 
    confirmPassword As String) As Boolean
        If String.IsNullOrEmpty(userName) Then
            ModelState.AddModelError("username", "You must specify a 
            username.")
        End If

        If String.IsNullOrEmpty(email) Then
            ModelState.AddModelError("email", "You must specify an 
            email address.")
        End If

        If password Is Nothing OrElse password.Length < 
        MembershipService.MinPasswordLength Then
            ModelState.AddModelError("password", String.Format(
            CultureInfo.CurrentCulture, _
                                                   "You must specify a 
                                                   password of {0} or 
                                                   more characters.", 
                                                   _
                                                   MembershipService.
                                                   MinPasswordLength))
        End If

        If Not String.Equals(password, confirmPassword, 
        StringComparison.Ordinal) Then
            ModelState.AddModelError("_FORM", "The new password and 
            confirmation password do not match.")
        End If

        Return ModelState.IsValid
    End Function

    Private Shared Function ErrorCodeToString(ByVal createStatus As 
    MembershipCreateStatus) As String
        ' See http://msdn.microsoft.com/en-us/library/system.web.
        security.membershipcreatestatus.aspx for
        ' a full list of status codes.
        Select Case createStatus
            Case MembershipCreateStatus.DuplicateUserName
                Return "Username already exists. Please enter a 
                different user name."

            Case MembershipCreateStatus.DuplicateEmail
                Return "A username for that e-mail address already 
                exists. Please enter a different e-mail address."

            Case MembershipCreateStatus.InvalidPassword
                Return "The password provided is invalid. Please enter 
                a valid password value."

            Case MembershipCreateStatus.InvalidEmail
                Return "The e-mail address provided is invalid. Please 
                check the value and try again."

            Case MembershipCreateStatus.InvalidAnswer
                Return "The password retrieval answer provided is 
                invalid. Please check the value and try again."

            Case MembershipCreateStatus.InvalidQuestion
                Return "The password retrieval question provided is 
                invalid. Please check the value and try again."

            Case MembershipCreateStatus.InvalidUserName
                Return "The user name provided is invalid. Please 
                check the value and try again."

            Case MembershipCreateStatus.ProviderError
                Return "The authentication provider returned an error. 
                Please verify your entry and try again. If the problem 
                persists, please contact your system administrator."

            Case MembershipCreateStatus.UserRejected
                Return "The user creation request has been canceled. 
                Please verify your entry and try again. If the problem 
                persists, please contact your system administrator."

            Case Else
                Return "An unknown error occurred. Please verify your 
                entry and try again. If the problem persists, please 
                contact your system administrator."
        End Select

    End Function
#End Region

End Class

' The FormsAuthentication type is sealed and contains static members, 
so it is difficult to
' unit test code that calls its members. The interface and helper 
class below demonstrate
' how to create an abstract wrapper around such a type in order to 
make the AccountController
' code unit testable.

Public Interface IFormsAuthentication

    Sub SignIn(ByVal userName As String, ByVal createPersistentCookie 
    As Boolean)
    Sub SignOut()

End Interface


Public Class FormsAuthenticationService
    Implements IFormsAuthentication

    Public Sub SignIn(ByVal userName As String, ByVal 
    createPersistentCookie As Boolean) Implements IFormsAuthentication.
    SignIn
        FormsAuthentication.SetAuthCookie(userName, 
        createPersistentCookie)
    End Sub

    Public Sub SignOut() Implements IFormsAuthentication.SignOut
        FormsAuthentication.SignOut()
    End Sub

End Class

Public Interface IMembershipService
    ReadOnly Property MinPasswordLength() As Integer

    Function ChangePassword(ByVal userName As String, ByVal 
    oldPassword As String, ByVal newPassword As String) As Boolean
    Function CreateUser(ByVal userName As String, ByVal password As 
    String, ByVal email As String) As MembershipCreateStatus
    Function ValidateUser(ByVal userName As String, ByVal password As 
    String) As Boolean

End Interface

Public Class AccountMembershipService
    Implements IMembershipService

    Private _provider As MembershipProvider

    Sub New()
        Me.New(Nothing)
    End Sub

    Sub New(ByVal provider As MembershipProvider)
        _provider = If(provider, Membership.Provider)
    End Sub

    Public ReadOnly Property MinPasswordLength() As Integer Implements 
    IMembershipService.MinPasswordLength
        Get
            Return _provider.MinRequiredPasswordLength
        End Get
    End Property

    Function ChangePassword(ByVal userName As String, ByVal 
    oldPassword As String, ByVal newPassword As String) As Boolean 
    Implements IMembershipService.ChangePassword
        Dim currentUser As MembershipUser = _provider.GetUser(userName,
        True)
        Return currentUser.ChangePassword(oldPassword, newPassword)
    End Function

    Function CreateUser(ByVal userName As String, ByVal password As 
    String, ByVal email As String) As MembershipCreateStatus 
    Implements IMembershipService.CreateUser
        Dim status As MembershipCreateStatus
        _provider.CreateUser(userName, password, email, Nothing, 
        Nothing, True, Nothing, status)
        Return status
    End Function

    Function ValidateUser(ByVal userName As String, ByVal password As 
    String) As Boolean Implements IMembershipService.ValidateUser
        Return _provider.ValidateUser(userName, password)
    End Function

End Class

To add Captcha validation to the Register action Controller code, we perform a single line of setup in the Register action when the user GETs it, and execute the <CaptchaValidation> filter when the user POSTs it.

The filter attribute will automatically add the appropriate ModelState error if the Captcha code input doesn't match the code displayed to the user in the Captcha picture.

CaptchaHelper.vb

Imports BotDetect
Imports BotDetect.Web
Imports BotDetect.Web.UI
Imports BotDetect.Web.UI.Mvc

Public Class CaptchaHelper

    Public Shared Function GetRegistrationCaptcha() As MvcCaptcha

        ' create the control instance
        Dim registrationCaptcha As BotDetect.Web.UI.Mvc.MvcCaptcha = _
            New BotDetect.Web.UI.Mvc.MvcCaptcha("RegistrationCaptcha")

        registrationCaptcha.UserInputClientID = "captchaCode"

        ' Captcha properties are set in this event handler
        AddHandler registrationCaptcha.InitializedCaptchaControl, _
            AddressOf RegistrationCaptcha_InitializedCaptchaControl

        Return registrationCaptcha

    End Function

    ' event handler used for Captcha control property randomization
    Public Shared Sub RegistrationCaptcha_InitializedCaptchaControl( _
        ByVal sender As Object, _
        ByVal e As BotDetect.InitializedCaptchaControlEventArgs)

        If (e.CaptchaId <> "RegistrationCaptcha") Then
            Return
        End If

        Dim registrationCaptcha As CaptchaControl = TryCast(sender, 
        CaptchaControl)

        ' fixed Captcha settings 
        registrationCaptcha.ImageSize = New System.Drawing.Size(200, 
          50)
        registrationCaptcha.CodeLength = 4

        ' randomized Captcha settings
        registrationCaptcha.ImageStyle = CaptchaRandomization.
          GetRandomImageStyle()
        registrationCaptcha.SoundStyle = CaptchaRandomization.
          GetRandomSoundStyle()
    End Sub

End Class

Captcha instance creation and property setting is encapsulated in this simple helper class. This separation allows application Views to stay simple regardless of the amount of Captcha customization chosen.

Global.asax.vb

' Note: For instructions on enabling IIS6 or IIS7 classic mode, 
' visit http://go.microsoft.com/?LinkId=9394802

Public Class MvcApplication
    Inherits System.Web.HttpApplication

    Public Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}")

        ' BotDetect requests must not be routed
        routes.IgnoreRoute("{*botdetect}", New With {.botdetect = "(.*)
          BotDetectCaptcha\.ashx"})


        ' Set the Register action as the sample project default, 
        ' since it includes the Captcha control and we want to show it
        routes.MapRoute( _
            "Default", _
            "{controller}/{action}/{id}", _
            New With {.controller = "Account", .action = "Register", .
            id = ""} _
        )
    End Sub

    Sub Application_Start()
        RegisterRoutes(RouteTable.Routes)
    End Sub
End Class

Since all BotDetect requests are handled by the BotDetect HttpHandler, ASP.NET Url Routing must be configured to ignore BotDetect requests, which can be achieved by a single line of code in Global.asax code-behind.

Web.config

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.web.extensions" type="System.Web.
    Configuration.SystemWebExtensionsSectionGroup, System.Web.
    Extensions, Version=3.5.0.0, Culture=neutral, 
    PublicKeyToken=31BF3856AD364E35">
      <sectionGroup name="scripting" type="System.Web.Configuration.
      ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, 
      Culture=neutral, PublicKeyToken=31BF3856AD364E35">
        <section name="scriptResourceHandler" type="System.Web.
        Configuration.ScriptingScriptResourceHandlerSection, System.
        Web.Extensions, Version=3.5.0.0, Culture=neutral, 
        PublicKeyToken=31BF3856AD364E35" requirePermission="false" 
        allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.
        Configuration.ScriptingWebServicesSectionGroup, System.Web.
        Extensions, Version=3.5.0.0, Culture=neutral, 
        PublicKeyToken=31BF3856AD364E35">
          <section name="jsonSerialization" type="System.Web.
          Configuration.ScriptingJsonSerializationSection, System.Web.
          Extensions, Version=3.5.0.0, Culture=neutral, 
          PublicKeyToken=31BF3856AD364E35" requirePermission="false" 
          allowDefinition="Everywhere"/>
          <section name="profileService" type="System.Web.
          Configuration.ScriptingProfileServiceSection, System.Web.
          Extensions, Version=3.5.0.0, Culture=neutral, 
          PublicKeyToken=31BF3856AD364E35" requirePermission="false" 
          allowDefinition="MachineToApplication"/>
          <section name="authenticationService" type="System.Web.
          Configuration.ScriptingAuthenticationServiceSection, System.
          Web.Extensions, Version=3.5.0.0, Culture=neutral, 
          PublicKeyToken=31BF3856AD364E35" requirePermission="false" 
          allowDefinition="MachineToApplication"/>
          <section name="roleService" type="System.Web.Configuration.
          ScriptingRoleServiceSection, System.Web.Extensions, 
          Version=3.5.0.0, Culture=neutral, 
          PublicKeyToken=31BF3856AD364E35" requirePermission="false" 
          allowDefinition="MachineToApplication"/>
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>
  </configSections>
  <connectionStrings>
    <add name="ApplicationServices" connectionString="data source=.
    \SQLEXPRESS;Integrated Security=SSPI;
    AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" 
    providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <system.web>
    <compilation debug="true">
      <assemblies>
        <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, 
        PublicKeyToken=B77A5C561934E089"/>
        <add assembly="System.Web.Extensions, Version=3.5.0.0, 
        Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Abstractions, Version=3.5.0.0, 
        Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Routing, Version=3.5.0.0, 
        Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Mvc, Version=1.0.0.0, 
        Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, 
        Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
      </assemblies>
    </compilation>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>
    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.
        Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, 
        Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
        connectionStringName="ApplicationServices" 
        enablePasswordRetrieval="false" enablePasswordReset="true" 
        requiresQuestionAndAnswer="false" requiresUniqueEmail="false" 
        passwordFormat="Hashed" maxInvalidPasswordAttempts="5" 
        minRequiredPasswordLength="6" 
        minRequiredNonalphanumericCharacters="0" 
        passwordAttemptWindow="10" 
        passwordStrengthRegularExpression="" applicationName="/"/>
      </providers>
    </membership>
    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.
        SqlProfileProvider, System.Web, Version=2.0.0.0, 
        Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
        connectionStringName="ApplicationServices" 
        applicationName="/"/>
      </providers>
    </profile>
    <roleManager enabled="false">
      <providers>
        <clear/>
        <add connectionStringName="ApplicationServices" 
        applicationName="/" name="AspNetSqlRoleProvider" type="System.
        Web.Security.SqlRoleProvider, System.Web, Version=2.0.0.0, 
        Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        <add applicationName="/" name="AspNetWindowsTokenRoleProvider" 
        type="System.Web.Security.WindowsTokenRoleProvider, System.Web,
        Version=2.0.0.0, Culture=neutral, 
        PublicKeyToken=b03f5f7f11d50a3a"/>
      </providers>
    </roleManager>
    <!-- make sure Session State is enabled -->
    <pages enableSessionState="true">
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" 
        assembly="System.Web.Extensions, Version=3.5.0.0, 
        Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add tagPrefix="asp" namespace="System.Web.UI.WebControls" 
        assembly="System.Web.Extensions, Version=3.5.0.0, 
        Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </controls>
      <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Ajax"/>
        <add namespace="System.Web.Mvc.Html"/>
        <add namespace="System.Web.Routing"/>
        <add namespace="System.Collections.Generic"/>
        <!-- add BotDetect namespaces for coding convenience -->
        <add namespace="BotDetect"/>
        <add namespace="BotDetect.Web"/>
        <add namespace="BotDetect.Web.UI"/>
        <add namespace="BotDetect.Web.UI.Mvc"/>
      </namespaces>
    </pages>
    <!-- configure Session State for BotDetect use -->
    <sessionState mode="InProc" cookieless="AutoDetect" timeout="20" 
      sessionIDManagerType="BotDetect.Web.CustomSessionIdManager, 
        BotDetect"/>
    <httpHandlers>
      <remove verb="*" path="*.asmx"/>
      <add verb="*" path="*.asmx" validate="false" type="System.Web.
      Script.Services.ScriptHandlerFactory, System.Web.Extensions, 
      Version=3.5.0.0, Culture=neutral, 
      PublicKeyToken=31BF3856AD364E35"/>
      <add verb="*" path="*_AppService.axd" validate="false" 
      type="System.Web.Script.Services.ScriptHandlerFactory, System.
      Web.Extensions, Version=3.5.0.0, Culture=neutral, 
      PublicKeyToken=31BF3856AD364E35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.
      Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.
      5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" 
      validate="false"/>
      <add verb="*" path="*.mvc" validate="false" type="System.Web.Mvc.
      MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral,
      PublicKeyToken=31BF3856AD364E35"/>
      <!-- register HttpHandler used for BotDetect Captcha requests -->
      <add verb="GET" path="BotDetectCaptcha.ashx" 
	  type="BotDetect.Web.CaptchaHandler, BotDetect"/>
    </httpHandlers>
    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, 
      System.Web.Extensions, Version=3.5.0.0, Culture=neutral, 
      PublicKeyToken=31BF3856AD364E35"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.
      UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, 
      Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </httpModules>
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" 
      warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, 
      System, Version=2.0.0.0, Culture=neutral, 
      PublicKeyToken=b77a5c561934e089">
        <providerOption name="CompilerVersion" value="v3.5"/>
        <providerOption name="WarnAsError" value="false"/>
      </compiler>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" 
      warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, 
      System, Version=2.0.0.0, Culture=neutral, 
      PublicKeyToken=b77a5c561934e089">
        <providerOption name="CompilerVersion" value="v3.5"/>
        <providerOption name="OptionInfer" value="true"/>
        <providerOption name="WarnAsError" value="false"/>
      </compiler>
    </compilers>
  </system.codedom>
  <system.web.extensions/>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="ScriptModule"/>
      <remove name="UrlRoutingModule"/>
      <add name="ScriptModule" preCondition="managedHandler" 
      type="System.Web.Handlers.ScriptModule, System.Web.Extensions, 
      Version=3.5.0.0, Culture=neutral, 
      PublicKeyToken=31BF3856AD364E35"/>
      <add name="UrlRoutingModule" type="System.Web.Routing.
      UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, 
      Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>
    <handlers>
      <remove name="WebServiceHandlerFactory-Integrated"/>
      <remove name="ScriptHandlerFactory"/>
      <remove name="ScriptHandlerFactoryAppServices"/>
      <remove name="ScriptResource"/>
      <remove name="MvcHttpHandler"/>
      <remove name="UrlRoutingHandler"/>
      <add name="ScriptHandlerFactory" verb="*" path="*.asmx" 
      preCondition="integratedMode" type="System.Web.Script.Services.
      ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, 
      Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="ScriptHandlerFactoryAppServices" verb="*" 
      path="*_AppService.axd" preCondition="integratedMode" 
      type="System.Web.Script.Services.ScriptHandlerFactory, System.
      Web.Extensions, Version=3.5.0.0, Culture=neutral, 
      PublicKeyToken=31BF3856AD364E35"/>
      <add name="ScriptResource" preCondition="integratedMode" 
      verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.
      Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.
      5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      <add name="MvcHttpHandler" preCondition="integratedMode" 
      verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, 
      System.Web.Mvc, Version=1.0.0.0, Culture=neutral, 
      PublicKeyToken=31BF3856AD364E35"/>
      <add name="UrlRoutingHandler" preCondition="integratedMode" 
      verb="*" path="UrlRouting.axd" type="System.Web.
      HttpForbiddenHandler, System.Web, Version=2.0.0.0, 
      Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
      <!-- register HttpHandler used for BotDetect Captcha requests -->
      <remove name="BotDetectCaptchaHandler"/>
      <add name="BotDetectCaptchaHandler" 
      preCondition="integratedMode" verb="GET" 
	  path="BotDetectCaptcha.ashx" 
	  type="BotDetect.Web.CaptchaHandler, BotDetect"/>
    </handlers>
  </system.webServer>
</configuration>

The application's web.config file includes the standard BotDetect HttpHandler and Session state configuration elements.


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.