ASP.NET MVC 5 Application Template CAPTCHA C# Code Example

The ASP.NET MVC 5 application template Captcha C# Razor example project shows how to use the BotDetect CAPTCHA MvcSimpleCaptcha control in ASP.NET MVC 5.0 C# web applications.

First Time Here?

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

Starting with the default ASP.NET MVC 5 Web Application Visual Studio 2015 / 2013 project template (File > New Project > Installed > Templates > Visual C# > Web > ASP.NET Web Application > MVC), the example includes all code required to add CAPTCHA validation to the Account controller Register action (Views\Account\Register.cshtml and Controllers\AccountController.cs).

The example also shows how to complement server-side CAPTCHA validation with client-side Ajax CAPTCHA validation using ASP.NET MVC 5 unobtrusive validation (based on jQuery) applied to all form fields (Scripts\captcha.validate.js).

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

→ ASP.NET MVC version:

→ .NET programming language:

Installed Location

By default, the .NET 4.5 C# Razor version of the ASP.NET MVC 5 Captcha Simple API example project is installed at:
C:\Program Files\Captcha Inc\BotDetect 4 CAPTCHA Component\Asp.Net\.NET\WebApp\ SimpleAPI\Mvc50ApplicationTemplateCaptchaExample\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 AspNetMvc50CaptchaExampleCSharp.Models.RegisterViewModel

@* namespaces needed to access BotDetect members*@
@using BotDetect.Web.Mvc;
@using AspNetMvc50CaptchaExampleCSharp.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()

    <div class="form-group">
      @Html.LabelFor(m => m.UserName, new { @class = "col-md-4 control-label" })
      <div class="col-md-8">
        @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
      </div>
    </div>

    <div class="form-group">
      @Html.LabelFor(m => m.Password, new { @class = "col-md-4 control-label" })
      <div class="col-md-8">
        @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
      </div>
    </div>
    <div class="form-group">
      @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-4 control-label" })
      <div class="col-md-8">
        @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-4 col-md-8">
          @Html.SimpleCaptcha(registrationCaptcha)
        </div>
        @Html.Label("Retype the code", new { @class = "col-md-4 control-label", 
        @for = "CaptchaCode" })
        <div class="col-md-8">
          @Html.TextBox("CaptchaCode", null, new { @class = "form-control captchaVal" })
        </div>
      </div>
    <div class="form-group" id="form-submit">
      <div class="col-md-offset-4 col-md-8">
        <input type="submit" class="btn btn-default" value="Register" />
      </div>
    </div>
  </div>
}
@section Scripts {
  @Scripts.Render("~/bundles/jqueryval")
  @Scripts.Render("~/Scripts/captcha.validate.js")
}

To display Captcha protection on the Register View, we first ensure we can use BotDetect members and the application code by using the relevant namespaces.

When we have the registrationCaptcha object, displaying the Captcha is as easy as calling the Html.SimpleCaptcha() helper with it as a parameter.

We also add a Html.Label() and a Html.TextBox() to complete the SimpleCaptcha elements on the form; note that the textbox has it's CSS class set to captchaVal – we'll use this class to dynamically add unobtrusive jQuery validation of the user's Captcha input.

The client-side SimpleCaptcha validation rules are defined in a JavaScript file called captcha.validate.js, which we include in the ScriptsSection content placeholder after all other jQuery validation scripts in the jqueryval bundle.

Controllers\AccountController.cs

using System;
using System.Collections.Generic;
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.EntityFramework;
using Microsoft.Owin.Security;
using AspNetMvc50CaptchaExampleCSharp.Models;

using BotDetect.Web.Mvc;

namespace AspNetMvc50CaptchaExampleCSharp.Controllers
{
  [Authorize]
  public class AccountController : Controller
  {
    []

    //
    // 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.UserName };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
          await SignInAsync(user, isPersistent: false);

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

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

    []
  }
}

Above we're showing only the part of AccountController code tied to SimpleCaptcha validation functionality, since that's what we're interested in.

After we've included the BotDetect.Web.Mvc namespace, we just need to add the SimpleCaptchaValidation attribute to the method processing Register 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 Register form),
  2. the ID of the SimpleCaptcha instance we're validating (which we set to RegistrationCaptcha in the file botdetect.xml
  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 Register form is submitted, and will automatically add a Model error with the error message configured above when SimpleCaptcha validation fails. So we don't need to check the Captcha validation status separately from the validation status of Model fields – checking if (ModelState.IsValid) is enough.

Scripts\captcha.validate.js

