ASP.NET MVC Single Page Application CAPTCHA C# Code Example

The ASP.NET MVC Single Page Application Captcha Simple API C# example project shows the most basic source code required to protect an ASP.NET MVC form with BotDetect CAPTCHA and validate the user input.

First Time Here?

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

ASP.NET MVC View code displaying CAPTCHA protection can be found in Views/Account/Register.cshtml, and the ASP.NET MVC Controller code checking user input is in Controllers/AccountController.cs.

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

→ .NET programming language:

Installed Location

By default, the .NET C# version of the ASP.NET MVC Single Page Application Captcha Simple API example project is installed at:
C:\Program Files\Captcha Inc\BotDetect 4 CAPTCHA Component\ Asp.Net\.NET\WebApp\SimpleAPI\MvcSinglePageApplicationExample\CSharp

You can also run it from the BotDetect Start Menu:
Programs > Captcha Inc > BotDetect 4 CAPTCHA Component > ASP.NET > ASP.NET Examples > Run .NET Examples

Views\Account\Register.cshtml

@model CSharp.Models.RegisterViewModel

@* namespaces needed to access BotDetect members*@
@using BotDetect.Web.Mvc;
@using AspNetMvc523SinglePageApplicationExampleCSharp.App_Code;

@{
    ViewBag.Title = "Register";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = 
"form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    <div class="col-md-6" id="form-container">
        @Html.ValidationSummary("", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" 
            })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Hometown, new { @class = "col-md-2 control-
            label" })
            <div class="col-md-10">
                @Html.TextBoxFor(m => m.Hometown, new { @class = "form-control" }
                )
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-
            label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.Password, new { @class = "form-control" 
                })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 
            control-label" })
            <div class="col-md-10">
                @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-
                control" })
            </div>
        </div>
        @* showing Captcha on the form:
            add SimpleCaptcha validation controls to the protected action View*@

        @{MvcSimpleCaptcha registrationCaptcha = New MvcSimpleCaptcha("RegistrationCaptcha")
        ; }
            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                    @Html.SimpleCaptcha(registrationCaptcha)
                </div>
                @Html.Label("Retype the code", new { @class = "col-md-2 control-
                label", @for = "CaptchaCode" })
                <div class="col-md-10">
                    @Html.TextBox("CaptchaCode", null, new { @class = "form-
                    control captchaVal" })
                </div>
            </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" class="btn btn-default" value="Register" />
            </div>
        </div>
    </div>

            }

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

To display Captcha protection on the example View, we first ensure we can use BotDetect members by Import-ing the relevant namespaces.

We then create a MvcSimpleCaptcha instance, and add it to the form by calling the Html.SimpleCaptcha() Html helper with it.

In this simplest case, we also use the Html.ValidationMessage helper to display Captcha validation errors.

Controllers\AccountController.cs

using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using CSharp.Models;
using BotDetect.Web.Mvc;
namespace CSharp.Controllers
{
    [Authorize]
    public class AccountController : Controller
    {
        private ApplicationSignInManager _signInManager;
        private ApplicationUserManager _userManager;

        public AccountController()
        {
        }

        public AccountController(ApplicationUserManager userManager, 
        ApplicationSignInManager signInManager)
        {
            UserManager = userManager;
            SignInManager = signInManager;
        }
        
        [..]

        //
        // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        [SimpleCaptchaValidation("CaptchaCode", "RegistrationCaptcha", "Incorrect 
        CAPTCHA Code!")]
        public async Task<ActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser { UserName = model.Email, Email = 
                model.Email, Hometown = model.Hometown };
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
                    await SignInManager.SignInAsync(user, isPersistent: false, 
                    rememberBrowser: false);

                    // For more information on how to enable account 
                    confirmation and password reset please visit http://go.
                    microsoft.com/fwlink/?LinkID=320771
                    // Send an email with this link
                    // string code = await UserManager.
                    GenerateEmailConfirmationTokenAsync(user.Id);
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", 
                    new { userId = user.Id, code = code }, protocol: Request.Url.
                    Scheme);
                    // await UserManager.SendEmailAsync(user.Id, "Confirm your 
                    account", "Please confirm your account by clicking <a 
                    href=\"" + callbackUrl + "\">here</a>");

                    return RedirectToAction("Index", "Home");
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
        
        [..]

        
    }
}

After we've included the BotDetect.Web.Mvc namespace, we just need to add the SimpleCaptchaValidation attribute to the method processing form submissions. The attribute takes three parameters:

  1. the ID of the textbox containing the user's Captcha code input (which we named CaptchaCode on the form),
  2. the ID of the SimpleCaptcha instance we're validating (which we set to ExampleCaptcha in the MvcSimpleCaptcha constructor), and
  3. the error message to be shown when SimpleCaptcha validation fails.

When the SimpleCaptcha validation action filter attribute has been added, the SimpleCaptcha validation will trigger every time the form is submitted, and will automatically add a Model error with the error message configured above when SimpleCaptcha validation fails. The Html.ValidationMessage helper on the form will then display this error when SimpleCaptcha validation fails.

App_Start\RouteConfig.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace AspNetMvc50BasicCaptchaExampleCSharp
{
  public class RouteConfig
  {
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      // BotDetect requests must not be routed
      routes.IgnoreRoute("{*botdetect}", 
      new { botdetect = @"(.*)BotDetectCaptcha\.ashx" });

      routes.MapRoute(
          name: "Default",
          url: "{controller}/{action}/{id}",
          defaults: new { controller = "Example", action = "Index", 
          id = UrlParameter.Optional }
      );
    }
  }
}

