How to keep reCaptcha on screen after failed input - asp.net-mvc

I have an asp.net MVC site with a bootstrap modal that has a reCaptcha form on it. It correctly validates the input upon submit, but if it's not valid, upon rendering the view so they can try again, the captcha disappears and the javascript console shows this error: "Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened." I have to refresh the page and reopen the modal to see the Captcha again.
Snippet of code containing the Captcha (public/private keys are in web.config):
<input type="hidden" name="ProductID" value="#Model.ProductID" />
<input type="hidden" name="UserTypeID" value="#Model.User.UserTypeID" />
#Html.Recaptcha(theme: Recaptcha.Web.RecaptchaTheme.Clean)
<div id="request-error-summary">
#Html.ValidationSummary(false, "All fields are required.")
</div>
Controller code upon submitting form:
public PartialViewResult SubmitRequest(RequestKitModel kitModel)
{
/* code removed for brevity */
RecaptchaVerificationHelper recaptchaHelper = this.GetRecaptchaVerificationHelper();
if (String.IsNullOrEmpty(recaptchaHelper.Response))
{
ModelState.AddModelError("", "Captcha answer cannot be empty.");
return PartialView("_Request", kitModel);
}
RecaptchaVerificationResult recaptchaResult = recaptchaHelper.VerifyRecaptchaResponse();
if (recaptchaResult != RecaptchaVerificationResult.Success)
{
ModelState.AddModelError("", "Incorrect captcha answer.");
return PartialView("_Request", kitModel);
}
/* code to ruun upon success of captcha input */
//close modal and return to results
return PartialView("_Confirmation");
}
Jquery Ajax call to SubmitRequest... I think the way I'm loading the partial view may be the culprit.
if ($('#request-form').valid()) {
$.ajax({
url: "/SubmitRequest",
type: "POST",
data: $("#request-form").serialize(),
success: function (data) {
//show the confirmation (thanks) modal
$("#request-modal .modal-content").html(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
window.location.href = '#Url.Action("Error")';
}
});
}
UPDATE: I changed it to use recaptcha_ajax.js since I am loading it after an ajax request. Now I get this error: "cannot set property 'innerhtml' of null" from the recaptcha_ajax.js file (cannot tell which object it's throwing this error on). Instead of calling Html.Recaptcha in the razor file, I now have this:
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
<div id="recaptcha1"></div>
And the updated AJAX call:
$.ajax({
url: "/SubmitRequest",
type: "POST",
data: $("#request-form").serialize(),
success: function (data) {
//show the confirmation (thanks) modal
$("#request-modal .modal-content").html(data);
Recaptcha.create("6LedL_sSAAAAAJuozIfRiVfNOCHs-jlTn6NM4c-T",
"recaptcha1",
{
theme: "white",
callback: Recaptcha.focus_response_field
}
);
console.log("done loading html");
console.log('captcha control: ' + $("#recaptcha1").length);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
window.location.href = '#Url.Action("Error")';
}
});

Try and put the javascript reference
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
in your main layout, I got the same error you did because the javascript library wasn't fully loaded.
You should also check that the div exists in the callback.
I hope this helps,
Salvador

Related

How can I debug mvc ajax calls effectively using the error function?

I am quite new to MVC, I had a function that I wrote to override the default event on a submit button and I would update a partial view based on the submit form. It was working great. Then it just stopped working. The only thing I've changed is that I've added a few webshim things for a datepicker (IE 9). I tried commenting this out and nothing. I placed an error function in the ajax call, and sure enough, the call is failing for some reason. Below is my ajax call:
<script>
$(document).ready(function () {
$("#DropDownForm").on("submit", function (event) {
//Prevent default action on the drop down submit form
event.preventDefault();
var form = $(this);
var Project = $('#ProjectDropDown').val();
var Release = $('#ReleaseDropDown').val();
//Instead run this function - find Release and update table
$.ajax({
url: form.attr("action"),
//async: false,
method: form.attr("method"),
data: form.serialize(),
error: function (exception) { alert(exception + "\n" + form.serialize() + "\n" + form.attr("action") + "\n" + form.attr("method")) }
})
.done(function (result) {
$("#ReleaseTableBodyForm").empty();
$("#ReleaseTableBodyForm").html(result +
'<br/><div><button style=\"text-align:center\">Submit</button></div>');
});
});
});
</script>
The form it is referencing:
#using (Html.BeginForm("LoadRelease", "Home", FormMethod.Post, new { id = "DropDownForm", style = "" }))
{
#*Dropdowns*#
<select id="BusinessAreaDropDown" name="BusinessArea" onchange="javascript: FillGenericProject(); FillProject(); FillReleases();" style="width: 11em;">
#Html.Partial(#"Dropdowns\_BusinessArea", Model.ProjectViewModels);
</select>
<select id="GenericProjectDropDown" name="GenericProject" onchange="javascript: FillProject(); FillReleases();" style="width: 11em;"></select>
<select id="ProjectDropDown" name="Project" style="width: 18em;" onchange="javascript: FillReleases();"></select>
<select id="ReleaseDropDown" name="Release" style="width: 11em;"></select>
<button type="submit" id="GoButton" style="visibility:hidden;">Go</button>
}
And the controller that it was calling very happily until recently (In HomeController.cs)
[HttpPost]
public ActionResult LoadRelease(string Project, string Release)
{
var ProjectID = _ProblemReportsDB.ProjectMaps
.Where(r => r.Project == Project)
.Select(r => r.ID).FirstOrDefault();
ViewBag.Project = Project;
var Releases = from row in _ProblemReportsDB.PlannedOpenCloses
where (row.Project == ProjectID && (Release == null || row.Release == Release))
select row;
return PartialView("_TableBody", Releases.ToList());
}
I just have no idea how to debug the ajax call.
The error call is outputting this:
[object Object]
BusinessArea=Test1&GenericProject=Test2&Project=Test3&Release=Create+New+Release
/Home/LoadRelease
post
All of which is correct. Just simply fails. Is there some way I can get more information from the ajax error parameters? [object Object] is kind of useless to me.
Is there some way I can get more information from the ajax error
parameters? [object Object] is kind of useless to me.
As per the documentation for $.ajax
error Type: Function( jqXHR jqXHR, String textStatus, String
errorThrown )
Function receives three arguments: The jqXHR (in jQuery 1.4.x,
XMLHttpRequest) object, a string describing the type of error that
occurred and an optional exception object, if one occurred. Possible
values for the second argument (besides null) are "timeout", "error",
"abort", and "parsererror".
When an HTTP error occurs, errorThrown
receives the textual portion of the HTTP status, such as "Not Found"
or "Internal Server Error." As of jQuery 1.5, the error setting can
accept an array of functions. Each function will be called in turn.
Note: This handler is not called for cross-domain script and
cross-domain JSONP requests. This is an Ajax Event.
So the [object] you're getting is the jpXHR which is the jquery wrapper for the underlying XMLHttpRequest. If you want status text and error message, then add the additional parameters to your error callback:
error: function (xhr, textStatus, errorThrown) {
console.error(textStatus + "\n" + errorThrown);
}
Javascript is not like C# in this respect. All arguments are essentially optional and you can also pass more arguments than a function signature requires.

The required anti-forgery form field __RequestVerificationToken is not present

Could you please help me to solve this issue? I'm implementing sign in form without form or html.beginform because I'm calling the controller /API through Ajax call and based on the status message / success, I want to redirect to some page as per the requirement. Please note, I shouldn't skip the anti-forgery method which has been implemented for the controller method. Thanks.
But I'm not able to proceed further because of "The required anti-forgery form field __RequestVerificationToken is not present"
My View is as follows :
""<input data-bind="value: UserName" type="text" name="username" />
<button type="button" data-bind="click:LoginMethod"> Login </button>""
And the Ajax code is as follows
self.LoginMethod = function () {
//Ajax call to Insert the Customer record
$.ajax({
type: "POST",
url: "http://localhost:8089/Home/SignIn/",
data: ko.toJSON(CustData), //Convert the Observable Data into JSON
success: function (data) {
console.log("success");
alert("Record Added Successfully");
},
error: function () {
console.log("failed");
alert("Failed");
}
});
Appreciated your's help.
Change data: ko.toJSON(CustData) to data: ko.toJS(CustData).
And you should be good to go

HTML reponse after Ajax call is stripped of some tags

I am making an ajax call to a action in a controller which returns a partial view. The partial view is a row that will be appended or it will replace an existing row from a grid of items (depending if I am adding or editing a row item).
In the Network tab from Google Chrome I am getting the correct string of HTML like:
<tr class="" data-id="1c4daceb-2afb-413b-8adc-d20b4d8969e5">
<td><img style="width:100px; height:100px;" src="http://localhost/Project/6b39488b-db2d-495e-957c-ede0eb462292.png" data-id="1c4daceb-2afb-413b-8adc-d20b4d8969e5"/></td>
<td>bvcbvX</td>
<td>6b39488b-db2d-495e-957c-ede0eb462292.png</td>
</tr>
but in my Ajax success function:
function onDataEdited(data, status, xmlhttp) {
alert(data);
}
I get the row stripped of and tags, like this:
<img style="width:100px; height:100px;" src="http://localhost/Project/6b39488b-db2d-495e-957c-ede0eb462292.png" data-id="1c4daceb-2afb-413b-8adc-d20b4d8969e5"/>
bvcbvX
6b39488b-db2d-495e-957c-ede0eb462292.png
So something from jquery strips my tags leaving only the content.
The call to the action is done through Ajax like this:
function MakeAjaxCall() {
$('#myForm').ajaxForm({
iframe: true, ---> here is needed since I am adding a file upload from my form
beforeSubmit: function () {
if (!$('#myForm').valid())
//process validation
return $('#myForm').valid();
},
success: function (data, status, xmlhttp) {
if (xmlhttp.getResponseHeader('ErrorHeader') == null ||
xmlhttp.getResponseHeader('ErrorHeader') == "") {
//process success
}
else {
//process error
}
},
error: function (xhr, textStatus, errorThrown) {
alert(xhr);
}
});
}
Can anyone tell me how to get my response data without being stripped of and tags?
I am using this jquery plugin (malsup.com/jquery/form) for making the form "ajaxified" in order to submit a form that contains files through Ajax.
The 'ajaxForm' method from this plugin has as dataType only 'xml', 'json', 'script' and null - (which I am using) and the response is stil stripped of tags for 'xml'. If I set 'json' or 'script' it throws a client side errors specifying that it cannot parse the response (is trying to parse it as a script when it is html).
Could be an issue with the dataType: http://malsup.com/jquery/form/#options-object ?

Load partial view into div on button click without refreshing page

I know this question might be repeated but my query is different let me explain, I have a drop down in page and by selecting value in drop down list,and I click on submit button.. I want by click on submit button I need to load partial view in tag that is list of records of selected drop down list value.
i tried this :
$("#btnclick").click(function () {
$.ajax({
type: 'POST',
url: '#Url.Content("~/Search/MDLNoDataList")',
data: mdlno,
success: function (data) { $("#viewlist").innerHtml = data; }
});
});
but not getting result And I m using these many jquery plugins
<script src="../../Scripts/jquery-migrate-1.0.0.js" type="text/javascript"></script>
<script src="../../Scripts/jquery.unobtrusive-ajax.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
If i understand correctly, below is what you need to do.
HTML Example:
<div id="records">
</div>
<select id="ddlRecordType">
<option value="1">Type 1</option>
<option value="2">Type 2</option>
</select>
<input type="submit" value="Load Records" id="btn-submit" />
jQuery Code
$(document).ready(function(){
$('#btn-submit').click(function(){
var selectedRecVal=$('#ddlRecordType').val();
$('#records').load('/LoadRecords?Id='+selectedRecVal);
return false; // to prevent default form submit
});
});
Here ?Id= is the query string parameter passed to server to get
the selected item in dropdown.
Edit: The below answer was added, as the question content changed from initial post
$("#btnclick").click(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("MDLNoDataList","Search")',
data: mdlno,
success: function (data) {
// $("#viewlist")[0].innerHtml = data;
//or
$("#viewlist").html(data);
}
});
return false; //prevent default action(submit) for a button
});
Make sure you cancel the default action of form submission by returning false from your click handler:
$("#btnclick").click(function () {
$.ajax({
type: 'POST',
url: '#Url.Action("MDLNoDataList", "Search")',
data: mdlno,
success: function (data) {
$("#viewlist").html(data);
}
});
return false; // <!-- This is the important part
});
And if you are using the WebForms view engine and not Razor make sure you use the correct syntax to specify the url:
$("#btnclick").click(function () {
$.ajax({
type: 'POST',
url: '<%= Url.Action("MDLNoDataList", "Search") %>',
data: mdlno,
success: function (data) {
$("#viewlist").html(data);
}
});
return false; // <!-- This is the important part
});
If you do not return false, the form is simply submitted to the server when you click on the submit button, the browser redirects away from the page and obviously your AJAX call never has time to execute.
You will also notice some improvements I made to your original code:
Using the Url.Action helper when pointing to a server side controller action in order to take into account routes defined in your application.
Using jQuery's .html() method instead of innerHTML to set the contents of a given element.
You need AJAX for this purpose.
$.get(url, data, function(data) { $(element).append(data) });
and Partial View that is vague.
element {
overflow:hidden;
}

