Azure web role receiving results from a long process - ajax

My Azure web role uses Ajax to call a function (in default.aspx.cs) that delegates work to worker roles. Worker roles may take up to 30-40 minutes depending on input file selected by user. If the worker roles return the result quickly it is received by the webrole and displays correctly on the web page. If it takes long the results are still received by the webrole (tried printing to trace) but nothing gets displayed on the web page.
I feel there is some kind of time out that kills the connection between the ajax code on the page and the webrole.
The code looks like:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<script type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function () {
var params = '{ map1 : "' + document.getElementById('<%=ddlMap1.ClientID %>').value + '",' +
'map2 : "' + document.getElementById('<%=ddlMap2.ClientID %>').value + '",' +
'op : "' + document.getElementById('<%=ddlOperator.ClientID %>').value + '"}';
$('#spinner').show();
$('#results').text('');
$.ajax({
type: "POST",
url: "Default.aspx/Overlay",
data: params,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var dmsg = '';
if (msg == null) {
dmsg = 'null';
} else {
dmsg = msg.d;
}
$('#spinner').hide();
$('#results').text(dmsg);
},
error: function (error) {
$('#results').text('');
}
});
});
});
</script>

The azure load balancer kills any inactive connections after 1 minute. See my answer to this question about how to work around this problem.

I would try to override the default timeout value of jquery to see if it helps:
$.ajaxSetup({
timeout: 3600000 // one hour
});
This issue could be caused by jquery but also be dependent on browser and network settings as stated in this SO question.

Related

Harvest Chosen multiselect dropdownlist inconsistently populates with set value

I have a ASP.net webform populated with data from a MS SQL DB, and allows you to edit values.
The web app uses a Harvest Chosen multiselect dropdown list (max=1) to select two different persons picked from the same list of information, but on two separate controls.
When I refresh the page, sometimes both controls are populated with the correct value, sometimes neither or one are. I tested in the console and it is definitely pulling the correct information from the DB, but I must be missing something relating to how these procedures are executed. I have done this work with VB.NET and ASP controllers in the past. This is my first time using AJAX and web method functions. I believe I am missing an update somewhere, or not understanding the order in which code is executed.
I tried explicitly stating the order of operations in the .aspx page, and then doing no update triggers until after all the code for the controller had been executed, but this appears to have broken both controllers (the both end up looking like normal select controllers). Apologies if my terminology is not on point, I am very self-taught. The current state of the code where I get inconsistent application
The .aspx page is as such. Each control has a set of different parameters that affect how it is populated, and what happens when it changes.
<select class="chosen-select" multiple data-placeholder="Assign a scientist" name="ChosenScientist" style="width:800px;" id="cmbChosenScientist">
<script type="text/javascript">
handleChosenControls("select#cmbChosenScientist.chosen-select");
</script>
</select>
<select class="chosen-select" multiple data-placeholder="Assign a supervisor" name="ChosenSupervisor" style="width:800px;" id="cmbChosenSupervisor">
<script type="text/javascript">
handleChosenControls("select#cmbChosenSupervisor.chosen-select");
</script>
</select>
The aspx page passes the controller name to a function which first defines all of the parameters used by the controllers.
function defineChosenControls(controller) {
switch (controller) {
case "select#cmbChosenScientist.chosen-select":
currentData = JSON.stringify({ sqlQueryName: "studyScientist" + "/" + MainContent_txbStudy.value });
populateData = JSON.stringify({ sqlQueryName: "userList" });
changeData = JSON.stringify({ strControlName: controller, arrValues: JSON.stringify($(controller).val()), strArg1: MainContent_txbStudy.value });
break;
case "select#cmbChosenSupervisor.chosen-select":
currentData = JSON.stringify({ sqlQueryName: "studySupervisor" + "/" + MainContent_txbStudy.value });
populateData = JSON.stringify({ sqlQueryName: "userList" });
changeData = JSON.stringify({ strControlName: controller, arrValues: JSON.stringify($(controller).val()), strArg1: MainContent_txbStudy.value });
break;
}
}
The function that handles the populating the options, setting the current value, and handling changes is as follows:
function handleChosenControls(controller) {
//Purpose: Any time a Chosen control is loaded, changed, etc., this is run.
defineChosenControls(controller);
$(controller).chosen({ max_selected_options: 1 });
//Script for populating the control
$.ajax({
type: "POST",
url: "ClientToServer.aspx/GetDT",
data: populateData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
for (line of JSON.parse(response.d)) {
$(controller).append('<option value="' + line[Object.keys(line)[0]] + '">' + line[Object.keys(line)[0]] + '</option>');
}
$(controller).trigger("chosen:updated");
},
error: function (response) { console.log("ERROR: Unable to pass changed values from controller " + controller + " to server-side."); }
});
//Script for determining current value during load
$.ajax({
type: "POST",
url: "ClientToServer.aspx/GetDT",
data: currentData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
for (line of JSON.parse(response.d)) {
$(controller).val(line[Object.keys(line)[0]]).trigger("liszt:updated");
console.log(line[Object.keys(line)[0]]);
}
$(controller).trigger("chosen:updated");
},
error: function (response) { console.log("ERROR: Unable to retrieve current value of " + controller + " from server-side."); }
});
//Script for when a value in the control is changed
$(controller).on('change', function (e) {
defineChosenControls(controller);
$.ajax({
type: "POST",
url: "ClientToServer.aspx/PassJqueryControlValue",
data: changeData,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
},
error: function (response) { console.log("ERROR: Unable to pass changed values from controller " + controller + " to server-side."); }
});
});
}
I expect both controls to have the proper value in the DB, and those values are being written in the browser console properly, but the harvest chosen controls are inconsistent.
The solution was to call the code after load.
<script type="text/javascript">
$(window).bind("load", function() {
handleChosenControls("select#cmbChosenScientist.chosen-select");
handleChosenControls("select#cmbChosenSupervisor.chosen-select");
});

