How To Add BotDetect CAPTCHA Protection to ASP.NET MVC 6 Applications

BotDetect ASP.NET Core Captcha protection can be added to your ASP.NET MVC 6 applications using the MvcCaptcha class, a BotDetect TagHelper and a custom ActionFilterAttribute implemented in the BotDetect.Web.Mvc.dll assembly.

First Time Here?

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

You can also see how BotDetect Captcha protection has been added to the starting ASP.NET MVC application by running the BotDetect Captcha ASP.NET MVC integration code examples coming with the BotDetect installation.

You can reuse the example projects source code that fits your application requirements.

CAPTCHA Integration Steps

When adding BotDetect CAPTCHA to an ASP.NET MVC 6 application:
  1. Display a Captcha challenge on the Asp.Net MVC View
  2. Check is the visitor a human in the Controller action
  3. Further Captcha customization and options

I. Display a CAPTCHA Challenge on the ASP.NET MVC View

Before protecting a Controller action in your ASP.NET MVC application with BotDetect Captcha, you should decide how to call the Captcha instance and the related textbox you will use. In this guide, we will use ExampleCaptcha and CaptchaCode. If you plan to protect multiple Controller actions within the same ASP.NET MVC application, you should take care to give each Captcha instance a different name (e.g. LoginCaptcha, RegisterCaptcha, CommentCaptcha etc.).

Add BotDetect Captcha NuGet Package

ASP.NET MVC 6 applications should reference both the base BotDetect.dll assembly and the ASP.NET MVC-specific BotDetect.Web.Mvc.dll assembly by adding package CAPTCHA.asp.net.core.on.legacy.net.frameworks via nuget.org package source. If you don't want to access Microsoft package manager, you need to set up your own offline local NuGet repository. To hosting your own NuGet feeds, please click here for more details.

Configure Your ASP.NET Application Startup

In order to make BotDetect works properly, you need to modify the Startup class which configures the request pipeline that handles all BotDetect Captcha requests made to the application.

Additionally, BotDetect Captcha ASP.NET Core validation requires ASP.NET Session midlleware – generated random Captcha codes have to be stored on the server and compared to the user input.

Open Startup.cs and update it in the way demonstrated in the following:

The ConfigureServices method

Locate the ConfigureServices method

public void ConfigureServices(IServiceCollection services)
{
  services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
  services.AddMemoryCache(); // Adds a default in-memory implementation of 
                         // IDistributedCache
  // Add framework services.
  services.AddMvc();
  services.AddSession(options =>
  {
    options.IdleTimeout = TimeSpan.FromMinutes(20);
  });
}

The Configure method

Locate the Configure method and add a call to app.UseCaptcha.

public void Configure(IApplicationBuilder app, 
IHostingEnvironment env, ILoggerFactory loggerFactory)
{
  ...
  app.UseSession();
  
  //configure BotDetectCaptcha
  app.UseCaptcha(Configuration);
  ...
}

Makes BotDetect Captcha Tag Helper available

Add @addTagHelper directive makes Tag Helpers available to the view. To expose BotDetect Captcha Tag Helper in your project, you would use the following in Views/_ViewImports.cshtml file:

@using AspNetCoreWebApplicationExample
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper "BotDetect.Web.Mvc.CaptchaTagHelper, BotDetect.Web.Mvc"

Create and Render a BotDetect.Web.Mvc.MvcCaptcha Instance

Captcha objects in ASP.NET MVC 6 applications are represented by the MvcCaptcha class, and they can be rendered using a TagHelper extension method defined in the same assembly. To use them, your View should first import the BotDetect.Web.Mvc namespace.

Then, you can add a Captcha challenge to the View by rendering a <label ⁄> tag with the Captcha instructions for the user, a <captcha mvc-captcha ⁄> tag with the name of MvcCaptcha object instance, and a <input ⁄> tag in which the user is to type the Captcha code:

@using BotDetect.Web.Mvc;

  […]

<label asp-for="CaptchaCode">Retype the code from the picture:</label>
@{ var exampleCaptcha = new MvcCaptcha("ExampleCaptcha", ViewContext.Current()) 
{ UserInputID = "CaptchaCode" }; }
<captcha mvc-captcha="exampleCaptcha" />
<div class="actions">
  <input asp-for="CaptchaCode" />
  <input type="submit" value="Validate" />
  <span asp-validation-for="CaptchaCode"></span>
  @if (ViewContext.IsPost() && ViewData.ModelState.IsValid)
  {
    <span class="correct">Correct!</span>
  }
</div>

(Option) Encapsulate MvcCaptcha Instance Creation in a Helper Class

Since the MvcCaptcha object exposes a number of Captcha properties, the code that initializes it will often grow much longer than a single line with the constructor call (as shown in the View code above).

Adding those additional lines directly to the View would add unnecessary length and complexity to View code, and mixing code that deals with different concerns (View composition and Captcha object initialization in this case) is never a good practice. It is a much better idea to separate Captcha object creation in a specialized helper class, and keep MvcCaptcha instance access in a single line of View code.