jQuery Ajax Form Submit Fails

I am developing an MVC4 mobile app that uses several forms which are loaded into a section on the layout via ajax. I've got jQuery mobile set with Ajax turned off so I can manage the Ajax myself. Most of the forms work fine, the load and submit via ajax as they should. However, so far there is one form that refuses to fire the form submit and submit the form via ajax like the rest. First, the form is loaded when a user clicks to add a contact and this works fine:
// Handle the add contact button click
$('#btnAddNewContact').on('click', function (e) {
e.preventDefault();
// Make sure a location was selected first.
var locationID = $('#cboLocation').val();
if (locationID.length === 0) {
//$('#alertTitle').text('REQUIRED');
$('#alertMsg').html("<p>A Contact must be associated with a Location.</p><p>Please select or add a Location first.</p>");
$('#alertDialogDisplay').click();
} else {
SaveOpportunityFormState();
$.cookie('cmdLocationId', locationID, { path: '/' });
$.mobile.loading('show');
$.ajax({
url: '/Contact/Add',
type: 'GET',
cache: false,
success: function (response, status, XMLHttpRequest) {
$('section.ui-content-Override').html(response);
// Refresh the page to apply jQuery Mobile styles.
$('section.ui-content-Override').trigger('create');
// Force client side validation.
$.validator.unobtrusive.parse($('section.ui-content-Override'));
},
complete: function () {
$.cookie('cmdPreviousPage', '/Opportunity/Add', { path: '/' });
AddContactLoad();
ShowSearchHeader(false);
$.mobile.loading('hide');
},
error: function (xhr, status, error) {
// TODO - See if we need to handle errors here.
}
});
}
return false;
});
Notice that after successfully loading the form the AddContactLoad() function is fired. This works fine and here is that code:
function AddContactLoad() {
$('#contactVM_Phone').mask('(999) 999-9999? x99999');
$('#frmAddContact').on('submit', function (e) {
e.preventDefault();
if ($(this).valid()) {
$.mobile.loading('show');
$.ajax({
url: '/Contact/Add',
type: 'POST',
cache: false,
data: $(this).serialize(),
success: function (response, status, XMLHttpRequest) {
if (!response) { // Success
ReturnToAddOpportunity();
} else { // Invalid Form
$('section.ui-content-Override').html(response);
// Force jQuery Mobile to apply styles.
$('section.ui-content-Override').trigger('create');
// Force client side validation.
$.validator.unobtrusive.parse($('section.ui-content-Override'));
AddContactLoad();
$.mobile.loading('hide');
}
},
complete: function () {
},
error: function (xhr, status, error) {
// TODO - See if we need to handle errors here.
}
});
}
return false;
});
$('#btnCancel').on('click', function (e) {
e.preventDefault();
// See where add contact was called from.
var previousPage = $.cookie('cmdPreviousPage');
if (previousPage.indexOf("Detail") >= 0) {
ReturnToOpportunityDetails();
} else {
ReturnToAddOpportunity();
}
return false;
});
}
If I click the cancel button, that code is fired so I know this is working too. Here is my form code:
#using (Html.BeginForm("Add", "Contact", FormMethod.Post, new { #id = "frmAddContact" }))
{
#Html.ValidationSummary(true)
#Html.AntiForgeryToken()
-- Form Fields Here --
<div class="savecancel" >
<input type="submit" value="Save" data-mini="true", data-theme="b", data-inline="true" />
Cancel
</div>
}
As you can see the form is named frmAddContact and that is what the AddContactLoad() function is attaching the submit event to. To save my sole I cannot figure out why the form does not submit via the ajax post like every other form in the app. Am I missing some kind of initialization, I just don't know. If anyone can please help I'd really appreciate it!!
As it turns out, I had created a custom unobtrusive Ajax validator for a phone number then copied and pasted it to do the same with a zip code. Unfortunately in the process I forgot to rename a variable and thus an error was occurring in the validation script which caused the problem. In the mean time, if you're reading this, you might take a note of the code here and how to inject HTML into a page via Ajax and jQuery mobile. I've never found this in a book or on the web and it contains some very useful methodology and syntax. On the form submit the reason I'm checking for the empty response is I just return null from the controller to validate the form was valid and the save worked in which case I send them to a different HTML injection i.e. that page they originally came from. If null is not returned I inject that page with the HTML containing the original form and error markup so the user can make corrections then resubmit. I'm also calling a form load method that attaches handlers to the HTML once it's injected into the main page. Hope this helps somebody!

Resources