Concurrent coldfusion ORM database requests fail

I'm new to coldfusion and am trying out the ORM (Hibernate, I believe, which I don't know at all)
I came across a problem when trying to call two CF pages in rapid succession. The code on the two pages is super simple:
getAppointments.cfm:
<cfscript>
ORMReload();
appointments = serializeJSON(EntityLoad("Appointment"));
</cfscript>
<cfoutput>#appointments#</cfoutput>
getRooms.cfm:
<cfscript>
ORMReload();
rooms = serializeJSON(EntityLoad("Room"));
</cfscript>
<cfoutput>#rooms#</cfoutput>
The code that I use to call them is jQuery/AJAX:
var appointments;
var rooms;
$(document).ready(function () {
loadAppointments();
loadRooms();
});
function loadAppointments() {
$.ajax({
type: 'get',
url: 'getAppointments.cfm'
}).done(function (response) {
appointments = JSON.parse(response);
}).fail(function (response) {
var message = response.status + " - " + response.statusText;
alert("Failed to load appointments: " + message);
});
}
function loadRooms() {
$.ajax({
type: 'get',
url: 'getRooms.cfm'
}).done(function (jsonString) {
rooms = JSON.parse(jsonString);
}).fail(function (response) {
var message = response.status + " - " + response.statusText;
alert("Failed to load rooms: " + message);
})
}
If I set a breakpoint to pause execution before loadRooms() is called, all is well. If I let the code run straight through I get a 500 error, so it's pretty obvious that I'm running into some sort of concurrency issue with the ORM due to the asynchronous nature of the AJAX calls.
I'm running CF on IIS (localhost), with an SQL Server database.
None of the tutorials on CF that I've seen covers this kind of scenario. I know I could defer execution inside the JS functions, but that would only be masking the underlying problem.
Can anybody point me towards a solution? Is there something similar to a C# lock available in CF?
You are applying ORMReload() with each call which is causing to reload all entities, clear orm cache etc.
Please read about ORMReload(), it should only be used once whenever you make changes in your entity CFCs.

Can I use SignalR 3 or AJAX to stop timeout for long file downloads

I have an ajax POST that sends a CSV file to the server. I have signalR 3 working to inform the client as to where its up to with the 16000 odd records its processing via a progress bar. It works.... for small files with processing finishing in less than two minutes. Any time processing takes longer it times out.
I have looked here and its not what I require.. and
I have tried adding an extended timeout using ".timeout: 600000" on the POST but that doesnt work. It still times out at 2 minutes but processing works and the database is still updated and it even tries to send back those records that were new.
Can I use a SignalR server call to keep the session alive? (how, with SignalR 3)?
can I use AJAX?
I need it to wait just over 8 minutes to avoid timeout.
AJAX code:
//On button click POST file and signalR connection Id back to controller.
$('#SubmitFile').click(function (e) {
e.preventDefault(); // <------------------ stop default behaviour of button
var url = "/SuburbsAndPostcodesAdmin/FileIndexView";
var connId = $.connection.hub.id;
var fd = new FormData();
fd.append('File', $("#txtFileUpload")[0].files[0]);
fd.append('connId', connId);
//Post back the file with the SignalR Id.
$.ajax({
type: "POST",
url: url,
data: fd,
processData: false,
contentType: false,
success: function (result) {
//display the results in a partial view.
$("#DisplayResults").html(result);
},
error: function (xhr, status, error) {
alert(xhr.responseText);
},
});
});
SignalR client code:
// Reference the auto-generated proxy for the hub.
var progress = $.connection.progressHub;
// Start the connection.
$.connection.hub.start().done(function () {
connectionId = $.connection.hub.id;
$("#SubmitFile").removeAttr("disabled");
$("#initialise").html("<h4>" + "Ready to upload" + "</h4>" + "<br /> " + "<br />");
});
updating progress bar:
//Send from server to the client process current notification.
progress.client.notifyProgress = function (processedRecords, newRecords, percentage) {
$("#NoOfRecordsProcessedValue").text(processedRecords);
$("#NoOfNewRecordsFoundValue").text(newRecords);
$('.progress-bar')
.css('width', percentage + '%')
.attr('aria-valuenow', percentage);
if (percentage > 5) {
$("#workDone").text(percentage + "%");
}
};

