ASP.NET Website Razor 3 CAPTCHA C# Code Example

The ASP.NET Website Razor 3 Captcha example project shows the most basic source code required to protect an ASP.NET Web Pages form using new Razor syntax with BotDetect CAPTCHA and validate the user input.

First Time Here?

Check the BotDetect Developer Crash Course for key integration steps.

ASP.NET Website Razor 3 code displaying CAPTCHA protection and checking user input can be found in Register.cshtml.

Download the BotDetect ASP.NET CAPTCHA Generator archive to run this example

Visual Studio 2017, 2015 / .NET 4.6 and onwards

Within this page, the root folder of the extracted archive is referred as the <BDC-DIR>.

This example is in the <BDC-DIR>/lgcy-on-lgcy/examples/t_api-captcha-webpages-web.security.membership/csharp/ folder; and contains the following files:

Register.cshtml

@using BotDetect.Web
@* Remove this section if you are using bundling *@
@section Scripts {
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
}

@{
    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "Register";

    // Initialize general page variables
    var email = "";
    var password = "";
    var confirmPassword = "";

    // Setup validation
    Validation.RequireField("email", "You must specify an email address.");
    Validation.RequireField("password", "Password cannot be blank.");
    Validation.Add("confirmPassword",
        Validator.EqualsTo("password", "Password and confirmation password do 
        not match."));
    Validation.Add("password",
        Validator.StringLength(
            maxLength: Int32.MaxValue,
            minLength: 6,
            errorMessage: "Password must be at least 6 characters"));

    Captcha exampleCaptcha = new Captcha("ExampleCaptcha")
    {
        UserInputID = "CaptchaCode",
        RemoteScriptEnabled = true
    };
    // If this is a POST request, validate and process data
    if (IsPost)
    {
        AntiForgery.Validate();
        email = Request.Form["email"];
        password = Request.Form["password"];
        confirmPassword = Request.Form["confirmPassword"];

        // Validate the user's captcha answer

        bool isHuman = exampleCaptcha.Validate();
        if (!isHuman)
        {
            ModelState.AddFormError("Captcha response was not correct");
        }

        // If all information is valid, create a new account
        if (Validation.IsValid())
        {
            // Insert a new user into the database
            var db = Database.Open("StarterSite");

            // Check if user already exists
            var user = db.QuerySingle("SELECT Email FROM UserProfile WHERE LOWER(
            Email) = LOWER(@0)", email);
            if (user == null)
            {
                // Insert email into the profile table
                db.Execute("INSERT INTO UserProfile (Email) VALUES (@0)", email);

                // Create and associate a new entry in the membership database.
                // If successful, continue processing the request
                try
                {
                    bool requireEmailConfirmation = !WebMail.SmtpServer.IsEmpty()
                    ;
                    var token = WebSecurity.CreateAccount(email, password, 
                    requireEmailConfirmation);
                    if (requireEmailConfirmation)
                    {
                        var hostUrl = Request.Url.GetComponents(UriComponents.
                        SchemeAndServer, UriFormat.Unescaped);
                        var confirmationUrl = hostUrl + VirtualPathUtility.
                        ToAbsolute("~/Account/Confirm?confirmationCode=" + 
                        HttpUtility.UrlEncode(token));

                        WebMail.Send(
                            to: email,
                            subject: "Please confirm your account",
                            body: "Your confirmation code is: " + token + ". 
                            Visit <a href=\"" + confirmationUrl + "\">" + 
                            confirmationUrl + "</a> to activate your account."
                        );
                    }

                    if (requireEmailConfirmation)
                    {
                        // Thank the user for registering and let them know an 
                        email is on its way
                        Response.Redirect("~/Account/Thanks");
                    }
                    else {
                        // Navigate back to the homepage and exit
                        WebSecurity.Login(email, password);

                        Response.Redirect("~/");
                    }
                }
                catch (System.Web.Security.MembershipCreateUserException e)
                {
                    ModelState.AddFormError(e.Message);
                }
            }
            else {
                // User already exists
                ModelState.AddFormError("Email address is already in use.");
            }
        }
    }
}

<hgroup class="title">
    <h1>@Page.Title.</h1>
    <h2>Create a new account.</h2>
</hgroup>

<form method="post">
    @AntiForgery.GetHtml()
    @* If at least one validation error exists, notify the user *@
    @Html.ValidationSummary("Account creation was unsuccessful. Please correct 
    the errors and try again.", excludeFieldErrors: true, htmlAttributes: null)

    <fieldset>
        <legend>Registration Form</legend>
        <ol>
            <li class="email">
                <label for="email" @if (!ModelState.IsValidField("email")) { <
                text> class="error-label" </text>  }>Email address</label>
                <input type="text" id="email" name="email" value="@email" 
                @Validation.For("email") />
                @* Write any email validation errors to the page *@
                @Html.ValidationMessage("email")
            </li>
            <li class="password">
                <label for="password" @if (!ModelState.IsValidField("password")) 
                { <text> class="error-label" </text>  }>Password</label>
                <input type="password" id="password" name="password" @Validation.
                For("password") />
                @* Write any password validation errors to the page *@
                @Html.ValidationMessage("password")
            </li>
            <li class="confirm-password">
                <label for="confirmPassword" @if (!ModelState.IsValidField(
                "confirmPassword")) { <text> class="error-label" </text>  }>
                Confirm password</label>
                <input type="password" id="confirmPassword" 
                name="confirmPassword" @Validation.For("confirmPassword") />
                @* Write any password validation errors to the page *@
                @Html.ValidationMessage("confirmPassword")
            </li>
            <li>
                @Html.Label("Retype the code from the picture:", "CaptchaCode")
                @Html.Raw(exampleCaptcha.Html)
                @Html.TextBox("CaptchaCode")
                
            </li>
        </ol>
        <input type="submit" value="Register" />


    </fieldset>
</form>

Web.config

<?xml version="1.0" encoding="utf-8"?>

<configuration>
    <configSections>
        <section name="botDetect" requirePermission="false" 
        type="BotDetect.Configuration.BotDetectConfigurationSection, BotDetect"/>
    </configSections>
    <system.web>
        <compilation debug="true" targetFramework="4.6"/>
        <httpRuntime targetFramework="4.6"/>
        <httpHandlers>
            <!-- Register the HttpHandler used for BotDetect Captcha requests -->
            <add verb="GET" path="BotDetectCaptcha.ashx" 
            type="BotDetect.Web.CaptchaHandler, BotDetect"/>
        </httpHandlers>
        <!-- Register a custom SessionIDManager for BotDetect Captcha requests -->
        <sessionState mode="InProc" cookieless="AutoDetect" timeout="20" 
        sessionIDManagerType="BotDetect.Web.CustomSessionIdManager, BotDetect"/>
    </system.web>

    <connectionStrings>
        <add name="StarterSite" connectionString="Data 
        Source=|DataDirectory|\StarterSite.sdf" providerName="System.Data.
        SqlServerCe.4.0"/>
    </connectionStrings>

    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="DotNetOpenAuth.Core" 
                publicKeyToken="2780ccd10d57b246"/>
                <bindingRedirect oldVersion="1.0.0.0-4.1.0.0" newVersion="4.
                1.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="DotNetOpenAuth.AspNet" 
                publicKeyToken="2780ccd10d57b246"/>
                <bindingRedirect oldVersion="1.0.0.0-4.1.0.0" newVersion="4.
                1.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Optimization" 
                publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.
                1.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="WebGrease" 
                publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-1.5.2.14234.0.0" 
                newVersion="1.5.2.14234.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Helpers" 
                publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.
                0.0.0"/>
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="System.Web.WebPages" 
                publicKeyToken="31bf3856ad364e35"/>
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.
                0.0.0"/>
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    <system.data>
        <DbProviderFactories>
            <remove invariant="System.Data.SqlServerCe.4.0"/>
            <add name="Microsoft SQL Server Compact Data Provider 4.0" 
            invariant="System.Data.SqlServerCe.4.0"
                    description=".NET Framework Data Provider for Microsoft 
                    SQL Server Compact"
                    type="System.Data.SqlServerCe.SqlCeProviderFactory, 
                    System.Data.SqlServerCe, Version=4.0.0.0, 
                    Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
        </DbProviderFactories>
    </system.data>
    <system.codedom>
        <compilers>
            <compiler language="c#;cs;csharp" extension=".cs"
            type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.
            CSharpCodeProvider, Microsoft.CodeDom.Providers.
            DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, 
            PublicKeyToken=31bf3856ad364e35"
            warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;
            1699;1701"/>
            <compiler language="vb;vbs;visualbasic;vbscript" extension=".
            vb"
            type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.
            VBCodeProvider, Microsoft.CodeDom.Providers.
            DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, 
            PublicKeyToken=31bf3856ad364e35"
            warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 
            /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
        </compilers>
    </system.codedom>
    <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="BotDetectCaptcha.ashx" type="BotDetect.Web.CaptchaHandler, BotDetect"/>
        </handlers>
    </system.webServer>
    <botDetect helpLinkEnabled="true" helpLinkMode="image"/>
</configuration>