We configure ASP.NET Routing to ignore BotDetect requests, since they do not conform to any MVC-related patterns. The regex defining requests to ignore must match the path configured for the BotDetect HttpHandler registered in web.config.

Web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please 
  visit
  http://go.microsoft.com/fwlink/?LinkId=301879
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.
    microsoft.com/fwlink/?LinkID=237468 -->
    <httpHandlers>
      <!-- register HttpHandler used for BotDetect Simple API requests -->
      <add verb="GET" path="BotDetectCaptcha.ashx" 
      type="BotDetect.Web.SimpleCaptchaHandler, BotDetect"/>
    </httpHandlers>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <remove name="FormsAuthentication" />
    </modules>
    <handlers>
      <!-- Register the HttpHandler used for BotDetect Simple API requests (IIS 7.0+) -->
      <remove name="BotDetectCaptchaHandler"/>
      <add name="BotDetectCaptchaHandler" preCondition="integratedMode"
      verb="GET" path="BotDetectCaptcha.ashx" 
      type="BotDetect.Web.SimpleCaptchaHandler, BotDetect"/>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" 
      type="System.Web.Handlers.TransferRequestHandler" 
      preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" 
        publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.OAuth" 
        publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.Cookies" 
        publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" 
        publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" culture="neutral" 
        publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.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" newVersion="1.5.2.
        14234" />
      </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>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" 
        publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
 </configuration>

To allow the application to use BotDetect Captcha protection, we must register the BotDetect HttpHandler in both <system.web><httpHandlers> and <system.webServer><handlers> configuration sections.

The <dependentAssembly> entry for System.Web.Mvc is also needed to make all ASP.NET MVC dependencies referenced by the BotDetect MVC assembly point to the correct ASP.NET MVC version.

botdetect.xml

<?xml version="1.0" encoding="UTF-8"?>
<botdetect xmlns="https://captcha.com/schema/net" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://captcha.com/schema/net 
      https://captcha.com/schema/net/botdetect-4.4.0.xsd">

  <captchaStyles>
    <captchaStyle>
      <name>RegistrationCaptcha</name>
      <userInputID>CaptchaCode</userInputID>
      <codeLength>3-5</codeLength>
    </captchaStyle>
  </captchaStyles>

</botdetect>

In botdetect.xml, we configure captcha options for the RegistrationCaptcha captcha style name. You can find a full list of available Captcha configuration options and related instructions at the Captcha configuration options page .