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>
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
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”
Method 2
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>
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