I have been sorting through this issue all day and hope someone can help pinpoint my problem. I have created a “asynchronous progress callback” type functionality in my app using ajax. When I strip the functionality out into a test application I get the desired results. See image below:
Desired Functionality

When I tie the functionality into my single page application using the same code I get a sort of blocking issue where all requests are responded to only after the last task has completed. In the test app above all request are responded to in order. The server reports a (“pending”) state for all requests until the controller method has completed. Can anyone give me a hint as to what could cause the change in behavior?
Not Desired

Desired Fiddler Request/Response
GET http://localhost:12028/task/status?_=1383333945335 HTTP/1.1 X-ProgressBar-TaskId: 892183768 Accept: */* X-Requested-With: XMLHttpRequest Referer: http://localhost:12028/ Accept-Language: en-US Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0) Connection: Keep-Alive DNT: 1 Host: localhost:12028 HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=utf-8 Vary: Accept-Encoding Server: Microsoft-IIS/8.0 X-AspNetMvc-Version: 3.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?QzpcUHJvamVjdHNcVEVNUFxQcm9ncmVzc0Jhclx0YXNrXHN0YXR1cw==?= X-Powered-By: ASP.NET Date: Fri, 01 Nov 2013 21:39:08 GMT Content-Length: 25 Iteration completed...
Not Desired Fiddler Request/Response
GET http://localhost:60171/_Test/status?_=1383341766884 HTTP/1.1 X-ProgressBar-TaskId: 838217998 Accept: */* X-Requested-With: XMLHttpRequest Referer: http://localhost:60171/Report/Index Accept-Language: en-US Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0) Connection: Keep-Alive DNT: 1 Host: localhost:60171 Pragma: no-cache Cookie: ASP.NET_SessionId=rjli2jb0wyjrgxjqjsicdhdi; AspxAutoDetectCookieSupport=1; TTREPORTS_1_0=CC2A501EF499F9F...; __RequestVerificationToken=6klOoK6lSXR51zCVaDNhuaF6Blual0l8_JH1QTW9W6L-3LroNbyi6WvN6qiqv-PjqpCy7oEmNnAd9s0UONASmBQhUu8aechFYq7EXKzu7WSybObivq46djrE1lvkm6hNXgeLNLYmV0ORmGJeLWDyvA2 HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=utf-8 Vary: Accept-Encoding Server: Microsoft-IIS/8.0 X-AspNetMvc-Version: 4.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?QzpcUHJvamVjdHNcSUxlYXJuLlJlcG9ydHMuV2ViXHRydW5rXElMZWFybi5SZXBvcnRzLldlYlxfVGVzdFxzdGF0dXM=?= X-Powered-By: ASP.NET Date: Fri, 01 Nov 2013 21:37:48 GMT Content-Length: 25 Iteration completed...
The only difference in the two requests headers besides the auth tokens is “Pragma: no-cache” in the request and the asp.net version in the response.
Thanks
Update – Code posted (I probably need to indicate this code originated from an article by Dino Esposito )
var ilProgressWorker = function () {
var that = {};
that._xhr = null;
that._taskId = 0;
that._timerId = 0;
that._progressUrl = "";
that._abortUrl = "";
that._interval = 500;
that._userDefinedProgressCallback = null;
that._taskCompletedCallback = null;
that._taskAbortedCallback = null;
that.createTaskId = function () {
var _minNumber = 100,
_maxNumber = 1000000000;
return _minNumber + Math.floor(Math.random() * _maxNumber);
};
// Set progress callback
that.callback = function (userCallback, completedCallback, abortedCallback) {
that._userDefinedProgressCallback = userCallback;
that._taskCompletedCallback = completedCallback;
that._taskAbortedCallback = abortedCallback;
return this;
};
// Set frequency of refresh
that.setInterval = function (interval) {
that._interval = interval;
return this;
};
// Abort the operation
that.abort = function () {
// if (_xhr !== null)
// _xhr.abort();
if (that._abortUrl != null && that._abortUrl != "") {
$.ajax({
url: that._abortUrl,
cache: false,
headers: { 'X-ProgressBar-TaskId': that._taskId }
});
}
};
// INTERNAL FUNCTION
that._internalProgressCallback = function () {
that._timerId = window.setTimeout(that._internalProgressCallback, that._interval);
$.ajax({
url: that._progressUrl,
cache: false,
headers: { 'X-ProgressBar-TaskId': that._taskId },
success: function (status) {
if (that._userDefinedProgressCallback != null)
that._userDefinedProgressCallback(status);
},
complete: function (data) {
var i=0;
},
});
};
// Invoke the URL and monitor its progress
that.start = function (url, progressUrl, abortUrl) {
that._taskId = that.createTaskId();
that._progressUrl = progressUrl;
that._abortUrl = abortUrl;
// Place the Ajax call
_xhr = $.ajax({
url: url,
cache: false,
headers: { 'X-ProgressBar-TaskId': that._taskId },
complete: function () {
if (_xhr.status != 0) return;
if (that._taskAbortedCallback != null)
that._taskAbortedCallback();
that.end();
},
success: function (data) {
if (that._taskCompletedCallback != null)
that._taskCompletedCallback(data);
that.end();
}
});
// Start the progress callback (if any)
if (that._userDefinedProgressCallback == null || that._progressUrl === "")
return this;
that._timerId = window.setTimeout(that._internalProgressCallback, that._interval);
};
// Finalize the task
that.end = function () {
that._taskId = 0;
window.clearTimeout(that._timerId);
}
return that;
};
Update 1 – Many thanks to John Saunders. I was able to locate this article that explains what John was implying in his comment about serialized access
“It blocks parallel execution and forces parallel requests to be executed one after another because the access to ASP.NET Session state is exclusive per session“
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
I found a fix at last. The session state can be controlled at the Controller and/or Controller Method level. Since the authorization is being verified at a higher level there is no need to use session in what I am doing. I simply disable it for the unit of work.
[SessionState(SessionStateBehavior.Disabled)] public class _TestController : ProgressWorkerController
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0