Refreshing data in a div with ajax

I'm developing a Phonegap based app which shows some data that is stored in a remote server. How can I make it refresh data every certain time in case an error happened and it didn't get the data the first time?
this is the list.js
$(document).ready(function(){
var output = $('#vehiculosOutput');
$.ajax({
url: 'http://www.periodicosonofertas.com/mobile/conexVehiculos.php',
dataType: 'jsonp',
jsonp: 'jsoncallback',
timeout: 5000,
success: function(data, status){
$.each(data, function(i,item){
var landmark = '<li>'+item.name + '<p></p>'
+ '<p><font style="white-space:normal; font-size: small" >'+item.descripcion+'</p>' + '<p>'+item.contacto+'</p>' + '<p>'+item.telefono+'</p>' + '<p>'+item.correo+'</p><p>'+status+'</p></li>';
output.append(landmark);
});
},
error: function(){
output.text('Error');
//setTimeout(func.updateStatus, 1000);
}
});
});
You can use long polling for this. In case if you haven't heard about it, this is a good place to start.
If you need to resend the request only in error case, the following snippet would work.
(function poll(delay){
setTimeout(function(){
$.ajax({
url: "http://127.0.0.1:8000/time/",
success: function(data){
$('#requiredDivId').text(data.value);
},
error: function(data){
//Recursive **Poll**
poll(30000);
},
dataType: "json"
});
}, delay);
})(0);
If you want to go with specific feature you mentioned in your comment then there is a function named network.isReachable(You can find more details here) in phonegap. You can put that function to check whether connection is on or not within settimeout function and if its true then you can run function to send data to server.
I hope it'll help you

Pass Ajax POST variable to JQuery UI dialog

Below is an Ajax POST variable I use to return some information to an ASP MVC3 View. However, I cannot get the .dialg() pop-up function to work. Right now you click on the icon that calls GetProgramDetails(pgmname), and nothing happens. First time using Ajax, so any suggestions would be appreciated. Thx!
<script src="http://code.jquery.com/jquery-1.8.3.js" type="text/javascript"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js" type="text/javascript"></script>
<script type="text/javascript">
function GetProgramDetails(pgmname) {
var request = $.ajax({
type: 'POST',
url: '/BatchPrograms/PopDetails',
data: { programName: pgmname },
dataType: 'html'
});
request.done(function (data) {
$('#data').dialog();
});
</script>
EDIT
I've updated the request.done function to include a simple alert to see if the code was being called. After stepping through with Chrome's debugger, I saw that the code inside was completely skipped over.
request.done(function (data) {
alert("HERE!");
$('#programExplanation').html(data);
});
SECOND EDIT
Here is the controller code the ajax is returning a value from:
[HttpPost]
public string PopDetails(string programName)
{
BatchPrograms batchprograms = db.BatchPrograms.Find(programName);
if (batchprograms == null) return string.Empty;
StringBuilder s = new StringBuilder();
s.Append(batchprograms.ProgramName + " - " + batchprograms.ShortDescription);
s.Append("<br />Job Names: " + batchprograms.PrdJobName + ", " + batchprograms.QuaJobName );
s.Append("<br /> " + batchprograms.Description);
return s.ToString();
}
You need to use the success method to handle the callback, like so:
var request = $.ajax({
type: 'POST',
url: '/BatchPrograms/PopDetails',
data: { programName: pgmname },
dataType: 'html'
}).success(function(data){ $('#data').dialog()} );
This will launch the dialog for you, but if you want to get the response data to work with it, you can have GetProgramDetails take a second parameter which is a callback for after the data is loaded like so:
function GetProgramDetails(pgmname, callback) {
var request = $.ajax({
type: 'POST',
url: '/BatchPrograms/PopDetails',
data: { programName: pgmname },
dataType: 'html'
}).success(callback);
}
This way after the response is received you can handle what to do with the data in your implementation of the callback, in this case it seems like you will be setting data in the dialog and launching the dialog.

Resources