Adding Captcha To Mvc C# Project

I was tasked to add a captcha to a webpage on a solution that I have written in C#. Most people have written excellent simple step by step guides for how to add Captcha using reCaptcha, where you register on the site the domain that you need to add captcha to.

However what happens like in my situation where your solution is used to host many website domains and more are added every day? Such dynamic sites are not handled as well by googles recaptcha as it works off a public and private key for each domain.

I did however find this useful guide which I have broken down into my own step by step guide here.

Any faults, errors, bugs, flaws etc you find please feel free to let me know or make the edit to this guide as I appreciate that times change, technologies develop and guides can become outdated.

Create Captcha Controller Class

First you will need to add in a captcha controller to your project. In this section of code you will be able to perform all the necessary validation, generation of the captcha, and all the logic behind the captcha goes in here.

/// <summary>
    /// This class is fully self-contained. All Captcha related code including
    /// handling of session veriables, hashing, validation etc. is located here.
    /// In order to use this class include the following image tag somwhere in
    /// your view, e.g. in the view handling the registration process:
    /// <img src='/Captcha/Show' alt="" />
    /// </summary>
    public class CaptchaController : Controller
        public JsonResult ValidateCaptcha(string CaptchaValue)
            bool b = IsValidCaptchaValue(CaptchaValue.ToUpper());
            if (!b) return Json(string.Empty, JsonRequestBehavior.AllowGet);
            else return Json(true, JsonRequestBehavior.AllowGet);
        public JsonResult ValidateInvisibleCaptcha(string CaptchaValue)
            bool b = CaptchaValue == "";
            if (!b) return Json(string.Empty, JsonRequestBehavior.AllowGet);
            else return Json(true, JsonRequestBehavior.AllowGet);

        private const int height = 30;
        private const int width = 80;
        private const int length = 4;
        private const string chars = "ABCDEFGHIJKLMNPQRSTUVWXYZ1234567890()$!*";

        public ActionResult Show()
            var randomText = GenerateRandomText(length);
            var hash = ComputeMd5Hash(randomText + GetSalt());
            Session["CaptchaHash"] = hash;

            var rnd = new Random();
            var fonts = new[] { "Verdana", "Times New Roman" };
            float orientationAngle = rnd.Next(0, 359);
            var index0 = rnd.Next(0, fonts.Length);
            var familyName = fonts[index0];

            using (var bmpOut = new Bitmap(width, height))
                var g = Graphics.FromImage(bmpOut);
                var gradientBrush = new LinearGradientBrush(new Rectangle(0, 0, width, height),
                                                            Color.DarkGray, Color.DarkGray,
                g.FillRectangle(gradientBrush, 0, 0, width, height);
                DrawRandomLines(ref g, width, height);
                g.DrawString(randomText, new Font(familyName, 18), new SolidBrush(Color.Gray), 0, 2);
                var ms = new MemoryStream();
                bmpOut.Save(ms, ImageFormat.Png);
                var bmpBytes = ms.GetBuffer();

                return new FileContentResult(bmpBytes, "image/png");

        public static bool IsValidCaptchaValue(string captchaValue)
            var expectedHash = System.Web.HttpContext.Current.Session["CaptchaHash"];
            var toCheck = captchaValue + GetSalt();
            var hash = ComputeMd5Hash(toCheck);
            return hash.Equals(expectedHash);

        private static void DrawRandomLines(ref Graphics g, int width, int height)
            var rnd = new Random();
            var pen = new Pen(Color.Gray);
            for (var i = 0; i < 10; i++)
                g.DrawLine(pen, rnd.Next(0, width), rnd.Next(0, height),
                                rnd.Next(0, width), rnd.Next(0, height));

        private static string GetSalt()
            return typeof(CaptchaController).Assembly.FullName;

        private static string ComputeMd5Hash(string input)
            var encoding = new ASCIIEncoding();
            var bytes = encoding.GetBytes(input);
            HashAlgorithm md5Hasher = MD5.Create();
            return BitConverter.ToString(md5Hasher.ComputeHash(bytes));

        private static string GenerateRandomText(int textLength)
            var random = new Random();
            var result = new string(Enumerable.Repeat(chars, textLength)
                  .Select(s => s[random.Next(s.Length)]).ToArray());
            return result;

Now that your controller is all setup correctly, you will want to add the captcha image to your webpage.

Adding Captcha Image To Web Page

Now as you can see from the comments at the top of the Captcha controller you can add in the captcha image on any page by including the line

 <img src='/Captcha/Show' alt="Captcha" /><br />

If you want to add a “refresh” button on the captcha then add the captcha to the page in the following way

<a href="#" onClick="window.location.reload();return false;"><img src='/Captcha/Show' alt="Captcha" /> Reload</a>

With the image added, you will need a text box to be filled by the user of the site and a lable and a button for submitting and validating the Cpatcha.

This can be easily added by using the following code:

<img src='/Captcha/Show' alt="Captcha" />
   <div class="editor-label">
       <p style ="font-weight:bold "> Please prove you are a human (NOTE this is case sensitive)</p>
   <div class="editor-field">
      @Html.TextBoxFor(m => m.CaptchaValue)
      @Html.ValidationMessageFor(m => m.CaptchaValue)

In order for the above to work you will need to add a Property “CapthcaValue” to the model that is passed onto the page where your captcha is appearing. I had a model passed across already so was able to add this property to the model and it now gets populated when the captcha box is filled.

public string CaptchaValue { get; set; }

All the rest happens behind the scenes and is completely handled by the class CaptchaController. So what follows is a description of the implementation.

When the CaptchaController renders an image it also creates a cryptographic hash as a session variable. This hash is an MD5 value in my implementation and the calculation uses an additional value to add some ‘salt’ before calculating the MD5 hash. Since the client has no access to the server side code it won’t be able to calculate a matching pair of MD5 and CAPTCHA value. As ‘salt’ I use the assembly’s full name which changes with each compile as it includes the version number.

computing how_to

QR Code
QR Code adding_captcha_to_mvc_csharp_project (generated for current page)