Home » ASP » ASP.MVC » How to add ReCaptcha to your Asp.Net MVC4 register form.

How to add ReCaptcha to your Asp.Net MVC4 register form.

To prevent bot (automatic program that act like a human without being a real one) to register account to your website, you can use what we can captcha. Captcha is image that only human can read. They have letters that need to be input in a text box when the form is filled up. Today, I’ll show you how to implement ReCaptcha, a popular Captcha service that is totally free and owned by Google.

The first step is to register a API key for your website. You can go to http://www.google.com/recaptcha and create a new one. I suggest you to not check the check box of “Enable this key on all domains” to be able to debug with localhost. So, after this step, you will have a private and public key that will be required to use the ReCaptcha service.

The second step is to have library to access ReCaptcha. Inside your project, add the two following NuGet Package. One is the Recaptcha API service and the other one will give you Html helper.

The third step is to configure your project with the public and private key. This can be done by adding 2 appsettings in the web.config.

  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />

    <add key="RecaptchaPrivateKey" value="123nI9cSAAAAALtUefffnLRn2pWb7IpNrtOGQjzz" />
    <add key="RecaptchaPublicKey" value="123nI9cSAAAAAOH3eee3t1ZaZ6rRUwHQK4KMimfu" />
  </appSettings>

The forth step is to let know every page about the new library by adding the name space into the system.web configuration of the web.config.

  <system.web>
    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
        <add namespace="Recaptcha" />
      </namespaces>
    </pages>

The fifth step is to add the control to the register form.

<li>
     @Html.Raw(Html.GenerateCaptcha())
     @Html.ValidationMessage("recaptcha")
</li>

The last step is to check if everything is fine from the controller side. This will be validated when the user will submit the form to the server.

