In Focus

Integrate Google ReCaptcha And Validate It With ASP.NET MVC 5 And Entity Framework

In this Article, I will demonstrate how to integrate Google ReCaptcha and Validate it with ASP.Net MVC5.

Introduction
 
In this article, I will demonstrate how to integrate Google Recaptcha and Validate it with ASP.Net MVC5. After going through with this article you may get the benefit of this rich feature. In this modern world, many of the hackers, robotics, and spam are available so we need to ensure the user is a human and not a bot or a computer. Okay! let's move forward. 
 
Prerequisite 
  • Visual Studio
  • SQL Server
  • Google Account(Gmail Id)
  • Basic knowledge of ASP.NET MVC
Article Flow 
  • Use of Captcha and ReCaptcha?
  • Create ASP.Net MVC Application
  • Register Site(s)/Domain(s) and Generate Key's in Google
  • Integrate Google ReCaptcha with Application
  • Validate Google ReCaptcha
 Use of Captcha and ReCaptcha?
 
A CAPTCHA is a challenge-response system wherein typically a dynamically generated image consisting of random letters and numbers is displayed to the users and the users are asked to re-enter the text in an attempt to verify that both of them match. CAPTCHA stands for "Completely Automated Public Turing Test to Tell Computers and Humans Apart ".
 
reCAPTCHA is a free service that protects your site from spam and abuse. It uses advanced risk analysis techniques to tell humans and bots apart. With the new API, a significant number of your valid human users will pass the reCAPTCHA challenge without having to solve a CAPTCHA. reCAPTCHA comes in the form of a widget that you can easily add to your blog, forum, registration form, etc.
 
Create ASP.Net MVC Application
 
One of my articles discussed how to do the Scaffolding process with ASP.Net MVC5 and Entity Framework Implements scaffolding with Entity Framework   Once you followed those steps just copy a content folder which contains predefined CSS file from another new ASP.Net Web Application because we have created the empty project. Once you followed those steps it will gives you the following screen
 
 
 
And the result as below
 


Register Site(s)/Domain(s) and Generate Key's in Google
 
The initial step to integrate Google reCaptcha is to register your site/domain to receive public/private keys. To reach that level merely click here. As soon as you hit the preceding given URL it gives you given the following screen

 
I have registered mine as the following screenshot
 
 

I am running my ASP.Net MVC application in localhost so I have mentioned to register it with localhost. After successful registration, it will provide this ReCaptcha feature to your localhost and provides public/private keys along with a reference file and API to use further.
 
 
We got enough things and completed everything on google. Now move to the Application
 
Integrate Google ReCaptcha with Application
 
To integrate Google ReCaptcha with an application, follow the below steps one by one.
 
Step 1 Add public and private key in web.config
 
Kindly paste your public and private key in the web.config file as shown in the following screen
  1. <add key="recaptchaPublickey" value="6LdHcTwUAAAAAIFoGNGSjl_daxhYsQUWVV9PKWWW"/>  
  2. lt;add key="recaptchaPrivatekey" value="6LdHcTwUAAAAAD_al4p9Zp7qMDvyZy6cCXW51hKEr"/>  
 
 
Step 2 Refer ReCaptcha API Js 
 
Here I referred a Javascript file to shared layout page
  1. <script src='https://www.google.com/recaptcha/api.js'></script>   
Step 3 Add ReCaptcha widget to view 
 
Now add the Google ReCaptcha widget to your view, here I added to create.cshtml view
  1. <div class="g-recaptcha" data-sitekey="6LdHcTwUAAAAAIFoGNGSjl_daxhYsQUWVV9PKWWW"></div>   
Now run your application, you can see that we got the Google ReCaptcha widget in our application.
 
 
 
 Validate Google ReCaptcha
 
Verify that the user response as reCAPTCHA is generated and resolved by a user. The following API URL is used to verify the user response. To validate captcha include following method in your controller
  1. /// <summary>  
  2. /// Validate Captcha  
  3. /// </summary>  
  4. /// <param name="response"></param>  
  5. /// <returns></returns>  
  6. public static CaptchaResponse ValidateCaptcha(string response)  
  7. {  
  8.     string secret = System.Web.Configuration.WebConfigurationManager.AppSettings["recaptchaPrivateKey"];  
  9.     var client = new WebClient();  
  10.     var jsonResult = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, response));  
  11.     return JsonConvert.DeserializeObject < CaptchaResponse > (jsonResult.ToString());  
  12. }  
The following API URL is used to verify the user response. It will return two type of parameter in JSON result. A result such as success,error-codes for that I have created a model class which holds two property to hold the response. success parameter returns true if  captcha is valid else returns false. error-codes parameter returns a list of error.
  1. using Newtonsoft.Json;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Linq;  
  5. using System.Web;  
  6. namespace GoogleReCaptchaInMVC5.Models {  
  7.     public class CaptchaResponse {  
  8.         [JsonProperty("success")]  
  9.         public bool Success {  
  10.             get;  
  11.             set;  
  12.         }  
  13.         [JsonProperty("error-codes")]  
  14.         public List < string > ErrorMessage {  
  15.             get;  
  16.             set;  
  17.         }  
  18.     }  
  19. }  
To Deserialize JSON result we need to use the Newtonsoft.Json, to get clear picture visit JSON Serialization And Deserialization In C# ,  to get a server-side response we need to use the 'g-recaptcha-response' in controller request. The below method will be the post action to create an employee. Before creating employee we validating the captcha with the help of ValidateCaptcha method.
  1. [HttpPost]  
  2. [ValidateAntiForgeryToken]  
  3. public ActionResult Create([Bind(Include = "ID,Name,Designation,Location")] Employee employee) {  
  4.     CaptchaResponse response = ValidateCaptcha(Request["g-recaptcha-response"]);  
  5.     if (response.Success && ModelState.IsValid) {  
  6.         db.Employees.Add(employee);  
  7.         db.SaveChanges();  
  8.         return RedirectToAction("Index");  
  9.     } else {  
  10.         return Content("Error From Google ReCaptcha : " + response.ErrorMessage[0].ToString());  
  11.     }  
  12. }  
Run your application, As you can see from the image below it has returned “true” in success parameter from the server meaning it worked perfectly.After executing successfully it returns to the employee list page again with added employee "Ramar A". I've used this page for demonstration purposes only.
 
 
 
Now we will go with important negative scenario
 
Scenario 1: Invalid Private Key 
 
for that, I just made a wrong private key in web config as below
  1. <add key="recaptchaPrivatekey" value="6LdHcTwUAAAAAD_al4p9Zp7q"/>   
 
 
Now run your application
 
 
 
Scenario 2 Invalid User or robot
 
If you don't check the checkbox prefix to the message “I'm not a robot” and press Enter. It goes to the code and verifies the authenticity and it returns false. It means you are not a valid user.

 
 
Complete Web.config 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!--  
  3. For more information on how to configure your ASP.NET application, please visit  
  4. http://go.microsoft.com/fwlink/?LinkId=301880  
  5. -->  
  6. <configuration>  
  7.     <configSections>  
  8.         <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->  
  9.         <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections>  
  10.     <appSettings>  
  11.         <add key="webpages:Version" value="3.0.0.0" />  
  12.         <add key="webpages:Enabled" value="false" />  
  13.         <add key="ClientValidationEnabled" value="true" />  
  14.         <add key="UnobtrusiveJavaScriptEnabled" value="true" />  
  15.         <add key="recaptchaPublickey" value="6LdHcTwUAAAAAIFoGNGSjl_daxhYsQUWVV9PKWWW" />  
  16.         <add key="recaptchaPrivatekey" value="6LdHcTwUAAAAAD_al4p9Zp7qMDvyZy6cCXW51hKE" />  
  17.         <!--<add key="recaptchaPrivatekey" value="6LdHcTwUAAAAAD_al4p9Zp7q"/>-->  
  18.     </appSettings>  
  19.     <system.web>  
  20.         <compilation debug="true" targetFramework="4.5" />  
  21.         <httpRuntime targetFramework="4.5" /> </system.web>  
  22.     <connectionStrings>  
  23.         <add name="CSharpCornerEntities" connectionString="metadata=res://*/Models.Model1.csdl|res://*/Models.Model1.ssdl|res://*/Models.Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=CSharpCorner;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /> </connectionStrings>  
  24.     <entityFramework>  
  25.         <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />  
  26.         <providers>  
  27.             <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers>  
  28.     </entityFramework>  
  29. </configuration>  
Complete Controller
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Data;  
  4. using System.Data.Entity;  
  5. using System.Linq;  
  6. using System.Net;  
  7. using System.Web;  
  8. using System.Web.Mvc;  
  9. using GoogleReCaptchaInMVC5.Models;  
  10. using Newtonsoft.Json;  
  11. namespace GoogleReCaptchaInMVC5.Controllers {  
  12.     public class CRUDController: Controller {  
  13.         private CSharpCornerEntities db = new CSharpCornerEntities();  
  14.         // GET: /CRUD/  
  15.         public ActionResult Index() {  
  16.             return View(db.Employees.ToList());  
  17.         }  
  18.         // GET: /CRUD/Details/5  
  19.         public ActionResult Details(long ? id) {  
  20.             if (id == null) {  
  21.                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);  
  22.             }  
  23.             Employee employee = db.Employees.Find(id);  
  24.             if (employee == null) {  
  25.                 return HttpNotFound();  
  26.             }  
  27.             return View(employee);  
  28.         }  
  29.         // GET: /CRUD/Create  
  30.         public ActionResult Create() {  
  31.             return View();  
  32.         }  
  33.         // POST: /CRUD/Create  
  34.         // To protect from overposting attacks, please enable the specific properties you want to bind to, for  
  35.         // more details see http://go.microsoft.com/fwlink/?LinkId=317598.  
  36.         [HttpPost]  
  37.         [ValidateAntiForgeryToken]  
  38.         public ActionResult Create([Bind(Include = "ID,Name,Designation,Location")] Employee employee) {  
  39.             CaptchaResponse response = ValidateCaptcha(Request["g-recaptcha-response"]);  
  40.             if (response.Success && ModelState.IsValid) {  
  41.                 db.Employees.Add(employee);  
  42.                 db.SaveChanges();  
  43.                 return RedirectToAction("Index");  
  44.             } else {  
  45.                 return Content("Error From Google ReCaptcha : " + response.ErrorMessage[0].ToString());  
  46.             }  
  47.         }  
  48.         /// <summary>  
  49.         /// Validate Captcha  
  50.         /// </summary>  
  51.         /// <param name="response"></param>  
  52.         /// <returns></returns>  
  53.         public static CaptchaResponse ValidateCaptcha(string response) {  
  54.             string secret = System.Web.Configuration.WebConfigurationManager.AppSettings["recaptchaPrivateKey"];  
  55.             var client = new WebClient();  
  56.             var jsonResult = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secret, response));  
  57.             return JsonConvert.DeserializeObject < CaptchaResponse > (jsonResult.ToString());  
  58.         }  
  59.         // GET: /CRUD/Edit/5  
  60.         public ActionResult Edit(long ? id) {  
  61.             if (id == null) {  
  62.                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);  
  63.             }  
  64.             Employee employee = db.Employees.Find(id);  
  65.             if (employee == null) {  
  66.                 return HttpNotFound();  
  67.             }  
  68.             return View(employee);  
  69.         }  
  70.         // POST: /CRUD/Edit/5  
  71.         // To protect from overposting attacks, please enable the specific properties you want to bind to, for  
  72.         // more details see http://go.microsoft.com/fwlink/?LinkId=317598.  
  73.         [HttpPost]  
  74.         [ValidateAntiForgeryToken]  
  75.         public ActionResult Edit([Bind(Include = "ID,Name,Designation,Location")] Employee employee) {  
  76.             if (ModelState.IsValid) {  
  77.                 db.Entry(employee).State = EntityState.Modified;  
  78.                 db.SaveChanges();  
  79.                 return RedirectToAction("Index");  
  80.             }  
  81.             return View(employee);  
  82.         }  
  83.         // GET: /CRUD/Delete/5  
  84.         public ActionResult Delete(long ? id) {  
  85.             if (id == null) {  
  86.                 return new HttpStatusCodeResult(HttpStatusCode.BadRequest);  
  87.             }  
  88.             Employee employee = db.Employees.Find(id);  
  89.             if (employee == null) {  
  90.                 return HttpNotFound();  
  91.             }  
  92.             return View(employee);  
  93.         }  
  94.         // POST: /CRUD/Delete/5  
  95.         [HttpPost, ActionName("Delete")]  
  96.         [ValidateAntiForgeryToken]  
  97.         public ActionResult DeleteConfirmed(long id) {  
  98.             Employee employee = db.Employees.Find(id);  
  99.             db.Employees.Remove(employee);  
  100.             db.SaveChanges();  
  101.             return RedirectToAction("Index");  
  102.         }  
  103.         protected override void Dispose(bool disposing) {  
  104.             if (disposing) {  
  105.                 db.Dispose();  
  106.             }  
  107.             base.Dispose(disposing);  
  108.         }  
  109.     }  
  110. }  
