$.ajax().success not working only in firefox - ajax

I have an ajax function like so:
function RunSubmit() {
$.ajax({
url: '#Url.Action("Contact", "Public")',
type: "POST",
data: $('#contactForm').serialize(),
dataType: 'jsonp',
crossDomain: true,
success: function (result) {
alert("hit success function");
if (result.validForm) {
alert("At redirect. Url is: " + result.url);
window.location.assign(result.url);
//console.log("valid form");
} else {
$('#registerForForm').html(result);
//console.log("BAD FORM");
alert("ELSE CALLED");
}
},
error : function(ob1, ob2, ob3)
{
},
complete: function(val)
{
//This is being hit but it appears no value is being returned from the controller (FireFox)
}
});
Strange thing is it works in IE and Chrome but not FF. I have tried running the post with dataType: 'json' without the dataType and without the crossDomain property. Looking at the console on FF I can see that we are having numerous cross domain request errors mainly coming from google fonts. (This does not happen on chrome or ie). In our controller we are making a hardcoded http request to another server on a different host so I can see where the issue might be arising. The way we have dealt with this issue before is by adding a crossdomain.xml file to the root of our project. Something like this
<?xml version="1.0" encoding="utf-8" ?>
<cross-domain-policy>
<allow-access-from domain="*.xyz.com"/>
<allow-access-from domain="*.abc.com"/>
<allow-access-from domain="*.123.net"/>
<allow-access-from domain="http://university.abc.com"/> //this is the site we are sending a request to in our controller
</cross-domain-policy>
So I have searched and come across multiple posts on SO where the success function was not being called on an ajax post. Check my error objects the only information I am getting back is "error". This javascript should be receiving a url back and redirecting; however, what it is doing is rendering the JSON return value to the screen.
This is the line of code that returns our Json from our controller.
return Json(new { validForm = true, url = "/Public/ContactComplete" }, JsonRequestBehavior.AllowGet);
The line looks fine to me and the Json being returned is perfect json so it should not be a parsing error on the jquery side.

This was an interesting situation. I'm adding this to my list of reasons as to why a form may not post back in MVC. The outside firm we hired to develop our product created a 'hack' to get around an issue where Chrome would not post back if you wished to disable the submit button (to prevent double post) on the click of the button itself. To get around this the developer wrote an ajax script submitting the form manually on click. This in turn blew up functionality in firefox. There was some weird double posting going on and for whatever reason FF would render JSON to the screen instead of catching the Json back and running the success function.
Long story short:
If you are disabling a submit button to prevent double post then disable it on the form submit event.
pseudo code
$('#submit-button').on('click', function() { this.attr('disabled', true);}
Is not the way to go. The below is what fixed it for me
$('form').on('submit', function() { $('#submit-button').attr('disabled', true);}

Related

Handling session timeouts in ajax calls

ASP.Net MVC 5 .Net Framework 4.6.1
I just added code to detect session timeout which works fine:
public class CheckSessionTimeOutAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
{
var context = filterContext.HttpContext;
if (context.Session != null)
{
if (context.Session.IsNewSession)
{
string sessionCookie = context.Request.Headers["Cookie"];
if ((sessionCookie != null) && (sessionCookie.IndexOf("ASP.NET_SessionId", StringComparison.Ordinal) >= 0))
{
string redirectTo = "~/Home/Index";
filterContext.HttpContext.Response.Redirect(redirectTo, true);
}
}
}
base.OnActionExecuting(filterContext);
}
}
As you can see, I redirect them to the home screen. I have my [CheckSessionTimeOut] as an attribute on all pertinent controllers. So, I run the app, go to a page other than the home screen, wait 1 minute for session timeout, the code runs as expected in certain situations. Case and point, I have a dropdown and when a selection is made, a redirect is taking place. Heres the method:
$('#selusers').change(function () {
var rd = $(this).find("option:selected").attr('redirect');
location.href = rd;
});
What happens here is when a user is selected from the dropdown, the redirect attribute is read and redirection to that person takes place. If the session times out, redirection to the logged in user takes place and not the newly selected user. This is correct for my app.
However, I make numerous ajax calls in my app. When the session times out and I click on an element that fires an ajax call, I get redirected to the home screen, but the error method gets called in the ajax request. I get a popup with the home screen html inside of it. Here's one example of an ajax call I'm making. I'm on a screen with a save button, the session times out and this code gets fired:
SaveButtonClicked: function (somedata) {
$.ajax({
url: url,
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify(some data im sending),
success: function (dataResult) {
if (!dataResult.Ok) {
alert("Error occurred. Please try again");
}
},
error: function (err) {
alert(err.responseText);//this gets called
}
});
}
I have overridden the default alert so styled html will appear. The alert box has the home screen html in it. I do not want that. I want the app to be redirected to the home screen, no popup. So my first question, is there a way to do something at the server to stop the ajax call from running its complete methods(i.e I want to do something at the server so the ajax call's success, error, or complete methods will never be called)? Next question if the first one isn't an option, what would be a very good way to detect that the session has timed out in the complete methods of an ajax call so the user is gracefully redirected to the home screen? If there are any other ways of doing what i'm trying to achieve that I didn't not ask, please share them. Thank you for reading my question.
UPDATE
I removed the error function from one of my ajax calls and added a global error handler instead:
$(document).ajaxError(function (e, xhr, settings) {
debugger;
});
Now, when the session timeout, this error handler gets called, BUT, i look in the xhr variable and it contains the results of the ajax call and corresponding html. The status is a 200, the statusText says parsererror, the readystate is a 4. There is nothing here that tells me the session timed out. What can i do at the global ajaxError method to tell me session timed out?
A good starting points might be:
If your ASP.NET MVC project properly returns status code:
$.ajaxSetup({
statusCode: {
401: function() {
window.location.href = "/login/path";
}
}
});
if not you can try:
$(document).ajaxError(function (e, xhr, settings) {
debugger;
});
Review e & xhr properties and make a decision from there.

Prevent browser caching of MVC partial pages as full pages (on back/forward)

I have an iphone-style list-view system for navigation of a website that looks like this:
The URL is changed dynamically when a panel is loaded via AJAX and the same URL is placed in the browser address bar with puststate. This a allows a page refresh to reload the current page:
this.Historyjs.pushState({}, "", url);
To make this work the pages can return themselves as either a partial page, or a full page. The code to detect the difference is a base controller and looks like:
public bool IsPartialPage
{
get
{
// ListViewer will strip out HTML from a full page if this occurs
return Request.IsAjaxRequest() || !string.IsNullOrEmpty(Request["partial"]);
}
}
An example controller action looks like this (note the Partial View cache expiry):
[OutputCache(Duration=1)]
public ActionResult ListViewerDocumentation()
{
if (!base.IsPartialPage)
{
ViewBag.Layout = "~/Views/Shared/_ListViewLayout.cshtml";
}
return PartialView();
}
The problem I have is that when you navigate using the Browser's back and forward buttons, it will occasionally decide that a previously partial page is sufficient to become the entire page and does not make a call to the server (checked with Fiddler2) and so looks like this:
Any suggestions on a method that will ensure back and forward navigation always pull back a full page and not from its cache of Ajax requests? Is it simply a matter of making the Ajax calls unique, or will the vanilla URL from the back/forward still match?
Turns out the trick is to turn off caching on the Ajax request that pulls the partial pages, not on the server as that is never hit (the light suddenly came on after writing the above question):
$.ajax(
{
cache: false, // << Added this
url: url,
type: "GET",
error: function (jqXHR, textStatus: string, errorThrown: string)
{
// On error (eg. "not found") empty out the display
THIS._removeContent();
},
success: function (data: string, textStatus: string, jqXHR)
{
var $data = $(data);
THIS._insertContent($data, function ()
{
});
}
});
The cache false also apparently ensures the browser will not reuse the page on page back/forward operations.

why browser request for image after ajax?

I'm using backbone and nodejs for a single page webapp.
I got a view, which has a model(a blog post) in it. when user click on 'like' button, the view will start ajax send the user'id to server to let the like number +1.
it looks like this:
this.model.save({
likedBy: userModel.get('_id')
}, {
url: '/posts/' + this.model.get('_id') + '/like',
success: function() {
// do something
},
patch: true
});
my problem is, when this code got run. browser start http request to retrieve all the images on the screen, and re-render them. so the screen got a "shake" after user clicked the like button.
this is not happening everywhere, but what caused this? how to stop the "shake"?
thanks for any advance.
When you call this.model.save() the model will update his data in the server and will call your view's render function. The render method will create a new DOM element and replace the old DOM element, that's what causing the flickering (it requests the images again).
I assume you have an API call for Like action (if not it's better to have one) so you can make a sperate AJAX call for like action on your model by adding a function like so:
addLike : function(data) {
Backbone.ajax({
url: '/api/like/'+ this.get('id'),
method: 'POST',
data: data,
success: options.success,
error: options.error
});
}

AJAX jQuery form submission with HTML in form

I'm not terribly experienced with AJAX and so am using some tools and attempting to integrate and customize them. First, this is a wordpress site using an AJAX form to submit a post. It all works great! Now, of course, I have to add a WYSIWYG editor to the mix and need to figure out how to get the html content to submit properly.
Here's the submit code:
jQuery("form.pfs").submit(function() {
// vvv I ADDED THIS LINE!!! vvv
jQuery('textarea#postcontent').val(jQuery('div.workzone iframe').contents().find('body').html());
jQuery(this).ajaxSubmit({
type: "POST",
url: jQuery(this).attr('action'),
dataType:'json',
beforeSend: function() {
jQuery('.pfs-post-form #post').val('posting...');
},
complete: function(request,textStatus,error) {
data = jQuery.parseJSON(request.responseText);
if (data && data.error) {
jQuery('#pfs-alert').addClass('error').html('<p>'+data.error+'</p>').show();
jQuery('.pfs-post-form #post').val('Post');
} else {
jQuery('form.pfs').reset();
location.reload();
}
}
});
return false;
});
As you can see, I've added that first line where I take the content of the HTML in the WYSIWYG (http://elrte.org/) and set it as the value of what would have been the original textarea (#postcontent).
The AJAX works perfectly if there's an error, so it is only the "else" portion of the routine that is throwing the error:
Uncaught SyntaxError: Unexpected token < jquery.js:2
e.extend.parseJSON jquery.js:2
jQuery.submit.jQuery.ajaxSubmit.complete pfs-script.js:31
F
So as you see, I need to validate for malicious code (not part of this help request!!) but more importantly I just want to be able to accept HTML in my form posts. Ideas? I am not 100% sure I understand what is failing and where...
turns out there was a conflict with another Plugin. tracing out the request.responseText revealed it. This code works just fine.

JQuery - It fails on IE7. Crossbrowser compatibility?

I tried to open a post time ago about this problem (here), thinking i was wrong making the code. Now more or less i've understood that some version of Jquery with my code doesnt work on IE7. What's Happening? I also tried to open a post on JQuery official forum (link) but no one reply. Anyway, in my old website i used to work with jquery-1.3.2.min.js , and i didnt problems. Now, i need to use the .delegate() function, so I include the jquery-1.4.2.min.js library.
Above you can see the usual code I used in my old application :
// html page
prova
// javascript page
function pmNew(mexid) {
var time = new Date;
$.ajax({
type: 'POST',
url: './folder/ajax.php',
data: 'mexid='+escape(mexid)+'&id=pmnew',
success: function(msg) {
alert(msg);
}
});
return false;
}
// asynchf.php
if($_POST['id']=="pmnew") {
echo "please, i will just print this";
}
With some suggestions by some users of this website, i edited these functions :
// html page
prova
// javascript page
function pmNew(mexid) {
var time = new Date;
$.ajax({
type: 'POST',
cache: false,
url: './folder/ajax.php' + '?dummy=' + time.getTime(),
data: 'mexid='+escape(mexid)+'&id=pmnew',
success: function(msg) {
alert(msg);
}
});
return false;
}
// asynchf.php
if($_POST['id']=="pmnew") {
echo "please, i will just print this";
}
But it STILL DOESNT WORK on IE7. Firefox, Chrome, it rocks. It works on IE7 only if i load the page, i try (and i get the error message), i reload (F5) and i retry. Or, as i said before, i change the version of Jquery :)
I loaded a testpage on a real server (so you can check yourself this problem) : click here
I hope someone can help me with this big trouble.
Cheers
The reason behind this bug is when you are using relative URLs on IE7, it actually adds your base url (or wherever your page is loaded from e.g. if you place a relative url on your home page your relative URL would actually be http://gabbatracklistworld.com/http://gabbatracklistworld.com/folder/ajax.php)
I just came across your question here on SO while searching for a solution on some same problem I had myself a few minutes ago. There's actually an article from microsoft's blog that explains how IE7 handle relative urls (which is funny because it just shows that they are proud of how their stupid browser works)
Seeing that you have no answer yet, I'd put my solution here for future reference and other devs too.
What I did is use substring() to strip the instances of my base url forcing the ajax request to use the actual relative URL.
Can you add this argument to your .Ajax options:
error:function(xhr, status, errorThrown) {
alert(errorThrown+'\n'+status+'\n'+xhr.statusText);
},
and reply with the message ?

Resources