For example, if you added the following class declaration to your ASP.NET MVC application's App_Code folder:


public static class CaptchaHelper
{
    public static MvcCaptcha GetExampleCaptcha(HttpContext httpContext)
    {
        // create the control instance
        MvcCaptcha exampleCaptcha = new MvcCaptcha("ExampleCaptcha", context);

        // set up client-side processing of the Captcha code input textbox
        exampleCaptcha.UserInputID = "CaptchaCode";

        return exampleCaptcha;
    }
}

You could replace the exampleCaptcha = new MvcCaptcha("ExampleCaptcha", ViewContext.Current()) call in your View code with exampleCaptcha = CaptchaHelper.GetExampleCaptcha(ViewContext.Current()). That way, the code initializing the Captcha object can grow arbitrarily large without cluttering the View. Of course, you would also need to import your application's namespace in the View to be able to access the CaptchaHelper class.

Include the BotDetect CAPTCHA Layout StyleSheet

Since the Html markup generated by BotDetect includes a number of different elements (the Captcha image, the icons for Captcha reloading and Captcha sound playing, the Captcha help link etc.), there are some CSS declarations which need to be included for those elements to display correctly.

The best place to include CSS style declarations is in the page <head>, and since you are controlling the View markup, you know best where exactly to add them. The BotDetect layout stylesheet can be included with the following declaration:

@section header {
    <environment names="Development,Staging,Production">
        <link href="@BotDetect.Web.CaptchaUrls.Absolute.LayoutStyleSheetUrl"
              rel="stylesheet" type="text/css" />
  <⁄environment>
  }

If your View generates its own <head> section, you can add these declaration directly in View code. If you're using a Razor Layout and individual Views only generate main content, you can add them to the Razor Layout.

Even better, your layout can include a @RenderSection() – and then individual Views can add their required declarations there without affecting other Views.

Once all of these steps have been performed, the Captcha should be displayed when you open your form in a browser:

BotDetect CAPTCHA added to an ASP.NET form

If the Captcha image isn't being rendered properly, please check the BotDetect integration FAQ.

II. Check is the Visitor a Human in the Controller Action

Once the Captcha challenge is displayed on your View, the Controller code processing submissions can check if the Captcha was solved successfully and deny access to bots.

Captcha validation is encapsulated within an ActionFilterAttribute that can be added to actions accepting HtppVerbs.Post requests; the CaptchaValidation attribute just needs to be passed the names of the Captcha instance and Captcha code textbox used. ASP.NET Session state must also be enabled before Captcha validation can work.

Mark the Protected Controller Action with the CaptchaValidation Attribute

The CaptchaValidation attribute takes three parameters:

  • Captcha code textbox name
  • MvcCaptcha instance name
  • the error message that will be displayed when Captcha validation fails

//
// POST: /ExampleController/ExampleAction

[HttpPost]
[AllowAnonymous]
[CaptchaValidation("CaptchaCode", "ExampleCaptcha", "Incorrect CAPTCHA code!")]
public ActionResult ExampleAction(ExampleModel model)
{
    if (ModelState.IsValid)
    {    
    
        […]
        
        // You should call ResetCaptcha as demonstrated in the following example.
        MvcCaptcha.ResetCaptcha("ExampleCaptcha");

        […]
    

If everything has been configured correctly, the above ActionFilterAttribute will automatically add the appropriate ModelState error when Captcha validation fails, and checking ModelState validity will include the Captcha validation result.

(Option) Client-Side CAPTCHA Validation

Since the Captcha codes must be stored and checked on the server, pure client-side Captcha validation is not feasible (as explained in the BotDetect FAQ). However, it is possible to improve the usability of your form with Ajax Captcha validation.

CAPTCHA Validation Using ASP.NET MVC 5.0 Unobtrusive Validation

If you're using ASP.NET MVC 4.0 unobtrusive validation, adding the same for Captcha code fields is as simple as adding a few validation configuration rules in a JavaScript include added after the "~/bundles/jqueryval" ASP.NET MVC script bundle. An example is given in the ASP.NET MVC 5.0 Internet application Captcha example.

CAPTCHA Validation Using jQuery and JsonResult Controller Actions

Another MVC-specific way to implement Ajax Captcha validation is to combine jQuery $.getJSON Ajax requests on the client with the ASP.NET MVC Controller actions with the JsonResult return type. An example is given in the ASP.NET MVC 5.0 jQuery Ajax Captcha example.

CAPTCHA Validation Using the jQuery Validate Plugin

If you are using your own field validation functionality based on the jquery.validate.js plugin, client-side Captcha validation can be implemented using a combination of the required and remote validation rules. An example is given in the ASP.NET jQuery Validation Captcha example.

III. Further CAPTCHA Customization and Options

BotDetect ASP.NET Captcha allows detailed customization of many Captcha properties, and you can read more about them in the BotDetect Captcha configuration How To.