[SOLVED] How to add captcha in ASP.NET project

Issue

I want add captcha in login view for my ASP.NET application. The view is quite simple has only email and password text box. Now below the email and password text box I want to add captcha in my login form.

I have look into many articles about adding captcha and found Captcha in ASP.NET MVC 5 is quite simple to use but when I added it to my app.

Instead of showing captcha image it starts displaying a cross symbol.

I have checked all the configuration already there is nothing wrong with the implementation. Is there any other easiest way to add captcha in ASP.NET app ?

Solution

Below is the full implementation from one of my latest projects – it simply follows Google’s Recaptcha guidance with some additional useful code – please check the latest Google documentation for the latest updates:

Add 2 new keys in your web.config file – one for the site key and the other for the secret key – you get these values when you register your website from the Google Recaptcha portal.

  <add key="RECAPTCHA:SITE_KEY" value="Your site key that you generate from " />
  <add key="RECAPTCHA:SECRET_KEY" value="Your secret key" />

Create a public static Config class to reach your web.config key values easily as follows;

public static class Config
{
    private static NameValueCollection _appSettings;

    private static NameValueCollection AppSettings => _appSettings ?? (_appSettings = ConfigurationManager.AppSettings);

    public static string RecaptchaSiteKey => GetStringValueOrDefault("RECAPTCHA:SITE_KEY", "");

    public static string RecaptchaSecretKey => GetStringValueOrDefault("RECAPTCHA:SECRET_KEY", "");

    private static string GetStringValueOrDefault(string key, string defaultValue)
    {
        return string.IsNullOrWhiteSpace(GetStringValueFromAppSettings(key))
                ? defaultValue
                : GetStringValueFromAppSettings(key);
    }

    private static string GetStringValueFromAppSettings(string key)
    {
        return string.IsNullOrEmpty(AppSettings[key]) ? string.Empty : AppSettings[key];
    }
}

Add the g-recaptcha section to your view, i.e.

        if (ViewData.ModelState.Keys.Contains("OverallError"))
        {
            <div class="form__row">
                @Html.ValidationMessage("OverallError", new { @class = "form__error" }).Raw()
            </div>
        }
        <div class="form__row">
            <div class="form__controls">
                <div class="g-recaptcha"
                     data-sitekey="@YourProject.Config.RecaptchaSiteKey"
                     data-callback="reCaptchaResponse">
                </div>
                @Html.HiddenFor(m => m.RecaptchaToken)
            </div>
        </div>
        <div class="form__row form__row--final">
            <div class="form__controls">
                <button type="submit" class="button button--primary" id="createAccountSubmit">Create account</button>
            </div>
        </div>

Script section on the same view;

@section Scripts {
    <script>
        $(document).ready(function () {
            createAccountSubmit.disabled = true;
        });

        var createAccountSubmit = document.getElementById("createAccountSubmit");

        function reCaptchaResponse(token) {
            $('#RecaptchaToken').val(token);
            createAccountSubmit.disabled = false;
        }
    </script>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
}

Add RecaptchaToken to your viewmodel;

 public string RecaptchaToken { get; set; }

And here is your post action and how you can validate your recapcha token and add some custom validation errors:

    if (ModelState.IsValid)
    {
        if (!await model.RecaptchaToken.ValidateAsRecapchaToken())
        {
            ModelState.AddModelError("OverallError", "CAPTCHA validation failed. Please try again.");
        }

        // Always clear the token as it is no longer valid. Any subsequent re-posts will need a new token.
        ModelState.SetModelValue(nameof(model.RecaptchaToken), new ValueProviderResult("", "", CultureInfo.InvariantCulture));
    }

StringExtension to validate the recapcha token:

 public static class StringExtensions
    {
       public static async Task<bool> ValidateAsRecapchaToken(this string token)
        {
            using (var client = new HttpClient())
            {
                var secret = Config.RecaptchaSecretKey;
                var url = $"https://www.google.com/recaptcha/api/siteverify?secret={secret}&response={token}";
                var response = await client.PostAsync(url, new StringContent(""));
                var responseModel = await response.Content.ReadAsAsync<RecaptchaResponseModel>();

                return responseModel.Success;
            }
        }
    }

This is how things look like:

enter image description here

Answered By – Nurhak Kaya

Answer Checked By – Robin (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *