Reputation: 67195
I've used reCAPTCHA many times in my WebForms applications. Now I'd like to add it to an ASP.NET MVC application.
I found what appears to be some good code in RecaptchaControlMvc but, incredibly, I haven't been able to find a single paragraph or example on how to use this control.
I've posted in the Google reCAPTCHA group but it's dead.
Can anyone point me to an example that uses this control, a paragraph about how to use it, or suggest an alternative?
Note: I know there are similar questions on stackoverflow, but none that I've found discuss how to use this control.
Upvotes: 1
Views: 8523
Reputation: 11
This is How I do it with ASP.Net MVC and ReCaptcha 3.
<appSettings>
<add key="reCaptchaSiteKey" value="site_key" />
<add key="reCaptchaSecretKey" value="secret_key" />
</appSettings>
namespace ASPNetMVCWithReCaptcha3.Models
{
public class ReCaptchaForm
{
public string Message { get; set; }
}
}
using System;
using System.Web;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Net.Http;
using System.Configuration;
namespace ASPNetMVCWithReCaptcha3.Classes
{
}
Add the following lines inside the namespace
public static class GoogleReCaptchaVariables
{
public static string ReCaptchaSiteKey = ConfigurationManager.AppSettings["reCaptchaSiteKey"]?.ToString() ?? string.Empty;
public static string ReCaptchaSecretKey = ConfigurationManager.AppSettings["reCaptchaSecretKey"]?.ToString() ?? string.Empty;
public static string InputName = "g-recaptcha-response";
}
public static class ReCaptchaHelper
{
public static IHtmlString ReCaptchaHidden(this HtmlHelper helper)
{
var mvcHtmlString = new TagBuilder("input")
{
Attributes =
{
new KeyValuePair<string, string>("type", "hidden"),
new KeyValuePair<string, string>
("id", GoogleReCaptchaVariables.InputName),
new KeyValuePair<string, string>
("name", GoogleReCaptchaVariables.InputName)
}
};
string renderedReCaptchaInput =
mvcHtmlString.ToString(TagRenderMode.Normal);
return MvcHtmlString.Create($"{renderedReCaptchaInput}");
}
public static IHtmlString ReCaptchaJS
(this HtmlHelper helper, string useCase = "homepage")
{
string reCaptchaSiteKey = GoogleReCaptchaVariables.ReCaptchaSiteKey;
string reCaptchaApiScript = "<script
src='https://www.google.com/recaptcha/api.js?render=" +
reCaptchaSiteKey + "'></script>;";
string reCaptchaTokenResponseScript = "<script>
$('form').submit(function(e) { e.preventDefault();
grecaptcha.ready(function() { grecaptcha.execute('" +
reCaptchaSiteKey + "', {action: '" + useCase +
"'}).then(function(token) { $('#" +
GoogleReCaptchaVariables.InputName + "').val(token);
$('form').unbind('submit').submit(); }); }); }); </script>;";
return MvcHtmlString.Create
($"{reCaptchaApiScript}{reCaptchaTokenResponseScript}");
}
}
public static IHtmlString ReCaptchaValidationMessage
(this HtmlHelper helper, string errorText = null)
{
var invalidReCaptchaObj =
helper.ViewContext.Controller.TempData["InvalidCaptcha"];
var invalidReCaptcha = invalidReCaptchaObj?.ToString();
if (string.IsNullOrWhiteSpace(invalidReCaptcha))
return MvcHtmlString.Create("");
var buttonTag = new TagBuilder("span")
{
Attributes = {
new KeyValuePair<string, string>("class", "text-danger")
},
InnerHtml = errorText ?? invalidReCaptcha
};
return MvcHtmlString.Create(buttonTag.ToString(TagRenderMode.Normal));
}
public class ValidateReCaptchaAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string reCaptchaToken =
filterContext.HttpContext.Request.Form[GoogleReCaptchaVariables.InputName];
string reCaptchaResponse = ReCaptchaVerify(reCaptchaToken);
ResponseToken response = new ResponseToken();
if (reCaptchaResponse != null)
{
response = Newtonsoft.Json.JsonConvert.DeserializeObject
(reCaptchaResponse);
}
if (!response.Success)
{
AddErrorAndRedirectToGetAction(filterContext);
}
base.OnActionExecuting(filterContext);
}
public string ReCaptchaVerify(string responseToken)
{
const string apiAddress =
"https://www.google.com/recaptcha/api/siteverify";
string recaptchaSecretKey = GoogleReCaptchaVariables.ReCaptchaSecretKey;
string urlToPost = $"{apiAddress}
?secret={recaptchaSecretKey}&response={responseToken}";
string responseString = null;
using (var httpClient = new HttpClient())
{
try
{
responseString = httpClient.GetStringAsync(urlToPost).Result;
}
catch
{
//Todo: Error handling process goes here
}
}
return responseString;
}
private static void AddErrorAndRedirectToGetAction
(ActionExecutingContext filterContext, string message = null)
{
filterContext.Controller.TempData["InvalidCaptcha"] =
message ?? "Invalid Captcha! The form cannot be submitted.";
filterContext.Result =
new RedirectToRouteResult(filterContext.RouteData.Values);
}
internal class ResponseToken
{
public bool Success { get; set; }
public float Score { get; set; }
public string Action { get; set; }
public DateTime Challenge_TS { get; set; }
public string HostName { get; set; }
public List ErrorCodes { get; set; }
}
}
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateReCaptcha]
public ActionResult Index(ReCaptchaForm form)
{
return View(form);
}
@model ASPNetMVCWithReCaptcha3.Models.ReCaptchaForm
@using ASPNetMVCWithReCaptcha3.Classes;
@{
ViewBag.Title = "ReCaptcha Form";
}
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.LabelFor(model => model.Message)
@Html.TextAreaFor(model => model.Message, new { @class = "form-control" })
@Html.ReCaptchaValidationMessage()
@Html.ReCaptchaHidden()
@Html.ReCaptchaJS()
<button type="submit" class="btn btn-primary">Send Message</button>
}
Upvotes: 1
Reputation: 435
I can provide you an easy alternative method to use google recaptcha. Here you can find the complete reference about Google new reCAPTCHA using asp.net mvc
First all of you need to Sign up & Generate Google reCAPTCHA API. Go to http://www.google.com/recaptcha then click on the top right corner Get reCAPTCHA button
Second, Write html code in your view. Here replace text "Your sitekey here"
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
@using (Html.BeginForm("FormSubmit", "Home", FormMethod.Post))
{
<div class="g-recaptcha" data-sitekey="Your sitekey here"></div>
<input type="submit" value="Submit" />
}
</div>
<span style="display:inline-block; font-size:20px;margin:20px 0;padding:20px;border:1px solid #D3D3D3">
@ViewBag.Message
</span>
<script src='https://www.google.com/recaptcha/api.js' type="text/javascript"></script>
3rd and last, Write action code for validate google reCaptcha
[HttpPost]
public ActionResult FormSubmit()
{
//Validate Google recaptcha here
var response = Request["g-recaptcha-response"];
string secretKey = "Your secret here";
var client = new WebClient();
var result = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&response={1}", secretKey, response));
var obj = JObject.Parse(result);
var status = (bool)obj.SelectToken("success");
ViewBag.Message = status ? "Google reCaptcha validation success" : "Google reCaptcha validation failed";
//When you will post form for save data, you should check both the model validation and google recaptcha validation
//EX.
/* if (ModelState.IsValid && status)
{
}*/
//Here I am returning to Index page for demo perpose, you can use your view here
return View("Index");
}
Upvotes: 1
Reputation: 2907
Some code here
You add the attribute like this:
[CaptchaValidator]
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult SubmitForm( Int32 id, bool captchaValid )
{
.. Do something here
}
You render the captcha in your view:
<%= Html.GenerateCaptcha() %>
which is something like this:
public static string GenerateCaptcha( this HtmlHelper helper )
{
var captchaControl = new Recaptcha.RecaptchaControl
{
ID = "recaptcha",
Theme = "blackglass",
PublicKey = -- Put Public Key Here --,
PrivateKey = -- Put Private Key Here --
};
var htmlWriter = new HtmlTextWriter( new StringWriter() );
captchaControl.RenderControl(htmlWriter);
return htmlWriter.InnerWriter.ToString();
}
Upvotes: 2