I have a action method in ASP.NET MVC project (prod app) which imports csv file records and displays progress on progress bar, for this implementation i used this https://stackoverflow.com/a/2928148/1386991, this works well with brand new MVC project (poc app).
But, when I put exact same controller and view (with js code) in my original project (prod app), CheckTaskProgress
methods hits only when RunLongTask
completes the task hence users sees no progress bar update and sudden 100%, that's totally opposite behavior from what I had in brand new project (poc app). Here's visible behavior screenshot for your reference https://www.youtube.com/watch?v=wNa5De0lmdA.
I checked MVC package versions and web.config, this looks fine. Any clue to check ?
Here's controller code:
using System;
using System.Web.Mvc;
using System.Threading.Tasks;
namespace Prod.Web.Controllers
{
public class DemoController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public async Task<ActionResult> RunLongTask()
{
string id = "task_id1"; //should be unique
int maxcount = 200;
AsyncManager.OutstandingOperations.Increment();
await Task.Factory.StartNew(taskId =>
{
HttpContext.Application["t_max_" + taskId] = maxcount;
for (int i = 0; i < maxcount; i++)
{
System.Threading.Thread.Sleep(100);
HttpContext.Application["t_prog_" + taskId] = i;
}
AsyncManager.OutstandingOperations.Decrement();
}, id);
return Json(new { status = true, ProgressCurrent = maxcount, ProgressMax = maxcount, ProgressPercent = 100 });
}
public ActionResult CheckTaskProgress()
{
string id = "task_id1"; //should be unique
var progressCurrent = HttpContext.Application["t_prog_" + id];
var progressMax = HttpContext.Application["t_max_" + id];
decimal progressPercent = (Convert.ToDecimal(progressCurrent) / Convert.ToDecimal(progressMax)) * 100M;
return Json(new
{
ProgressCurrent = progressCurrent,
ProgressMax = progressMax,
ProgressPercent = Convert.ToInt32(progressPercent)
}, JsonRequestBehavior.AllowGet);
}
}
}
And here's view with js code:
@{
ViewBag.Title = "Run ajax long running process and display on progress bar";
}
<div class="main-wrap">
<div class="container">
<div class="row py-5">
<div class="col-12">
<button class="btn btn-primary runlongtask">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" style="display:none;"></span>
Run ajax long running process and display on progress bar
</button>
</div>
<div class="col-12 pt-5">
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="0" style="width:0%"></div>
</div>
</div>
</div>
</div>
</div>
@section foot{
<script>
$(function () {
$('.runlongtask').click(function () {
var triggerbtn = $(this);
triggerbtn.prop('disabled', true).children('.spinner-border').show();
$.ajax({
type: 'POST',
url: '/demo/runlongtask',
success: function (data) {
if (data.status) {
longTaskUpdateProgress(data.ProgressCurrent, data.ProgressMax, data.ProgressPercent);
triggerbtn.prop('disabled', false).children('.spinner-border').hide();
window.clearInterval(longTaskInterval);
}
}
});
var longTaskInterval = window.setInterval(function () {
console.log('interval func invoked');
$.ajax({
type: 'GET',
url: '/demo/checktaskprogress',
success: function (data) {
longTaskUpdateProgress(data.ProgressCurrent, data.ProgressMax, data.ProgressPercent);
}
});
}, 5000);
var longTaskUpdateProgress = function (ProgressCurrent, ProgressMax, ProgressPercent) {
console.log('progressbar func invoked');
$('.progress-bar')
.attr('aria-valuenow', ProgressPercent)
.css('width', ProgressPercent + '%')
.html(ProgressPercent + '% Completed');
console.log(ProgressPercent + ' Completed');
console.log(ProgressCurrent + ' executed out of ' + ProgressMax);
};
});
})
</script>
}
Here's the source code of my project (poc app) on GitHub https://github.com/itorian/Run-Ajax-Long-Process-With-Progress-Bar.