I have a webapi service that I need to access from web app
If I call the webapi url directly (e.g. /api/scrccc/32) it returns data in less then 5 sec, but when called from jquery, it takes more then 5 minutes (!!!) minutes
My ajax call is
j$.ajax({
type: "GET",
url: '/api/scrccc/' + id + '?dt=' + new Date().getTime(),
error: function (jqXHR, status, error) {
//....
},
success: function (data, status, jqXHR) {
//....
}
});
This happens with javascript console (firebug) open or closed, and in Chrome and FF
Anyone has any idea why this happens?
EDIT:
Here are the timings in Chrome with Jquery call:
and the timings in Chrome with direct access to url in address bar
... and timimgs in browser with timestamp also
EDIT - June 1
I realized there is a difference between calling the webapi from ajax and from browser's address bar:
- ajax call requests response as json
- browser requests response as XML
So I tested both requests in Postman, with json and xml response and the findings puzzled me: request with xml response took 1261 ms while json response took 47000 ms (!!!)
(The timings shown in Chrome console were with local IIS Express, while latest timings shown in Postman are with real app on real web server over internet, that's why they are different, but the scale remains)
So, indeed, the problem is at the server side, as some suggested, but not in the actual application code providing data, but instead at the serialization point.
My Webapi is 2.1 (version 5.1.2), and Json.Net version 6.0.3 (both are latest versions)
I have no special settings to use any particular json serializer, so, as I know, WebApi uses Json.Net.
Any idea what could cause such a HUGE difference in serialization time?
Thanks
First, thanks to all who took the time to loot at this.
As I posted in comment to #adreno, the problem was with an expensive calculated property, loaded on first access.
The property was in an class defined in BL, which was used in various places, so at first I didn't thought to check it.
Why that property was excluded from serialization by XML serialization? I don't know, and due to time constraints, I didn't had either the time or a particular interest to investigate further (since it's not an open api, and we didn't needed XML output).
How do you serialize the JSON?, what library are you using, I would try just Gson first in case that you are using Jackson or another library that your framework is using.
like I said render a String
String myjson = "";
Gson gson = new Gson();
myjson = gson.toJson(myuser);//myuser is my java object
return myjson
Related
I am rather new to NodeJS so hopefully I am able to articulate my question(s) properly. My goal is to create a NodeJS application that will use the node-rest-client to GET data and asynchronously display it in HTML on client side.
I have several node-rest-client methods created and currently I am calling my GET data operation when a user navigates to the /getdata page. The response is successfully logged to the console but I'm stumbling on the best method to dynamically populate this data in an HTML table on the /getdata page itself. I'd like to follow Node best practices, ensure durability under high user load and ultimately make sure I'm not coding a piece of junk.
How can I bind data returned from my Express routes to the HTML front end?
Should I use separate "router.get" routes for each node-rest-method?
How can I bind a GET request to a button and have it GET new data when clicked?
Should I consider using socket.io, angularjs and ajax to pipe data from the server side to client side?
-Thank you for reading.
This is an example of the route that is currently rendering the getdata page as well as calling my getDomains node-rest-client method. The page is rendering correct and the data returned by getDomains is successfully printed to the console, however I'm having trouble getting the data piped to the /getdata page.
router.get('/getdata', function(req, res) {
res.render('getdata', {title: 'This is the get data page'});
console.log("Rendering:: Starting post requirement");
args = {
headers:{"Cookie":req.session.qcsession,"Accept":"application/xml"},
};
qcclient.methods.getDomains(args, function(data, response){
var theProjectsSTRING = JSON.stringify(data);
var theProjectsJSON = JSON.parse(theProjectsSTRING);
console.log('Processing JSON.Stringify on DATA');
console.log(theProjectsSTRING);
console.log('Processing JSON.Parse on theProjectsSTRING');
console.log('');
console.log('Parsing the array ' + theProjectsJSON.Domains.Domain[0].$.Name );
});
});
I've started to experiment with creating several routes for my different node-rest-client methods that will use res.send to return the data and the perhaps I could bind an AJAX call or use angularjs to parse the data and display it to the user.
router.get('/domaindata', function(req, res){
var theProjectsSTRING;
var theProjectsJSON;
args = {
headers:{"Cookie": req.session.qcsession,"Accept":"application/xml"},
};
qcclient.methods.getDomains(args, function(data, response){
//console.log(data);
theProjectsSTRING = JSON.stringify(data);
theProjectsJSON = JSON.parse(theProjectsSTRING);
console.log('Processing JSON.Stringify on DATA');
console.log(theProjectsSTRING);
console.log('Processing JSON.Parse on theProjectsSTRING');
console.log('');
console.log('Parsing the array ' + theProjectsJSON.Domains.Domain[0].$.Name );
res.send(theProjectsSTRING);
});
});
I looked into your code. You are using res.render(..) and res.send(..). First of all you should understand the basic request-response cycle. Request object gives us the values passed from routes, and response will return values back after doing some kind of processing on request values. More particularly in express you will be using req.params and req.body if values are passed through the body of html.
So all response related statements(res.send(..),res.json(..), res.jsonp(..), res.render(..)) should be at the end of your function(req,res){...} where you have no other processing left to be done, otherwise you will get errors.
As per the modern web application development practices in javascript, frameworks such as Ruby on Rails, ExpressJS, Django, Play etc they all work as REST engine and front end routing logic is written in javascript. If you are using AngularJS then ngRoute and open source ui-router makes work really easy. If you look closely into some of the popular MEAN seed projects such as mean.io, mean.js even they use the ExpressJS as REST engine and AngularJS does the rest of heavyweight job in front end.
Very often you will be sending JSON data from backend so for that you can use res.json(..). To consume the data from your endpoints you can use angularjs ngResource service.
Let's take a simplest case, you have a GET /domaindata end point :
router.get('/domaindata',function(req,res){
..
..
res.json({somekey:'somevalue'});
});
In the front end you can access this using angularJS ngResource service :
var MyResource = $resource('/domaindata');
MyResource.query(function(results){
$scope.myValue = results;
//myValue variable is now bonded to the view.
});
I would suggest you to have a look into the ui-router for ui front end routing.
If you are looking for sample implementation then you can look into this project which i wrote sometime back, it can also give you an overview of implementing login, session management using JSON Web Token.
There are lot of things to understand, let me know if you need help in anything.
I'm trying to work with the IUCN Red List web services API (here's an example output). Unfortunately I haven't been able to find any documentation other than this one-off Gist. It looks as though the API is constructing an HTML document rather than returning a data object, which isn't something I've experienced in the past. I also notice that in the example there is no mention of a ?callback=JSON_CALLBACK in the URL, which I would expect when dealing with JSONP.
I've constructed an http request in AngularJS like so:
atRiskApp.controller('IucnController', ['$scope', '$routeParams', '$http', function ($scope, $routeParams, $http) {
$scope.iucn = $routeParams.iucn; // pulling a number from the URL: ex. 22718591
$scope.getIUCN = function () {
var iucnUrl = 'http://api.iucnredlist.org/details/' + $scope.iucn + '/0.js';
$http.jsonp( url )
.success( function (response) {
console.log(response);
})
.error( function (response) {
console.log(response);
});
};
}]);
Although the HTML document is being successfully passed to my app I'm getting the following error message:
Uncaught SyntaxError: Unexpected token <
It seems like the app is expecting to get Javascript, and is instead getting an HTML document, which it apparently can't parse. I've tried adding a config object to the request based on the angular docs: $http.jsonp( {url: iucnUrl, responseType: 'text'} ) without any luck.
My question is, how do I work with the returned HTML document, or am I way off track here?
Response from the API is an HTML document with a javascript extension:
On the page you linked to in your comment , I found some potentially useful information under the heading API Index.
You can actually get JSON for all levels of taxonomy, including your example Aneides aeneus. However, this JSON doesn't include all of the data from the HTML version, so it's not as useful. Hopefully this helps a little.
API Index (excerpt)
It is also possible to retrieve the row(s) of the index corresponding to an individual species:
http://iucn-redlist-api.heroku.com/index/species/panthera-leo.json
You can use dashes for spaces, as a convenient replacement for the standard URL escape, %20.
The HTML format contains direct links to the species account pages. The CSV and JSON formats include a species_id column which can be used to construct species account URLs as follows:
http://iucn-redlist-api.heroku.com/details/species_id/0
To use the index JSON in Web pages directly, you may need JSONP padding; use the “.js” extension and add a “callback” parameter with the name of the function to use.
http://iucn-redlist-api.heroku.com/index/genus/Dioscorea.js?callback=show
I diagonally looked over the website and its sitemap and found no reference to a public API. All the output is HTML, and it makes sense that json parse method jsonp will not be able to make sense of it. First < it encounters, it will fail (as is apparent).
First of all, I would contact the site admin to simply ask if there is an API that will yield you XML or json or some other object notation that's convenient to work with.
Then there's the scenario where his or her answer would be 'no':
Parsing HTML is not something to be taken lightly and certainly not something you would write yourself unless absolutely necessary.
Luckily, there are ways to get data from html using jQuery.parseHTML(), pure ('vanilla') javascript ways you can use from within AngularJS and full-blown HTML parsing libraries such as HTML Agility Pack(for use in .NET), all of which can get you to the heart of the data within the DOM nodes you're trying to poke at.
There are many other libraries that might serve you better, but these examples will give you a good starting point to canvas the landscape of HTML parsing. This will take some looking into, but it will be more than worth it.
I am using the $.ajaxSetup() function to append some additional params to each of my AJAX calls in Spine. However it isn't working as i'd expect it to.
If i call $ajaxSetup() as follows, my GET requests work fine, but my params are overidden with any POST requests and are not included in the form data as id expect:
$.ajaxSetup
data: "user_email=foo#bar.com&user_token=foobar"
As a result i tried changing my data string to an object to see if that made any difference:
settings =
data:
user_email:'foo#bar.com'
user_token:'foobar'
$.ajaxSetup settings
However that causes my URL's in my requests to appear malformed, like so:
http://dev.myapp.com:5000/api/v1/posts?[object%20Object]
I've tried recreating this in JSFiddle (my fiddle) to test that i wasn't going mad and it seems that my approach works as i'd expect over there. For GET requests, a string of my data object is appended to the end of my URL and with POST requests the data object is appended to the form data sent with the request.
So what am i doing wrong? Is this a bug in Spine or something else?
jQuery Version: 2.0.3
It looks like the problem is that spine sets data as a string:
type: 'POST'
contentType: 'application/json'
data: #record.toJSON()
(from the spine source)
You can use ajaxPrefilter to fix up requests before they are sent. Since the data is a JSON string you have a couple of options:
add your parameters to the JSON (by decoding it, using $.extend, then encoding it again)
add your parameters as custom HTTP headers instead of POST parameters
add the parameters to the URL, even on POST requests
I have a Node.js app which, among other things, responds to a AJAX (jQuery) $.get() request from a Web page by sending some HTML back to that page. The app uses Express.
So in the server code, I have:
app.get('/friends', api.friends);, where api is defined as api = require('./static/routes/api') and i'm setting app.use(app.router);.
In myapi.js module, I have api.friends code: I have
exports.friends = function(request, response)
{
...lots of code...
};
wherein I create some specific HTML.
Now, my question is: How do I actually send this HTML back to the client? I can't use the passed-in response object because this is no longer an Express-type response object, so the usual reponse.send(), .end(), etc. methods don't exist.
I have no idea what to do, reflecting a lack of understanding of Node and its innards (this is my first Node app), so any and all help will be greatly appreciated and welcomed. Thank you.
As #Daniel stated in his comment, the response object is certainly an Express object, and you can return your HTML simply by rendering a view, like so:
exports.friends = function(request, response) {
//do stuff
response.render('friends.html');
};
Of course, you would have to define your views in your app.js setup, with something like this:
app.set('views', __dirname + '/views')
Ugh! I am such an idiot! In my exports.friends handler, there's a request going out which, as a part of its calling parameters, takes a function of the form function(error, response, body). Note the response parameter. I was sending the results within this function, which of course used this response object and not the one passed through exports.friends(request, response). Doh. Oh well - thank you anyway - you made me look at the code again, and with the persepctive of knowing that the response object was legitimate, I was able to see the error. Thank you again - appreciated!
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.