I am just using the new Async Controller features in MVC 4 as described here http://www.asp.net/mvc/tutorials/mvc-4/using-asynchronous-methods-in-aspnet-mvc-4
If I have an action that may take 10-20 seconds to run I would like to provide some kind of status bar to notify the user of progress. Do the Async features have anything to help this out?
EDIT: I will take a stab at how I will try and do it and see if there are any better ways
public async Task<ActionResult> GizmosAsync()
{
return View("Gizmos", await GetGizmosAsync());
}
private void GetGizmosAsync()
{
for(int i=0; i<10; i++)
{
lock(_locker)
{
_statusMessage = String.Format("{0} of 10", i);
}
DoSomethingLongRunning();
}
}
public ActionResult Status()
{
return Json(new { Status = _statusMessage });
}
static readonly object _locker = new object();
static string _statusMessage = "";
....
<script>
setTimeout(displayStatus, 1000);
function displayStatus() {
$.post("/controller/status", function(data) {
alert(data.Status);
});
}
</script>
Async controllers is just a mechanism for freeing threads from the ThreadPool in IIS in order to be able to handle incoming requests during heavy load, but the communication with the client remains as the usual request-response.
Status bars and the sort are usually just javascript displaying something on screen until the ajax request finishes. I don't think MVC4 will be of aid in that part.
You could do something like this: https://stackoverflow.com/a/68503/1373170 to display a "processing..." <div>
during ajax calls.
EDIT: If you need real client progress and interaction (such as real progress), you should check out SignalR http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx And this related post: Async Controllers (MVC), long running process with "stops"
This article seems to describe what you want:
ASP.NET MVC 3: Async jQuery progress indicator for long running tasks
Controller:
public class HomeController : Controller
{
private static IDictionary<Guid, int> tasks = new Dictionary<Guid, int>();
public ActionResult Index()
{
return View();
}
public ActionResult Start()
{
var taskId = Guid.NewGuid();
tasks.Add(taskId, 0);
Task.Factory.StartNew(() =>
{
for (var i = 0; i <= 100; i++)
{
tasks[taskId] = i; // update task progress
Thread.Sleep(50); // simulate long running operation
}
tasks.Remove(taskId);
});
return Json(taskId);
}
public ActionResult Progress(Guid id)
{
return Json(tasks.Keys.Contains(id) ? tasks[id] : 100);
}
}
View:
<script type="text/javascript">
function updateMonitor(taskId, status) {
$("#" + taskId).html("Task [" + taskId + "]: " + status);
}
$(function () {
$("#start").click(function (e) {
e.preventDefault();
$.post("Home/Start", {}, function (taskId) {
// Init monitors
$("#monitors").append($("<p id='" + taskId + "'/>"));
updateMonitor(taskId, "Started");
// Periodically update monitors
var intervalId = setInterval(function () {
$.post("Home/Progress", { id: taskId }, function (progress) {
if (progress >= 100) {
updateMonitor(taskId, "Completed");
clearInterval(intervalId);
} else {
updateMonitor(taskId, progress + "%");
}
});
}, 100);
});
});
});
</script>
<div id="monitors"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With