[RecaptchaControlMvc.CaptchaValidator]
public ActionResult Register(RegisterModel model, bool captchaValid, string captchaErrorMessage)
{
    if (ModelState.IsValid)
    {
        if (!captchaValid)
        {
            ModelState.AddModelError("recaptcha", captchaErrorMessage);
            return View(model);
        }
//...

You need first to add the attribute that will call the server and do the validation. Second, you need to add 2 variables to the action that will tell you if the captcha is valid and the message. You can then check the value and display the form again if it’s wrong.

Nothing has to be done when developing into localhost (or 127.0.0.1) because ReCaptcha service allow developer to use for any key the localhost domain.

Behind the library

The first section was enough to let you implement ReCaptcha with your Asp.Net MVC 4 website. Now, let check a little bit the code behind the library. First, the html helper. This helper, create an instance of RecaptchaControl with the id “recaptcha”.

public static string GenerateCaptcha(this HtmlHelper helper)
{
  return RecaptchaControlMvc.GenerateCaptcha(helper, "recaptcha", "default");
}

public static string GenerateCaptcha(this HtmlHelper helper, string id, string theme)
{
  if (string.IsNullOrEmpty(RecaptchaControlMvc.publicKey) || string.IsNullOrEmpty(RecaptchaControlMvc.privateKey))
	throw new ApplicationException("reCAPTCHA needs to be configured with a public & private key.");
  RecaptchaControl recaptchaControl1 = new RecaptchaControl();
  recaptchaControl1.ID = id;
  recaptchaControl1.Theme = theme;
  recaptchaControl1.PublicKey = RecaptchaControlMvc.publicKey;
  recaptchaControl1.PrivateKey = RecaptchaControlMvc.privateKey;
  RecaptchaControl recaptchaControl2 = recaptchaControl1;
  HtmlTextWriter writer = new HtmlTextWriter((TextWriter) new StringWriter());
  recaptchaControl2.RenderControl(writer);
  return writer.InnerWriter.ToString();
}

This is quite interesting because when you validate your recaptcha you may want to add the error message next to it.

From the same code, we can see that the public and private key come from RecaptchaControlMvc… Those are two static string that get their value from the application setting of the web config file.

  public static class RecaptchaControlMvc
  {
    private static string publicKey = ConfigurationManager.AppSettings["RecaptchaPublicKey"];
    private static string privateKey = ConfigurationManager.AppSettings["RecaptchaPrivateKey"];

So far, nothing very hard to understand and we have two answers concerning the name of the control generated and the name of the setting used for the web.config.

The last interesting part is concerning the filter that we had to add to the action to validate the input of the user. This one is straight forward. It uses the RecaptchaValidator class to access the service and get a response from the ReCaptcha service. It then add the validation answer to the parameter. We have now our third answer concerning what are the parameter to add to the action.

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
	RecaptchaValidator recaptchaValidator = new RecaptchaValidator();
	recaptchaValidator.PrivateKey = RecaptchaControlMvc.PrivateKey;
	recaptchaValidator.RemoteIP = filterContext.HttpContext.Request.UserHostAddress;
	recaptchaValidator.Challenge = filterContext.HttpContext.Request.Form["recaptcha_challenge_field"];
	recaptchaValidator.Response = filterContext.HttpContext.Request.Form["recaptcha_response_field"];
	this.recaptchaResponse = !string.IsNullOrEmpty(recaptchaValidator.Challenge) ? (!string.IsNullOrEmpty(recaptchaValidator.Response) ? recaptchaValidator.Validate() : RecaptchaResponse.InvalidResponse) : RecaptchaResponse.InvalidChallenge;
	filterContext.ActionParameters["captchaValid"] = (object) (bool) (this.recaptchaResponse.IsValid ? 1 : 0);
	filterContext.ActionParameters["captchaErrorMessage"] = (object) this.recaptchaResponse.ErrorMessage;
	base.OnActionExecuting(filterContext);
  }

So that’s it for using a captcha to the register form of an Asp.Net MVC 4 application.

If you like my article, think to buy my annual book, professionally edited by a proofreader. directly from me or on Amazon.

29 Responses so far.

  1. Overmachine says:

    If i want to use this plugin to render the Captcha after some attempts, what would be the approach? i mean i can use a variable to render the captcha in the view but the controller still require the captcha validation

  2. In your Html Helper, why do you create a recaptcha control and then create second and assign the first control to the second? Why not render the first?

    • Hi Boxer, I may misunderstand your but the creation is done once. It’s done inside the View with this statement : @Html.Raw(Html.GenerateCaptcha())

      All other code inside this article is the code inside the library that you get already coded for you inside the Nuget package.

      If I do not answer your concern correctly, feel free to give me more detail and I’ll do my best to answer it.

  3. nugget says:

    Hey Patrick,

    I’m trying to use the above in an MVC WebAPI project but the controller method is not matched when I include the [RecaptchaControlMvc.CaptchaValidator] annotation and the “bool captchaValid, string captchaErrorMessage” params.

    If I remove them, the form is submitted ok.

    Do you have any ideas what the issue might be?

    Cheers!

    • nugget says:

      It seems that WebAPI doesn’t allow other params mixed with the model. I tried implementing a custom Parameter Binding class but still had no luck. I ended up downloading the source and added the recaptcha params to my form model and moved the validation logic to my controller.

      • Baseball says:

        I had the same problem. It was fixed when I put [HttpPost] above the controller method like this..

        [HttpPost]
        [RecaptchaControlMvc.CaptchaValidator]
        public ActionResult Register(RegisterModel model, bool captchaValid, string captchaErrorMessage)
        {
        if (ModelState.IsValid)
        {
        ……………

  4. kiiran says:

    Working fine…Thanks a million!

  5. EPF says:

    Thanks for great tutorial, its hard to find easy recaptcha tutorial for mvc 4.0 🙂

  6. test says:

    It is truly a nice and useful piece of information. I am satisfied that you simply shared this helpful info with us.
    Please keep us informed like this. Thanks for sharing.

  7. […] i have implemented it with the help of How to add ReCaptcha to your Asp.Net MVC4 register form […]

  8. Jason says:

    I am getting the following error when i run the register page

    Compiler Error Message: CS1061: ‘System.Web.Mvc.HtmlHelper’ does not contain a definition for ‘GenerateCaptcha’ and no extension method ‘GenerateCaptcha’ accepting a first argument of type ‘System.Web.Mvc.HtmlHelper’ could be found (are you missing a using directive or an assembly reference?)

    Source Error:

    Line 29:
    Line 30:
    Line 31: @Html.Raw(Html.GenerateCaptcha())
    Line 32: @Html.ValidationMessage(“recaptcha”)
    Line 33:

    What could I have missed. My project compiles without any error. Thanks for helping in advance

  9. Hi,

    I can get the Recaptcha and work as expected (i.e. pass or fail validation), however when the user enters the incorrect text for the captcha the page no longer shows the captcha, just the error message.

    Any suggestions would be gratefully received.

    Kind regards,
    Derek.

  10. Hi.
    I want to use Recaptcha in Ajax.BeginForm element. But I insert incorrect text for the captcha and submit the form only the error message is shown and the captcha is gown. What could be the reson?

  11. Gert du Plessis says:

    Hi Patrick

    Hope you are well. I have a problem that I can’t seem to validate. I get a time-out exception after exactly 30 seconds. Here is the stack-trace:

    System.Net.WebException: The operation has timed out at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context) at System.Net.HttpWebRequest.GetRequestStream() at Recaptcha.RecaptchaValidator.Validate() at Recaptcha.RecaptchaControlMvc.CaptchaValidatorAttribute.OnActionExecuting(ActionExecutingContext filterContext) at System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) at System.Web.Mvc.Async.AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(IActionFilter filter, ActionExecutingContext preContext, Func`1 nextInChain) at System.Web.Mvc.Async.AsyncControllerActionInvoker.c__DisplayClass37.b__31(AsyncCallback asyncCallback, Object asyncState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate`1 endDelegate, Object tag) at System.Web.Mvc.Async.AsyncControllerActionInvoker.c__DisplayClass25.b__1e(AsyncCallback asyncCallback, Object asyncState).

    Any advise is highly appreciated!

    Gert

  12. dev4 says:

    how can i use in multiple partial view in single page????

    i have used this.

    First Partial view

    @Html.Raw(Html.GenerateCaptcha(“recaptcha1″,”default”))
    @Html.ValidationMessage(“recaptcha”)

    Second Partial View

    @Html.Raw(Html.GenerateCaptcha(“recaptcha2″,”default”))
    @Html.ValidationMessage(“recaptcha”)

    but it does not appear in second only first have come up.

  13. maru says:

    hi… i am using this code but “RecaptchaControlMvc” missing assembly reference ..also add recaptcha extension…

  14. coolest guy says:

    Pretty! This was an extremely wonderful article. Many thanks for supplying
    this information.

  15. m88 says:

    I think that everything typed was actually very reasonable.
    However, consider this, what if you added a little
    content? I am not saying your content is not good, however suppose you added
    a title that makes people want more? I mean How to add ReCaptcha to your Asp.Net
    MVC4 register form. | Patrick Desjardins’ Blog is a little plain. You should peek at Yahoo’s front page and
    watch how they create article headlines to grab people to click.
    You might try adding a video or a related picture or two
    to grab readers excited about everything’ve got to say.
    Just my opinion, it might bring your posts a
    little livelier.

  16. Nisha says:

    Hi
    i have added the nuget package for CAPTCHA .

    I am getting the following error when i run the register page

    Compiler Error Message: CS1061: ‘System.Web.Mvc.HtmlHelper’ does not contain a definition for ‘GenerateCaptcha’ and no extension method ‘GenerateCaptcha’ accepting a first argument of type ‘System.Web.Mvc.HtmlHelper’ could be found (are you missing a using directive or an assembly reference?)

    Source Error:

    @Html.Raw(Html.GenerateCaptcha())
    @Html.ValidationMessage(“recaptcha”)

    What could I have missed. My project compiles without any error. Thanks for helping in advance

  17. Lorna says:

    Hello there, I believe your site could possibly be having browser compatibility issues.
    Whenever I take a look at yojr website in Safari, it looks fine however, if olening in I.E., it’s got some
    overlapping issues. I simply wanted to give you a quiuck heads up!
    Besides that, wonderful website!

  18. Gajendra says:

    I am not getting any response from recaptcha
    when i store the response of captcha in a variable it getting null in web api controller.
    var response = HttpContext.Request.Form[“g-recaptcha-response”];

    Also I have written the [HTTPPOST] above the controller method

    what should i do .Please help me

  19. Nostalrius says:

    Awesome article. I read your posts all the time and you
    always do a good job articulating the whatever topic you’re writing about.
    Btw, I shared this on Twitter and my followers loved it.
    Keep up the great work!

Leave a Reply

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