Calling MVC Controller On Periodic Basis in JavaScript

Here is a business use case I am trying to address.  After a web page is loaded, I need to make a server call every so often and make certain parts of the web page visible or hidden based on server call results.  In my case I am checking the state of the object in the database, and return a specific field that indicates that some operation on the entity in question is in progress elsewhere, in a Windows Service in my case.  This way a user who is looing at the screen always knows what is going with the object elsewhere.  You can for example implement some sort of pessimistic concurrency substitute mechanisms, proactively telling the user that they will not be able to save the entity, since another user just updated it.

 

So, in my HTML I define hidden id field and a message area.

<input type="hidden" value="22" id="idField"/>
<div class="progressMessage">
    Server progress returned true
</div>

In my JavaScript I need to define an entry function I will call after the page is loaded to setup timer.

    app.initailizeProgressMessage = function(url) {
        var id = $('#idField').val();
        myApp.setupTimer(url, id, false);
    };

The only parameter to the function is the address of my controller method:

public ActionResult ProgressCheck(string id)
{
    var second = DateTime.Now.Second%2 == 0;
    return Json(second, JsonRequestBehavior.AllowGet);
}

I am faking database call, but you get the idea.  Now I need to setup the next step.

    app.setupTimer = function(url, id) {
        myApp.checkForProgress(id, url, function (result) {
            if (result) {
                $('.progressMessage').show();
            } else {
                $('.progressMessage').hide();
            }
            setTimeout(function() {
                myApp.setupTimer(url, id);
            }, 1000);
        });

    };

As you can see, I am making an Ajax call by calling checkForProgress function (see below).  This call just calls controller and returns true/false, which I use to set visibility of my message div. You will also notice the recursive call to setupTimer, which is how you have to use setTimeout function in order to have it firing continuously.

    app.checkForProgress = function (id, url, callbackFunction) {
        try {
            $.ajax({
                url: url,
                data: { id: id },
                type: 'get',
                datatype: 'json',
                success: function(data) {
                    callbackFunction(data);
                },
                error: function(xhr, textStatus, errorThrown) {
                    callbackFunction(false);
                    if (xhr.status != 0) {
                        alert('Error');
                    }
                },
                global: false // override to keep regular ajaxStart ajaxEnd from firing
            });
        } catch(e) {
            callbackFunction(false);
        }
    };

There is one interesting thing here. I am setting global option to false.  The reason for that is because I am using ajaxStart and ajaxEnd global jQuery events to hide / show “Please Wait ” message to the user during Ajax calls to the server.  In my error handler I have to check to status != 0 because if I refresh the page while ajax call is in progress, my error handler is called.  Hence, your handler must be setup as such.  You can download the sample project here.

Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *