Implementing a Progress bar for long running task implemented with an ASP.NET MVC 2 AsyncController

前端 未结 1 626
醉梦人生
醉梦人生 2020-12-05 03:23

After reading the documentation on AsyncControllers in ASP.NET MVC 2, I am wondering what\'s the best way to implement an ajax progress bar in this scenario. It seems a bit

相关标签:
1条回答
  • 2020-12-05 04:09

    Very interesting question! Actually it seems that it is not a task for AsyncController. Async controllers are designed for long-running single-HTTP-query operations at server-side. When you are using async action, this could only help you to release ASP.Net worker thread during some long-running operation(s) and allow it to serve other requests while operation is performed. But from client-side point of view it doesn't matter, is this async controller or not. For client this is just single HTTP request.

    You need to redesign this using some long-running queries service in your application. Here is example of controller, that could serve such workflow:

    public class LongOperationsController : Controller
    {
        public ActionResult StartOperation(OperationData data)
        { 
            Guid operationId = Guid.NewGuid(); // unique identifier for your operation
            OperationsService.DoStartOperation(operationId, data); // service starts to perform operation using separate thread
            return new JsonResult(operationId); // operation id should be sent to client to allow progress monitoring
        }
    
        public ActionResult GetOperationStatus(Guid operationId) 
        {
            var status = OperationsService.GetStatus(operationId); // this method returns some object, that describes status of operation (e.g. progress, current task etc.)
            return new JsonResult(status); // returning it to client
        }
    
        public ActionResult GetOperationResult(Guid operationId)
        {
            var result = OperationsService.GetOperationResult(operationId); // this should throw exception if operation is not yet completed
            return new JsonResult(result);
        }
    
        public ActionResult ClearOperation(Guid operationId)
        {
            OperationsService.ClearOperationResult(operationId); // we should delete operation result if it was handled by client
            return true;
        }
    }
    

    And here are client-side code, that could interact with this controller:

    var operationId;
    function startOperation(data) {
        $.post('/LongOperations/StartOperation', data, function(response) {
            operationId = response; // store operationId
            startOperationMonitoring(); // start
        }, 'json');
    }
    
    function startOperationMonitoring() {
        // todo : periodically call updateOperationStatus() to check status at server-side
    }
    
    function updateOperationStatus() {
        // todo : get result of GetOperationStatus action from controller 
        // todo : if status is 'running', update progress bar with value from server, if 'completed' - stop operation monitoring and call finishOperation()
    }
    
    function finishOperation() {
        // todo : get result of GetOperationResult action from controller and update UI
        // todo : call ClearOperation action from controller to free resources
    }
    

    This is very basic concept, there are some missed items here, but I hope you will get the main idea. Also it's up to you how to design components of this system, for example:

    • use singleton for OperationsService, or not;
    • where and how long operation result should be stored (DB? Cache? Session?);
    • is it really required to manually release resources and what to do when client stopped to monitor operation (user closed browser) etc.

    Best luck!

    0 讨论(0)
提交回复
热议问题