Prototype AJAX Post Parameters missing randomly - javascript

Alright, so i have a .NET application that uses the Prototype library to make AJAX calls to webmethods in the page-behind to retrieve data. This application has been up and running for quite awhile with no issues. Recently a new user began using the application and experiencing some weird issues.
Basically, what happens is he can use the application fine for awhile and then it just starts throwing errors on AJAX calls stating parameters are missing to the webmethod. Here is the error:
System.InvalidOperationException - Unable to perform the requested action: Invalid web service call, missing value for parameter: 'fleet'.
at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary'2 parameters)
at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary'2 parameters)
AT SYSTEM.WEB.SCRIPT.SERVICES.RESTHANDLER.INVOKEMETHOD(HTTPCONTEXT CONTEXT, WEBSERVICEMETHODDATA METHODDATA, IDICTIONARY`2 RAWPARAMS)
at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)
It isn't just one call that messes up but any ajax call randomnly and it always seems to be the first parameter in the webmethod that is called "missing." leading me to believe the post data isn't gettin back somehow? (related?: JQuery Ajax post parameters sometimes not sent on IE).
I have never been able to recreate this issue, nor has any other user experienced it. This leads me to believe it is something specific on this users system that is causing the issue. Unfortunately they are a rather important user so i need to attempt to solve this problem. The user has IE8 as their browser. Here is the code that makes the ajax call using prototype:
function gAjax(url, params, onSuccess, onError, onException, onComplete) {
new Ajax.Request(url,
{
method:'post', //Post
contentType:"application/json; charset=utf-8", //As JSON
postBody:Object.toJSON(params), //Post Body is JSON string
sanitizeJSON:true, //Sanitize the JSON
onComplete:onComplete, //Set user on complete
onSuccess:onSuccess, //Set user on success
onFailure:onError, //Set user on error
onException:onException //Set user on exception
});
}
onComplete, onSuccess, onError, onException are function callbacks. params is an object like the following:
{'fleet':'fleetVal','bin':1234}
Url is the method, such as Bin.aspx/LoadBinInfo. This method is defined in the backend as follows:
<System.Web.Services.WebMethod()> _
Public Shared Function LoadBinInfo(ByVal fleet As String, ByVal bin As Integer) As Dictionary(Of String, Object)
'.....
'Returns a dictionary of info
End Function
If anyone has any ideas as to what is happening i would greatly appreciate any input! I can't seem to find any information in my research to lead me to the possible cause. Again it seems to only happen to this one user, so maybe its a browser setting on his end (any ideas what setting?). But then again its sporadic for him even, but once it starts happening it happens constantly until he closes out the browser and starts over.

I'm answering here because it seems I don't have enough reputation as to comment rather than answering.
It's not very clear what is missing from the request, but I'd go on checking the web logs (or setting some sort of logging) to see what the system is actually receiving. According to your description of the problem, the request is somehow missing the 'fleet' parameter. But you are not sending such value isolated in the request, you're sending all data in the post body as a serialized JSON string.
So, either the data passed to gAjax is not correct/complete, or something strange is happening on your server.
I obviously suspect that it's the former, but anyway you should try to log and debug on both ends.
For a start, I'd do something like this:
function gAjax(url, params, onSuccess, onError, onException, onComplete) {
params['debug']=Object.toJSON(params);
new Ajax.Request(url,
//....
That will add the JSON string to the request so you can check exactly what is being sent.
Hope this helps!

Related

Slow Webservice Callback

The question is about speeding up the loading of a ASP.NET web app, and I found that the loading time of the filtering feature of the web app is unacceptable. The filter list is generated from a database. Please see the following code:
This function is in .js and is invoking the webservice method.
function filterSetup() {
filterChanged = true;
var reset = true;
DDL_WebService.fillFilter(SucceededCallbackWithContext, FailedCallback,new ddlContext("My_Filter", reset));
filterSystemSetup();
}
This function is in .js too and is executed after the webservice method.
function SucceededCallbackWithContext(result, userContext) {
var ddl = $get(userContext.cntrl);
var curVal = userContext.getVal();
// Fetching result...
}
This function is one method in a web service file called "DDL_WebService.vb". It is in .vb and is getting the data from a database.
<WebMethod()> _
Public Function fillFilter() As List(Of String)
Dim strSQL As String
strSQL = "select '(All)' from My_Table "
Return getData(strSQL)
End Function
Problem: I thought after the last line of fillFilter(), it should go to SucceededCallbackWithContext()in almost no time (The step-into command tells me nothing happens in between too). However, getting to SucceededCallbackWithContext() from the last line of fillFilter() takes around 7 seconds.
I am not sure what is taking the time and how can I confirm and resolve that.
Any help is greatly appreciated :)
Updates:
Looking at the problem from another angle using Developer tool, I get the result shown in the sceenshot. Now my question becomes what are the possible reasons that some methods take too long to run (Note: For the webservice method with the longest request time, I speed up the query from 10 seconds to less than 3 seconds, but the request time is still arount 15 seconds). Could it be that the executing of one webservice method would affect the speed of another webservice method? Thanks again!
If you are going to filter data why you try to load all records with all columns?
If your my_table records is around 1000 or less than 1000(I mean you have a small data set) you can not understand performance issue but after a while as your data grow(for example it reaches up to 100000) you notice that your service is getting slower and slower.
If you query is not your main query in code so first use browsers developer tools or any other tools to measure response time of your service to be sure that problem is in your server side codes or in your javascript codes
Try to compress your datataTable before sending it !I share with you two functions thaallow the compression and decompression :
Public Shared Function CompressData(ByVal ds As DataSet) As Byte()
Try
Dim data As Byte()
Dim memStream As New MemoryStream()
Dim zipStream As GZipStream = New GZipStream(memStream, CompressionMode.Compress)
ds.WriteXml(zipStream, XmlWriteMode.WriteSchema)
zipStream.Close()
data = memStream.ToArray()
memStream.Close()
Return data
Catch ex As Exception
Return Nothing
End Try
End Function
Public Shared Function DecompressData(ByVal data As Byte()) As DataSet
Try
Dim memStream As New MemoryStream(data)
Dim unzipStream As New GZipStream(memStream, CompressionMode.Decompress)
Dim objDataSet As New DataSet()
objDataSet.ReadXml(unzipStream, XmlReadMode.ReadSchema)
unzipStream.Close()
memStream.Close()
Return objDataSet
Catch ex As Exception
Return Nothing
End Try
End Function
Hope help you.
Although it has been a long time since I posted the question, I still want to update my progress on this problem just to thanks Beldi and mostafa for the suggestions and to give people some hints when having similar issues.
Overall the problem has not been resolve but we came up with a workaround.
We were guessing that some queries might take a long time to finish, so I carved out all the queries that take a long time according to the developer tool. I tested them one by one and found that they are all pretty fast. In the next quite a bit of time, I was stuck on verifying what the developer tool indicates.
One breakthrough happens when I dissect the following code:
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "dataservice/getSimData_WebService.asmx/getSimsList",
data: JSON.stringify(params),
dataType: "json",
success: function (data, textStatus) {
if (textStatus == "success") {
var thegrid = $("#jqGrid_sims")[0];
thegrid.addJSONData(data.d);
}
},
error: function (data, textStatus) {
alert("Error from get grid data");
}
});
In this piece of ajax call, the code sends out the request upon executing. The time between the beginning of the execution and the beginning of the if statement is requesting time, and that is the time the developer tool indicates.The time that code inside if statement spends is the fetching time.
After looking into the requesting time and the fetching time for each ajax call, I found the fetching time for a simulation functionality takes a relatively significant amount of time. Since loading the functionality would cause the page to be frozen and trying to reduce the frozen time has more uncertainties and takes longer, we finally decide to not load it initially. Instead, it will load once a user clicks on a button.
Hope this would help anyone who has similar problems.

Javascript: How did I get here? (Viewing data sent by server, non-AJAX.)

I've got a React-based app that works like this: The user makes a request for "foo", the server returns basic page info (applicable to all pages on the site), and when the client receives this (DOMContentLoaded), it does an AJAX call for the internal details "foo" and renders that.
But is it possible, if I send the data on the first request, to skip the AJAX call? (I tried this previously but was very new to React, which is how I came up with the current scheme. It's come up again because now I'm handling previously saved items.) So, I'm in my DOMContentLoaded listener, and I can see (in the Browser|Network|Response area of Chrome) all the data that has been sent by the server. It's everything I need, and it's right there, but I can't find a way to access it in Javascript.
The searches I've done have almost all turned up AJAX requests. (I am using JQuery, if that helps.) Obviously I can handle loading saved data using the same gag I'm currently using, and maybe that's a an all-around better approach.
So, once again, the question is: Is it possible to look at the response from a non-AJAX place? If it is possible, is it advisable?
Update: Let me walk through an example scenario.
The user goes to "/foo".
The server response is {:some "json"}.
In the Javascript onReady, I can do this:
console.log(window.location);
and I'll see "/foo". But can I see {:some "json"}? And how? Contrast with the AJAX call version:
The user goes to "/foo".
The server response is nothing (i.e., a 200 but no body).
The Javascript onReady has:
$.ajax({
url: "/foo/data"
type: "GET",
success: function (req) {...} //req has {:some data} in it!
So, when I make an AJAX call, I get the request. Is there any way to get that {:some data} on a non-AJAX call? This doesn't work, but I could see something like:
x = window.response();
or
x = Response.last();
Neither of those things exist, of course. I hope that clarifies what I'm looking for.
You could drop a script tag on your server-rendered page that includes a global var accessible by your script bundle. e.g.,
<script>
var myGlobalVar = { ... server data ... } <!-- // note: this is rendered raw by your server
</script>
<script src="myScriptBundle.min.js"></script>
Or, alternatively you could look into server-side rendering, which is possible with React. Check out the implementation in Redux: http://redux.js.org/docs/recipes/ServerRendering.html

Use FormData after passing it to a new function

I'm not sure if this question is worth asking but I can't seem to find a workaround so here I am.
I have a Flask app in which I submit a form that uploads an image to the server. I send the image using FormData that is created this way:
$( "#myform" ).submit(function(event) {
event.preventDefault();
var $form = $(this),
formObject = $('form')[0],
formData = new FormData(formObject);
// other stuff
The FormData is then sent via an AJAX POST request to the sever. This operation works perfectly when the POST request is inside the submit function.
The problem is that in an other view, I need to use the same code but I moved the AJAX POST requests out of the submit function. So when I pass either my formObject or formData to the function that contains the AJAX requests, let's call it fctA, they are undefined.
I think I see the problem, since the submit function has a "particular status" (as you can use $(this) to get the form) but I can't find a way to pass the formData to an other function. I don't want to get rid of fctA since it saves me from duplicating a lot of code (because of client-side verifications)
Is there a way to pass FormData through different function calls?
Thanks in advance.
//Edit: Here's the code where I want to pass the FormData
//(I'm having trouble indenting it here)
$.ajax({
url: "url",
type: "GET",
dataType: "json",
success: function(data) {
//Create a JSON object to send other form inputs
/*
fctA is used to avoid duplicating AJAX POST requests since I
need to send the data only when meeting some expectations and
I must display error messages otherwise.
*/
fctA(json, formObject)
/*
The image is correctly sent if I have a POST request that
uses formData right here instead of passing it to fctA.
As soon as the POST request leaves the submit function to go to fctA though,
formData is undefined when I execute the code.
I tried passing formObject or formData, they are both undefined.
*/
},
error: function() {
//Display an error message
}
});
I am not sure why exactly it does not work, but it is probably caused by your variable scopes. formObject and formData are global variables because you don't declare them with var. fctA is called by the ajax-success-handler in case of a successful ajax-request. formObject is passed to fctA. Where does formObject come from? One might expect that it is available in the global scope. This seems not to be true for some reason.
I recommend to declare variables locally using var and I guess most people will agree. Global variables allow influences between arbitrary pieces of code that are hard to overlook, hard to govern and in effect hard to maintain. Global variables also increase the risk of accidently giving two variables the same name that are meant be distinct variables.
If you declare your variables locally then you can wrap your call to $.ajax in a function with formObject as parameter and call this function in the submit-handler. formObject will also be available in the ajax-success-handler because Javascript supports closures. So, if you use variable scopes the recommended way there is a good chance that you won't have the problem any more.
Alright I found the solution, the problem was that I passed my formData to a function which had a keyword argument as last parameter so the formData was the value of the keyword argument (since the default value was used in that call) and of course, the argument where I expected my formData to be was undefined.
Should I delete the whole question since it's almost no more than a typo problem? The warning that tells you your account may be blocked if you delete too many questions kinds of puts me off.

Run (JS) function if server responded something specific

On one of my pages I have "tracking.php" that makes a request to another server, and if tracking is sucessful in Firebug Net panel I see the response trackingFinished();
Is there an easy way (built-in function) to accomplish something like this:
If ("tracking.php" responded "trackingFinished();") { *redirect*... }
Javascript? PHP? Anything?
The thing is, this "tracking.php" also creates browser and flash cookies (and then responds with trackingfinished(); when they're created). I had a JS that did something like this:
If ("MyCookie" is created) { *redirect*... }
It worked, but if you had MyCookie in your browser from before, it just redirected before "track.php" had the time to create new cookies, so old cookies didn't get overwritten (which I'm trying to accomplish) before the redirection...
The solution I have in mind is to redirect after trackingFinished(); was responded...
I think the better form in javascript to make request from one page to another, without leaving the first is with the ajax method, and this one jQuery make it so easy, you only have to use the ajax function, and pass a little parameters:
$.post(url, {parameter1: parameter1value, param2: param2value})
And you can concatenate some actions:
$.post().done(function(){}).fail(function(){})
And isntead of the ajax, you can use the $.post that is more easy, and use the done and fail method to evaluate the succes of the information recived
As mentioned above, AJAX is the best way to communicate between pages like this. Here's an example of an AJAX request to your track.php page. It uses the success function to see if track.php returned 'trackingFinished();'. If it did then it redirects the page 'redirect.php':
$.ajax({
url: "track.php",
dataType: "text",
success: function(data){
if(data === 'trackingFinished();'){
document.location = 'redirect.php';
}
}
});
The example uses JQuery.

Zend Framework 1.12, ContextSwitch or AjaxContext not disabling layout and other problems

Environment:
Windows 8
Apache 2.4
ZF 1.12
PHP 5.4
YUI framework for the behind-the-scenes connection to the server
I am trying to carry out a very simple ajax/js combination where the user interacts with:
2 of 4 people found this review helpful. Was this review helpful to you? Yes No
When the user hits either yes/no the 2 of 4 should be updated through ajax/js. I have the following code in the init() method of my ReviewController (extends Zend_Controller_Action). Mind you, the view script that follows this action (feedbackAction) is /views/scripts/review/feedback.json.phtml
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('feedback', 'json')
->initContext();
When feedbackAction is executed an exception jumps out stating that it could not find feedback.phtml. This is telling me that AjaxContext is not, in effect, appending the "json" format. Why is this happening?
I read somewhere that the initContext() should be called inside the action. I tried it...same exception.
Then I tried using ContextSwitch, but it seems that it beats the purpose of having AjaxContext be a subclass of ContextSwitch. The code in the init() in ReviewController was replaced by:
$contextSwitch = $this->_helper->getHelper('contextSwitch');
$contextSwitch->addActionContext('feedback', 'json')
->initContext();
This time, inexplicably, the exception does not occur, but instead the following is rendered: the header code (generated by my _header.phtml file called by my layout.phtml file). I don´t understand at all. I had understood (obviously not well) that "addActionContext"+initContext() DISABLED layouts if any was enabled. ¿?
EDIT
I figured out that it wasn´t html content form my _header.phtml file but from another .phtml file that was being rendered because of some actions I had added to my actionStack. Once this was taken care of, what was rendered was the following:
{"originalModule":"default","originalController":"review","originalAction":"feedback","result":true,"id":1,"helpful_yes":"3","helpful_total":"4"}
Which is the variables placed in the $this->view being rendered as json thanks to ContextSwitch helper initiated at the init() method of my ReviewController(). When I say "this was rendred" is because I placed in the address bar the following url: http://localhost/PlacesforKids/public/review/feedback/format/json/id/1/helpful/1
which supposedly is the URL being sent by the YUI framework.
I say "supposedly" because in my javascript success function (being called back by the YUI framework when the ajax call is being executed successfully) I do the fowlling: alert(response), to print out the responce I am getting...and it prints out the whole shabang: html tags, headers...etc. I don´t know how that´s possible.
I thought then that I might be misusing the YUI framework, so I tried to change to jquery.js. To do so I copied the contect of this to a file named jquery.js and placed it under my /public/js directory. Here is the ajax call it´s making to the server:
$.ajax({
url: sUrl,//that would be
//localhost/PlacesforKids/public/review/feedback/format/json/id/$id/helpful/$helpful
type: "GET",
async: false,
success: function(response){
alert(response);
}
});
Here is the HILARIOUS part of all, the action for my ReviewController is NOT being called whatsoever. Instead, the view that was last rendered is re-rendered, meaning it´s re sending the content generated by the view script called by the last action (which belongs to a different controller than ReviewController). I know it´s been re-rendered because in the action that´s the owner of that view script I added this:
if($this->getRequest()->getQuery('ajax') == 1)
throw new Exception ("WRONG controller's action being called");
But it never throws the exception.
EDIT I THINK I GOT IT but I need to know how to clean the baseUrl()
So I opened up the java console on my chrome browser so I could look up the actual http request that my reviewFeedback.js was making through the $.ajax() method. Funny thing, this is what I got:
Request URL:http://localhost/PlacesforKids/public/place/index/id/localhost/PlaceforKids/public/review/feedback/format/json/id/1/helpful/0
Request Method:GET
Status Code:200 OK
Accept:*/*
Referer:http://localhost/PlacesforKids/public/place/index/id/1
X-Requested-With:XMLHttpRequest
WHY in the world is $ajax() APPENDING the url I have as GET to the EXISTING url? It means that whatever url I am trying to generate through my $.ajax() is gettign APPENDED to my "referer". So, I only need to be to CLEAN it and start from zero, for the url I mean... How could I do that in zend framework? Any ideas?
Now if I enter the string in sUrl (localhost/PlaceforKids/public/review/feedback/format/json/id/1/helpful/0) directly onto the address bar in my broswer, it does as it is supposed to do, print out the variables in $this->view that have been set by ReviewController, and send them as json.
{"originalModule":"default","originalController":"review","originalAction":"feedback","result":true,"id":1,"helpful_yes":"3","helpful_total":"4"}
Same problem I had with YUI framework. I´m going crazy.
I could really use the help, thank you.
You need to change the ajax request to asynchronous mode: async: true
Silly silly silly me. Here is the reason why $.ajax() was appending the made up url instead of sending a new one.
$.ajax({
url: sUrl,//that would be
//localhost/PlacesforKids/public/review/feedback/format/json/id/$id/helpful/$helpful
type: "GET",
async: false,
success: function(response){
alert(response);
}
I was writing a GET without a leading "http://", which by default, caused it to append to the existing url.
sUrl was localhost/PlacesforKids/public/review/feedback/format/json/id/$id/helpful/$helpful
and should have been http://localhost/PlacesforKids/public...
Though it still baffles me that ajaxContext did not stop layout rendering as it should have, making me use switchContext instead.
The ajax switch in zend 1.1x.x is only for the "special" html context (if memory serves) and you were trying to set it to a json context.

Categories

Resources