Reputation: 505
I'm having troubles adding google reCAPTCHA to my page. in the Layout I have added the Google Recaptcha js
_layout
<title>@ViewBag.Title</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
<script src='https://www.google.com/recaptcha/api.js'></script>
<script type="text/javascript">
<script type="text/javascript">
$(document).ready(function () {
$('#subject').on("change", function (e) {
e.preventDefault();
var selectedVal = $('#subject').val();
$.ajax({
// url: "/ContactUs/GetForm",
url: '@Url.Action("GetForm", "ContactUs")',
type: "POST",
data: { searchValue: selectedVal } ,
async: true,
success: function (data) {
$('#renderForms').empty();
$('#renderForms').append(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("An error has occured!!! " + xhr.status + " && " + xhr.responseText);
}
});
});
});
</script>
then in my index I select which form I want to show:
@Html.DropDownListFor(model => model.contactSelectListItems, new List<SelectListItem>
{
new SelectListItem() {Text = "option1", Value="option1"},
new SelectListItem() {Text = "option2", Value="option2"},
new SelectListItem() {Text = "option3", Value="option3"},
}, "--Choose--", new { id = "subject", @class= "dropdown-item" })
</div>
<div id="renderForms">
</div>
in both partial page there is a form where I do something similiar yet different viewmodels:
@using (Html.BeginForm("SendCustomerTeam", "ContactUs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>CustomerTeamViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="container">
<div class="form-group form-group-sm col-sm-6">
<div class="row">
@Html.LabelFor(model => model.Phone, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-sm-9">
@Html.EditorFor(model => model.Phone, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Phone, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-12">
<div class="row">
@Html.LabelFor(model => model.Inquiry, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-sm-12">
@Html.EditorFor(model => model.Inquiry, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Inquiry, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-12">
<div class="row">
<div class="col-sm-12">
<div id="NotRobot">
<label>Are you Human?</label>
<div id='recaptcha' class="col-sm-12 g-recaptcha"
data-sitekey="@System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"]"
>
</div>
<div id="recaptchaMessage" data-verifyrecaptchatokenurl="@Url.Action("VerifyReCaptchaToken", "Home")" style="display:none;padding:10px;color:red;font-weight:bold;" class="error">You need to verify reCAPTCHA.</div>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-6">
<div class="row">
<div class="col-sm-9">
<input id="Send" type="submit" value="Send" class="btn btn-default" />
</div>
</div>
</div> etc...
In my controller I handle it like this thou I would like to handle the reCAPTCHA as an ajax call I have yet to figure out how to do that.
public ActionResult Index()
{
ViewData["ReCaptchaKey"] = System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"];
//do something here
}
public static bool ReCaptchaPassed(string gRecaptchaResponse, string secret)
{
HttpClient httpClient = new HttpClient();
var res = httpClient.GetAsync($"https://www.google.com/recaptcha/api/siteverify?secret={secret}&response={gRecaptchaResponse}").Result;
if (res.StatusCode != HttpStatusCode.OK)
{
//logger.LogError("Error while sending request to ReCaptcha");
return false;
}
string JSONres = res.Content.ReadAsStringAsync().Result;
dynamic JSONdata = JObject.Parse(JSONres);
if (JSONdata.success != "true")
{
return false;
}
return true;
}
[HttpPost]
public ActionResult SendCustomerTeam(CustomerTeamViewModel model)
{
ContactViewModel contactModel = new ContactViewModel();
contactModel.CustomerTeamModel = model;
ViewData["ReCaptchaKey"] = System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"];
if (ModelState.IsValid)
{
if (!ReCaptchaPassed(
Request.Form["g-recaptcha-response"], // that's how you get it from the Request object
System.Configuration.ConfigurationManager.AppSettings["RecaptchaPrivateKey"]
))
{
ModelState.AddModelError(string.Empty, "You failed the CAPTCHA, stupid robot. Go play some 1x1 on SFs instead.");
return View(contactModel);
}
}
My problem is the reCAPTCHA never appears on my page.
Edit:
I've tried the following simplification to see if I could find the issue.
SimplePageViewModel
public class simplePageViewModel
{
public string Name { get; set; }
}
SimplePagePartialView
@model Contact_Portal.Models.simplePageViewModel
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>simplePageViewModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="container">
<div class="row">
<div class="form-group form-group-sm col-sm-6">
<div class="row">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-sm-9">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
</div>
<div class="form-group form-group-sm col-sm-12">
<div class="row">
<div class="col-sm-12">
<div id="NotRobot">
<label>Are you Human?</label>
<div id='recaptcha' class="col-sm-12 g-recaptcha" style="padding:10px;"
data-sitekey="@System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"]">
</div>
<div id="recaptchaMessage" data-verifyrecaptchatokenurl="@Url.Action("VerifyReCaptchaToken", "Home")" style="display:none;padding:10px;color:red;font-weight:bold;" class="error">You need to verify reCAPTCHA.</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
in the controller I get the partial view shown through this line
return PartialView("View", contactModel.simplePageModel);
Still the same problem persist.
Could it be because I'm displaying my partial page containing the reCAPTCHA as part of an Jquery Ajax call ? like this:
$(document).ready(function () {
$('#subject').on("change", function (e) {
e.preventDefault();
var selectedVal = $('#subject').val();
$.ajax({
// url: "/ContactUs/GetForm",
url: '@Url.Action("GetForm", "ContactUs")',
type: "POST",
data: { searchValue: selectedVal } ,
async: true,
success: function (data) {
$('#renderForms').empty();
$('#renderForms').append(data);
},
error: function (xhr, ajaxOptions, thrownError) {
alert("An error has occured!!! " + xhr.status + " && " + xhr.responseText);
}
});
});
I've now tried a entire new project where I've simplified it all the way down to one html file:
Index.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
<link href="~/Content/bootstrap.min.css" rel="stylesheet" type="text/css" />
<script src="~/Scripts/modernizr-2.6.2.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
</ul>
</div>
</div>
</div>
<div class="container body-content">
<div id='recaptcha' class="col-sm-12 g-recaptcha" style="padding:10px;"
data-sitekey="@System.Configuration.ConfigurationManager.AppSettings["RecaptchaPublicKey"]"></div>
<hr />
<footer>
<p>© @DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
</body>
</html>
Still it is not visible it never appears. why is it not working ? could it be that ASP.NET MVC is not supported by Recaptcha from google?
Upvotes: 1
Views: 1755
Reputation: 505
Well I found a solution I'm not happy with it but it works.
in my Layout file I've made a section like this:
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
<script type="text/javascript">
function enableBtn() {
document.getElementById("subject").disabled = false;
}
$(document).ready(function () {
document.getElementById("subject").disabled = true;
});
</script>
Then in my view I created this
<div class="g-recaptcha" data-sitekey="*********PublicKEY*************" data-callback="enableBtn"></div>
And it seems to be working.
I wish I could make it work in the partial view because now I have to have it no matter what else will happen and not just on a submit.
I don't know if I can verify this one server side anymore as it is also outside my form. ? Anyone with a better option would be welcomed.
EDIT:
I found a better solution for me. I changed my ajax call like this:
$('#subject').on("change", function (e) {
e.preventDefault();
var selectedVal = $('#subject').val();
$.ajax({
// url: "/ContactUs/GetForm",
url: '@Url.Action("GetForm", "ContactUs")',
type: "POST",
data: { searchValue: selectedVal } ,
async: true,
success: function (data) {
$('#renderForms').empty();
$('#renderForms').append(data);
if (!debug) {
document.getElementById("Send").disabled = true;
grecaptcha.render('Captcha', {
'sitekey': '**********PublicKey*********',
'callback': function() {
document.getElementById("Send").disabled = false;
},
'expired-callback': function() {
//document.getElementById("subject").selectedIndex = 0;
document.getElementById("Send").disabled = true;
//document.getElementById("renderForms").innerHTML = "";
}
});
}
},
error: function (xhr, ajaxOptions, thrownError) {
alert("An error has occured!!! " + xhr.status + " && " + xhr.responseText);
}
});
});
Now it is working as I intended. At least in the user interface part.
Upvotes: 0
Reputation: 5383
Your script src is wrong:
<script src='https://www.google.com/recaptcha/api.js async defer'></script>
to
<script src='https://www.google.com/recaptcha/api.js'></script>
Also could you check deveoper console, if there any error?
Upvotes: 2