jquery Ajax optimization tips - MVC - asp.net-mvc-3

I am currently trying to convert a controller action into Ajax requests in order to let the page load in sections rather than all at once. Before I started making changes, the page loaded in about 8 seconds (it has to process a lot of information).
Since I've changed it to loading up Partial Views via ajax, the page now takes about 35 seconds to load up the same information.
The process is as follows:
The initial request processes and then returns a viewmodel (a generic list) as json
I then use the returned data to create two partial views
I just wonder if there is a better way of laying out the jquery to get it to work faster. I'm aware the amount of data being passed could be a factor - although I can't find the exact size of the object in the debugger, when I dump the json out to a text file it is about 70kb.
jQuery
$.ajax({
type: 'GET',
dataType: "json",
url: '#Url.Action("GetMapDetails")',
success: function (data) {
$.ajax({
type: 'POST',
contentType: 'application/json',
url: '#Url.Action("GetMapItems")',
data: JSON.stringify({
list: data
}),
success: function (result) {
$("#mapContainer").html(result);
}
});
$.ajax({
type: 'POST',
contentType: 'application/json',
url: '#Url.Action("GetAreaPoints")',
data: JSON.stringify({
list: data
}),
success: function (result) {
$("#areaPointsContainer").html(result);
}
});
}
});
Controller
public JsonResult GetMapDetails()
{
List<ViewModel> vm = new List<ViewModel>();
//create viewmodel here
return Json(vm.ToArray(), JsonRequestBehavior.AllowGet);
}
public ActionResult GetMapItems(List<ViewModel> list)
{
return PartialView("_MapItemsPartial", list);
}
public PartialViewResult GetAreaPoints(List<ViewModel> list)
{
return PartialView("_AreaPointsPartial", list);
}
If anyone can offer some optimization advice, that would be great thanks

You could look into rendering partial views into strings. That way you could return both HTML strings from GetMapDetails, and you'd be able to achieve the same result in one AJAX call instead of three.
If would also rid you the need of serializing the viewmodel back and forth, so there might be some performance gain there.

Install the Stackexchange Miniprofiler and hook it into your database requests as well, this will help you find which bit is taking the most time. I suspect it could well be your data and processing on the server (depending on how you have written your controller you could be hitting your data load+process 4 times in the AJAX version, resulting in the 4 times page load).
If this is true then the problem is not going to be fixed by AJAXing your page but caching the processed data on the server (to keep it up to date your choices are a short cache duration or have the process that updates your data remove the cache, the correct answer depends on what your data is).

Since I think that your goal is to be able to load partial views only when they are needed, putting them all in one markup string isn't going to work.
The performance problem you are having is probably due to the fact that ajax-calls are indeed more performance expensive then to load a result stream from a server.
Caching will only help when you retrieve the same data into the same page - not your case either.
From what it seems to me, you should load up the initial view to the user, and immediately start background pre-loading of the views you are probably going to need soon. Just placing them onto the DOM as an indivisible elements, so one requested, they will be immediately loaded. Of course you pre-load only those which you are most likely to need soon.
Other, probably more effective way, would be to use an MVVM framework on the client, like KnockoutJS. Define your views in a simple html markup, without the actual need for the server to render the partial view with the model. This would allow an html to transfer faster. Separate REST calls from your client would be retrieving only the model data from the server in JSON format, and you will apply data binding to the view (lightweight html you've loaded previously). This way the burden of heavy-rendering will be on the client and the server will be able to service more clients in a long run + you are most likely to get the performance gain.

Also try to use $.ajax cache option to true to improve further calls jQuery ajax method
I assume that infomation don't change fast then it would improve the performance.
For example I work with statistics pages loading asynchronously 7-8 plots there cache saves me a lot of time.
From jQuery Api:
On the other hand if the posted data content changes fast it's not recommended to cache it but also take into account that EVERY browser caches that request in it's own cache. To avoid browsers caching use timestamps on every request as query strings just as $.ajax does automatically.

Related

RoR - optionally filling form fields based on external data

I recently started with Rails, making some good progress but hit another snag now.
I have a form that users should fill out manually. An example would be something like a human resources pages where one can enter name, address, phone number of an employee.
What I would want to do is have another field "remote_id" that is optional and when filled out, will do a REST call to a remote resource to retrieve name/address/phone number and fill out the form on the fly but not immediately submit it. A time saver, if you will.
And I have no clear idea of what that would entail in terms of form filling (the controller action for the remote call is probably not a problem), but it seems to go beyond what rails will do "out of the box". JQuery, AJX, something else? A pointer would be really appreciated!
Cheers,
Marc
The most important thing you need to check out for is the url of the remote resource and possible need to authenticate your request before having access to the resource. You might then make an ajax request to the resource. Using jQuery
$("remote_id").click(function(event){
event.preventDefault()
$.ajax("http://externalresourceurl.com", {
success: function(data) {
// fill each form field with corresponding item in the data object
$('#first_name').html($(data).first_name);
...
},
error: function() {
$('#notification-bar').text('An error occurred');
}
}
);
});

MVC return PartialView slow first time after edit

I imagine the answer to this is something cache related, but to better understand the reason I thought I'd at least ask.
In my MVC project I'm doing an AJAX request to the controller to return a html page as a partial view, I then inject that html into the page with. The reason for this is the model for the view changes depending on what's clicked.
Here is the AJAX: (Please note all code has been modified for simplicity)
$.ajax({
type: 'GET',
url: "../../Home/NewMembershipAlloc/",
contentType: 'application/json',
dataType: 'html',
success: function (data) {
$('#partial_div').html(data);
}
});
Here is the controller method:
public async Task<ActionResult> NewMembershipAlloc()
{
return PartialView("~/Views/Popup/GenericPopup.cshtml", new Membership());
}
Now, just to be clear, this all works as intended. Nearly everytime I run this code it takes maybe 20ms, as shown below:
However, if I edit my html page in any way, even if I just remove one character and then add it back in. The next time I perform the request it will take 2 seconds (ish).
So this is happening within my development environment which should be the only place my html is edited. It does not happen when I refresh the page, clear the cache or open a new browser. So my questions are the following:
What's the full reason this is happening?
Can I stop it from being slow the first time? Or is it the price I pay for loading new html?
Would this delay ever happen after release? If someone doesn't use the webpage for a few days for example and shuts down their machine maybe.
It looks similar to this question:
https://stackoverflow.com/a/25006809/6862867
In reference to the above link:
The first time a new or edited view is requested the server will parse and compile the code. This takes a small amount of time (but longer than you'd expect for a page load) and is only required once each time the page changes. I suspect that the reason you are seeing it even if you remove a character and then add it back in is that the server does not recognise what has changed until parse/compile time only that the file has changed since the last time it was loaded.
It would seem that you can precompile your project on publish although I'm not clear myself on how this is done/works.
Post release it would happen only the very first time that page was loaded. You could get round this by making that request yourself as soon as you release it.
Hope this helps :)

Speed up Sinatra page load with Ajax?

I am using the Sinatra to develop a web application but I am running into long page load time issue.
The application goes through and display a lot of data so I am sure this is the cause but I was wondering if there was a way to have the main erb layout of the page load first and then after that load, the data loads on top of it.
My first thought was AJAX but I am not sure how I would implement this.
Thanks in advance.
You are correct, it may help. The old mantra of "separate that which changes from that which does not" is applicable in any part of programming.
Here's route that returns some data:
require 'json'
get "/time-now/?" do
content_type :json
{time: Time.now.to_s}.to_json
end
and here's some javascript (jQuery ajax) to call it:
$.ajax({
accepts: "application/json",
type: "GET",
url: "/time-now",
dataType: "json",
success: function(res, status, xhr) {
return [$("#time").html(res)];
},
error: function(res, status, xhr) {
return [$("#time").addClass("error")];
},
complete: function(res, status, xhr) {
return [$("#button1").show()];
}
});
(that bit of jQuery may be a little bit wrong, just warning you, it's a copy 'n paste job hacked to fit this example)
Perhaps you could stop serving user pages from Sinatra routes and use static (i.e. prebuilt) pages with javascript in them that make AJAX calls to Sinatra routes. Or a mixture of the two types. Then you've got the start of a web service data API. There are lots of javascript frameworks to help with this, (e.g. Ember, Backbone, Angular and many more) and plenty of API builders alongside Sinatra, like Grape and Weasel Diesel.

Using web2py, jQuery and ajax, how do you post to a database?

Using web2py I am trying to use ajax to put data into a table in my database, but I'm needing a bit of help.
Here is the function I am using (it currently has dummy data in the data section, rather than being passed data from a form):
function submitData(){
$.ajax({
type: "POST",
url: "requests",
data: {
id: 1,
user_id:111,
bottle_image:'',
bottle_name:'JJjman',
bottle_description:'Lol',
request_creationDate:'2000-01-01',
request_expiryDate:'2003-08-08',
request_fulfilled:false
},
success: function(){
alert('Posted data');
}
});
}
I have a html button with this function attached to its 'onclick', but at the moment all it does is reload the page and not pass any data onto the database. The success alert is also coming up.
Firebug is saying that the POST does contain all that data, but I'm not sure if the POST is actually going anywhere..
Am I missing any steps needed to actually pass this data to the database? Or could this just be that my data isn't all the right type for the database?
Cheers guys
Simply sending a post from the browser won't do anything on the server unless you have code on the server to handle the data and insert it into the database.
I strongly recommend you read through the relevant parts of the book to learn how to do this. The Overview chapter provides an introductory tutorial, including building an image blog that involves modeling a database table and creating a form to post records to that table.
Review the DAL chapter for details on modeling your database, the section on SQLFORM for details on creating forms associated with database tables, and the sections on ajax and components for details on using Ajax to post forms.
The easiest way to do what you want would be something like this:
In /models/db.py:
db = DAL('sqlite://storage.sqlite')
db.define_table('bottle',
Field('user_id')
Field('bottle_image'),
Field('bottle_name'),
Field('bottle_description', 'text'),
Field('request_creationDate', 'date'),
Field('request_expiryDate', 'date'),
Field('request_fulfilled', 'boolean'),
format='%(bottle_name)s')
In /controllers/default.py:
def index():
return dict()
def add_bottle():
return dict(form=SQLFORM(db.bottle).process())
In /views/default/add_bottle.load:
{{=form}}
In /views/default/index.html:
{{extend 'layout.html'}}
{{=LOAD('default', 'add_bottle.load', ajax=True)}}
Then go to /yourapp/default/index, and you will see a form, which will post records to the database via Ajax.

KnockoutJS best practice to populate multiple view models using Ajax

I was wondering whether anyone had any recommendations regarding populating multiple view models on a screen. I have:
a) a view model that has a list of tasks
b) a view model that has a list of users
I populate these in the 2 x ajax success (separate ajax calls) something like:
success: function (data) {
masterVM.User = ko.mapping.fromJS(data, mapping);
ko.applyBindings(masterVM);
}
/* another ajax call: */
success: function (data) {
masterVM.Task = ko.mapping.fromJS(data, mapping);
ko.applyBindings(masterVM);
}
And currently calling in each ajax success call.
I hope my question is clear and concise. Please ask for further detail if required.
Regards
Phil
We currently handle this by sending all of the data to our page in a single Ajax call, then applying a ko.mapping to map the data to the view models on our main view model.
We began by making two calls just as you are but decided that it would be better to reduce the number of http requests being made, which is why we combined the data sets into a single hierarchical object structure, and it's working great.
This question and the subsequent answer contain a snippet of the approach we're taking:
Map JSON data to Knockout observableArray with specific view model type
As long as you dont notice a performance issue, I recommend making separate calls because this will keep your services loosely coupled with your presentation needs.
However, if its a perf issue, you can make your web service aggregate the data and return it in one shot. But you lose a little maintainability by this.

Resources