Complete View (Create.cshtml) 
  1. @model GoogleReCaptchaInMVC5.Models.Employee  
  2. @ {  
  3.     ViewBag.Title = "Create";  
  4. } < h2 > Create < /h2>  
  5. @using(Html.BeginForm()) {  
  6.     @Html.AntiForgeryToken() < div class = "form-horizontal" > < h4 > Employee < /h4> < hr / > @Html.ValidationSummary(true) < div class = "form-group" > @Html.LabelFor(model => model.Name, new {  
  7.         @class = "control-label col-md-2"  
  8.     }) < div class = "col-md-10" > @Html.EditorFor(model => model.Name)  
  9.     @Html.ValidationMessageFor(model => model.Name) < /div> < /div> < div class = "form-group" > @Html.LabelFor(model => model.Designation, new {  
  10.         @class = "control-label col-md-2"  
  11.     }) < div class = "col-md-10" > @Html.EditorFor(model => model.Designation)  
  12.     @Html.ValidationMessageFor(model => model.Designation) < /div> < /div> < div class = "form-group" > @Html.LabelFor(model => model.Location, new {  
  13.         @class = "control-label col-md-2"  
  14.     }) < div class = "col-md-10" > @Html.EditorFor(model => model.Location)  
  15.     @Html.ValidationMessageFor(model => model.Location) < /div> < /div> < div class = "form-group" > < div class = "g-recaptcha"  
  16.     data - sitekey = "6LdHcTwUAAAAAIFoGNGSjl_daxhYsQUWVV9PKWWW" > < /div> < /div> < div class = "form-group" > < div class = "col-md-offset-2 col-md-10" > < input type = "submit"  
  17.     value = "Create"  
  18.     class = "btn btn-default" / > < /div> < /div> < /div>  
  19. } < div > @Html.ActionLink("Back to List""Index") < /div> < script src = "~/Scripts/jquery-1.10.2.min.js" > < /script> < script src = "~/Scripts/jquery.validate.min.js" > < /script> < script src = "~/Scripts/jquery.validate.unobtrusive.min.js" > < /script>  
_Layout.cshtml 
  1. <!DOCTYPE html>  
  2. <html>  
  3.   
  4. <head>  
  5.     <meta charset="utf-8" />  
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0">  
  7.     <title>@ViewBag.Title - Google ReCaptcha</title>  
  8.     <link href="~/Content/Site.css" rel="stylesheet" type="text/css" />  
  9.     <link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />  
  10.     <script src='https://www.google.com/recaptcha/api.js'></script>  
  11. </head>  
  12.   
  13. <body>  
  14.     <div class="navbar navbar-inverse navbar-fixed-top">  
  15.         <div class="container">  
  16.             <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">  
  17. <span class="icon-bar"></span>  
  18. <span class="icon-bar"></span>  
  19. <span class="icon-bar"></span>  
  20. </button> @Html.ActionLink("Google ReCaptcha with ASP.Net MVC5""Index""Home"nullnew { @class = "navbar-brand" }) </div>  
  21.             <div class="navbar-collapse collapse">  
  22.                 <ul class="nav navbar-nav"> </ul>  
  23.             </div>  
  24.         </div>  
  25.     </div>  
  26.     <div class="container body-content"> <br /> @RenderBody()  
  27.         <hr /> </div>  
  28. </body>  
  29.   
  30. </html>  
Refer the attached project for reference and I did attach the demonstrated project without package for Entity Framework 6.0 due to the size limit.

Summary 
 
In this Article, you learnt how to integrate Google ReCaptcha and validate it with ASP.Net MVC5 Web Application. 
 
I hope it will help you out. Your valuable feedback and comments about this article are always welcome.