(function () {
  $.validator.setDefaults({
    // only validate fields when the form is submitted:
    // the SimpleCaptcha input must only be validated when the whole code string is
    // typed in, not after each individual character (onkeyup must be false);
    // onfocusout validation could be left on in more complex forms, but 
    // doesn't fit this example
    onkeyup: false,
    onfocusout: false,
    // always reload the Captcha image if remote validation failed,
    // since it will not be usable any more (a failed validation attempt
    // removes the attempted code for necessary SimpleCaptcha security
    showErrors: function (errorMap, errorList) {
      for (var i = 0; i < errorList.length; i++) {
        var element = errorList[i].element;
        var message = errorList[i].message;
        // check element css class and does the error message match remote
        // validation failure
        if (element.className.match(/captchaVal/) &&
            message === this.settings.messages[element.id].remote) {
          BotDetect.getInstanceByStyleName("RegisterCaptcha").reloadImage();
          $("form").valid();
        }
      }
    }
  });
})();


$(document).ready(function () {
  // add validation rules by CSS class, so we don't have to know the
  // exact client id of the Captcha code textbox
  $(".captchaVal").rules('add', {
    required: true,
    remote: BotDetect.getInstanceByStyleName("RegisterCaptcha").validationUrl,
    messages: {
      required: "Your input doesn't match displayed characters",
      remote: "Incorrect code, please try again"
    }
  });
});

Since ASP.NET MVC unobtrusive validation is based on the jquery.validate.js jQuery plugin, we add Captcha code textbox client-side validation by extending the validator settings as defined in its API.

We use the CSS class we gave the Captcha code textbox (captchaVal) to add validation rules making the Captcha code both a required field, and one validated remotely. Since secure Captcha validation can only be performed on the server, we make a validation Ajax request to the validation Url exposed by the client-side SimpleCaptcha object.

Furthermore, since each random Captcha code can only be attempted once for security reasons, we have to reload the Captcha image whenever Ajax Captcha validation fails (or it would be showing the user a code that cannot be validated anymore, making them always fail the validation even when they retype the Captcha code correctly). We do this in the validator showErrors() function, after we checked there is a remote SimpleCaptcha validation error.

For the same reason, the remote Captcha validation only needs to happen when the user has finished retyping the whole Captcha code, and must not trigger after each individual character has been typed. We achieve this by setting the validator onkeyup setting to false.

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 AspNetMvc50CaptchaExampleCSharp
{
  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 = "Account", action = "Register", 
          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=301880
  -->
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.
    EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, 
    PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
    <!-- For more information on Entity Framework configuration, visit http://go.
    microsoft.com/fwlink/?LinkID=237468 -->
  </configSections>
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;
    AttachDbFilename=|DataDirectory|\aspnet-AspNetMvc50CaptchaExampleCSharp-
    20140225103220.mdf;Initial Catalog=aspnet-AspNetMvc50CaptchaExampleCSharp-
    20140225103220;Integrated Security=True" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0"/>
    <add key="webpages:Enabled" value="false"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
  <system.web>
  <authentication mode="None"/>
  <compilation debug="false" targetFramework="4.5.1"/>
  <httpRuntime targetFramework="4.5.1"/>
  <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="FormsAuthenticationModule"/>
  </modules>
  <handlers>
    <!-- register HttpHandler used for BotDetect Simple API requests -->
    <remove name="BotDetectCaptchaHandler"/>
    <add name="BotDetectCaptchaHandler" preCondition="integratedMode" verb="GET" 
    path="BotDetectCaptcha.ashx" type="BotDetect.Web.SimpleCaptchaHandler, BotDetect"/>
  </handlers>
  </system.webServer>
  <runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
    <assemblyIdentity name="System.Web.Helpers" 
    publicKeyToken="31bf3856ad364e35"/>
    <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0"/>
    </dependentAssembly>
    <dependentAssembly>
    <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
    <bindingRedirect oldVersion="1.0.0.0-5.1.0.0" newVersion="5.1.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="WebGrease" publicKeyToken="31bf3856ad364e35"/>
    <bindingRedirect oldVersion="1.0.0.0-1.0.0.0" newVersion="1.0.0.0"/>
    </dependentAssembly>
  </assemblyBinding>
  </runtime>
  <entityFramework>
  <defaultConnectionFactory 
    type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
    <parameters>
    <parameter value="v11.0"/>
    </parameters>
  </defaultConnectionFactory>
  <providers>
    <provider invariantName="System.Data.SqlClient" 
    type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
  </providers>
  </entityFramework>
 </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 .