I am looking for a way to debug what happens between $.ajax and Controller action. Is there a way to see how long these stretches are and if there is a delay where it happens(if network, then where?)?
Here's one approach you could try in order to isolate the problem. You start a brand new ASP.NET MVC application and put a controller action that simulates some work:
public ActionResult SetSearchResults(SearchCriteria searchCriteria)
{
Thread.Sleep(400);
return Json(new { success = true });
}
and you invoke it with AJAX:
$.ajax({
contentType: 'application/json, charset=utf-8',
type: "POST",
url: '#Url.Action("SetSearchResults")',
data: JSON.stringify({ }),
cache: false,
success: function (response) {
}
});
then observe the time it takes for the AJAX request to execute in your javascript debugging tool (I am using Chrome developer toolbar but you could FireBug as well if you prefer):
405ms. Great, I guess this figure doesn't surprise anyone. If you get a different number you may start worrying seriously. But I doubt you will get a different number. So the problem doesn't come neither from ASP.NET MVC nor AJAX.
That's barebone. Now you could start adding some real work to your controller action by shaping it with database calls and stuff until you find the smoking gun. Add things progressively. Start by manually instantiating your repository class, then if you are using DI framework add that later, etc... It's very important to do it one step at a time.
Related
I want to call the hook methods onBeforeRendering and onAfterRendering externally. My requirement is, when my 3/4 ajax calls complete that time I am rendering UI parts after that I need to call those two methods.
As said, I think your architecture is wrong. I would have build it something like this:
var self = this;
$.ajax(firstURL, {
method: "GET",
contentType: "application/json",
}).fail(function(response) {
// handle error
}).done(function(data) {
// do something with the returned data from first call
$.ajax(secondURL, {
method: "GET",
contentType: "application/json",
}).fail(function(response) {
// handle error
}).done(function(data) {
// do something with the returned data from second call
$.ajax(thirdURL, {
method: "GET",
contentType: "application/json",
}).fail(function(response) {
// handle error
}).done(function(data) {
// build extra UI elements, for example:
var someContainer = self.getView().byId("myContainer"); // ui element where you add more controls
someContainer.addContent(new com.initrode.MyCustomControl({
value : data.someProperty,
change : self.doSomething
}));
});
});
});
As you see:
No calls to onBeforeRendering/AfterRendering
AJAX calls are nested, yet asynchronous (the Promises solves the "synchronous" issue here)
Set your custom control event handlers (in this case, change) inline, so no extra event registration needed
There is no need to set any control's ID (except for the layout element where you need to add the extra controls needed after your ajax calls have all successfully finished)
As #Qualiture said in the comment, you cannot call those methods as they are hooks, being called by the framework before and after the rendering of a control.
You can however "ask" for a rerendering of the control, which in turn will call both hooks, by calling oControl.rerender() or oControl.invalidate()
I dont know if you can do it for your scenario, but in a similar situation I was able to toggle on the fly rendering (as soon as all the ajax calls needed for a control are completed, the control is rendered) by leveraging model binding in the application.
i.e if a control requires some 'data' object to be loaded, bind the control to a model '/data' that will be updated by your ajax call and manage your control visible attribute with something like {= ${/data}||false }
Actually this is somehow relying on the framework to call the renderer function of the control when it detects a change in the model.
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);}
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
});
}
I was looking at Emberjs recently and found this useful article written by one of its main contributors: Advice on & Instruction in the Use Of Ember.js
It walked me through an example which fetch a list of user data from a server and render them on screen. I'll briefly explain how it worked:
The app contacts the server to fetch a list of user data though ajax
call.
At the end of the ajax call an empty enumerable is returned
immediately, which is later used as a property of a controller.
Once the ajax call is completed, it populates the enum with data which
in turns update the controller's property, and finally triggers an
automatic re-rendering.
This works fine as long as the list is not revisited. As a user revisit the list, say he/she navigates to another state and then comes back, the logic will be triggered again, fetching the data from server and populates the list. However, the list this time is not empty! Thus we have a list of duplicated data. I would like to resolve this by clearing the content of the list when the ajax call is successful. Below is the code for the ajax call:
allAwesomebergs: [],
fetch: function(){
$.ajax({
url: 'https://api.github.com/repos/emberjs/ember.js/contributors',
dataType: 'jsonp',
context: this,
success: function(response) {
response.data.forEach(function(awesomeberg){
this.allAwesomebergs.addObject(App.Awesomeberg.create(awesomeberg))
}, this);
}
});
return this.allAwesomebergs;
},
The above code does not clear the content of the list. I tried adding a line "allAwesomebergs = []" at the beginning of the success function, but what I got was just a blank screen. I thought I may not be doing this correctly, but I looked at the document from Ember and didn't see anything about clearing the content of an Enumerable.
Thus the question is: what is the easiest way to resolve this duplicate loading issue? Clearing the content before hand seems the most obvious but I can't make it work.
You can call clear() before you start adding the new objects. See this documentation.
New code would be:
allAwesomebergs: [],
fetch: function(){
$.ajax({
url: 'https://api.github.com/repos/emberjs/ember.js/contributors',
dataType: 'jsonp',
context: this,
success: function(response) {
this.allAwesomebergs.clear();
response.data.forEach(function(awesomeberg){
this.allAwesomebergs.addObject(App.Awesomeberg.create(awesomeberg))
}, this);
}
});
return this.allAwesomebergs;
},
I think your approach was ok, but it should have been:
this.allAwesomebergs = []
It is all about the this in front of it. So clear is not needed here.
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 ?