Saturday, August 7, 2010

The jQuery formula - Blocking UI and showing progress dialog across Ajax calls with Asp.Net MVC

This post in in continuation to my previous post where I create a progress dialog blocking the UI across asynchronous postbacks for WebForms. I will do the same thing here using Asp.Net MVC, except for the fact that there no such thing as postback in MVC, It’s all Get - Post -Put – Delete (a true web framework) . Much of the initial content will be common not identical.

The goal here is to not allow user to interact with the application, at the same time showing the user a dialog saying “Wait, let me first finish what you just asked me to do!”

The version of jQuery that I’m using is 1.4.1 (downloadable here) and the version of jQuery UI I’m using is 1.8.2(downloadable here). I’ll be using ASP.NET MVC 2.0 but this demo is valid for any web framework which allows making Ajax calls using jQuery.

The source code for this demo can be downloaded here.

Plugging in jQuery UI in to a new ASP.NET web application:

Well start with creating a new web application using Visual Studio 2010:

The application template by default contains the jQuery scripts in the /Scripts folder (I deleted the files non-relevant to this demo to minimize solution size).  jQueryUI scripts and CSS is required to be downloaded and include it in the solution via the following entries in the master page:

    <script src="../../Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>    
    <script src="../../Scripts/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script>
    <link href="../../Content/jQueryUI/redmond/jquery-ui-1.8.2.custom.css" rel="stylesheet" type="text/css" />

Creating a jQuery UI dialog with the content to show

We need to create two methods one to open the jQuery dialog and the other to close it. With the intention to keep all related javascript in one place and out of the .aspx pages, I created a new JScript file called jqueryProgressDialog.js, placed it in the Scripts folder and create two methods in it:

function showProgressDialog() {

    $("#progressDialog").dialog({
        autoOpen: false,
        modal: true,
        bgiframe: true
    });

    $('#progressDialog').dialog('open');

}

function hideProgressDialog() {

    if ($('#progressDialog').dialog('isOpen')) {

        $('#progressDialog').dialog('close');
    }
}

And include this script file in our master page -

    <script src="../../Scripts/jqueryProgressDialog.js" type="text/javascript"></script>

What will be shown in the dialog box will be defines using a DIV tag with id = “progressDialog”. We will put this in the Master Page so that it is available to the while application.

    <div id="progressDialog" title="Welcome to my demo!" style="display: none;">
        <img src="../../Images/AjaxProgress.gif" alt="Processing"/>
        <p>
            Please wait while your request is processed.
        </p>
    </div>

Obviously this solution will not work for the pages that do not  inherit from this master page.

 

Calling the progress dialog while asynchronous request

To consume this infrastructure, we need to add specify out show and hide dialog functions to the start and end of a request. You can either surpass the framework’s Ajax helpers and go the jquery way making Ajax calls -

The View -

    <p>
        <input type="button" value="Click here to for a 2 seconds long asynch call" onclick="makeAnAjaxCall();" />
    </p>

    <script type="text/javascript">

        function makeAnAjaxCall() {

            $.ajax({
                type: "GET",
                url: '<%= Url.Action("SleepFor2Seconds", "Home") %>',
                data: "{}",
                cache: false,
                beforeSend: showProgressDialog,
                complete: hideProgressDialog
            });
        }
    
    </script>

The Controller:

        public bool SleepFor2Seconds()
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
            return true;
        }

Or go with the framework infrastructure for secure posting your forms.

The View -

    <div>
        <% using (Ajax.BeginForm(new AjaxOptions()
                                 {
                                     HttpMethod = "post",
                                     OnBegin = "showProgressDialog",
                                     OnComplete = "hideProgressDialog"
                                 }
                     ))
           {%>
        <fieldset>
            <legend>Some form</legend>
            <p>
                FirstName:
                <%= Html.TextBox("FirstName", "FirstName")%>
            </p>
            <p>
                LastName:
                <%= Html.TextBox("LastName", "LasName")%>
            </p>
            <%= Html.AntiForgeryToken()%>
            <p>
                <input type="submit" value="Click here to Asynchronously post this form" />
            </p>
        </fieldset>
        <% } %>
    </div>

NOTE: For the Ajax.BeginForm to work the helper script files MicrosoftAjax.js and MicrosoftMvcAjax.js are required.

    <script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
    <script src="../../Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>

The Controller actions:

        [HttpGet]
        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to ASP.NET MVC!";

            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Index(FormCollection formcollection)
        {
            Thread.Sleep(TimeSpan.FromSeconds(1));
            return View();
        }

In either case, here’s the result:

jQueryProgressDialog_MVC

Friday, August 6, 2010

The jQuery formula - Blocking UI and showing progress dialog across asynchronous postbacks with ASP.NET Web Forms.

The goal here is to not allow user to interact with the application, at the same time showing the user a dialog saying “Wait, let me first finish what you just asked me to do!” The version of jQuery that I’m using is 1.4.1 (downloadable here) and the version of jQuery UI I’m using is 1.8.2(downloadable here). I’ll be using ASP.NET 4.0 Web forms but this demo is valid for pervious version with compatible ASP.NET AJAX (AKA Microsoft Ajax) version available.

The source code for this demo can be downloaded here.

Plugging in jQuery UI in to a new ASP.NET web application:

Well start with creating a new web application using Visual Studio 2010:

The application template by default contains the jQuery scripts in the /Scripts folder (I deleted the files non-relevant to this demo to minimize solution size).  jQueryUI scripts and CSS is required to be downloaded and include it in the solution via the following entries in the master page:

    <link href="Styles/jQueryUI/redmond/jquery-ui-1.8.2.custom.css" rel="stylesheet" type="text/css" />
    <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
    <script src="Scripts/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script>

Creating a jQuery UI dialog with the content to show

We need to create two methods one to open the jQuery dialog and the other to close it. With the intention to keep all related javascript in one place and out of the .aspx pages, I created a new JScript file called jqueryProgressDialog.js, placed it in the Scripts folder and create two methods in it:

function showProgressDialog() {

    $("#progressDialog").dialog({
        autoOpen: false,
        modal: true,
        bgiframe: true
    });

    $('#progressDialog').dialog('open');

}

function hideProgressDialog() {

    if ($('#progressDialog').dialog('isOpen')) {

        $('#progressDialog').dialog('close');
    }
}

And include this script file in our master page -

    <script src="Scripts/jqueryProgressDialog.js" type="text/javascript"></script>

What will be shown in the dialog box will be defines using a DIV tag with id = “progressDialog”. We will put this in the Master Page so that it is available to the while application.

    <div id="progressDialog" title="Welcome to my demo!" style="display: none;">
        <img src="Images/AjaxProgress.gif" alt="Processing"/>
        <p>
            Please wait while your request is processed.
        </p>
    </div>

Obviously this solution will not work for the pages that do not  inherit from this master page.

 

Calling the progress dialog while asynchronous request

To complete the infrastructure, we need to add an instance of  ScriptManager to the master page.

    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>

and use the methods exposed by PageRequestManager to specify the client side javascript methods that will be executed with the request start and end.

The PageRequestManager is a client side class that exposes events and functions to manipulate the asynchronous post back using the Script Manager. The intelessence support will be available if an instance of Scriptmanager or ScriptManagerProxy is available on the page. The methods exposed by the PageRequestManager are worth exploring if you are working extensively with Asp.Net Ajax.

PageRequestManager

To hook-up the progress dialog start stop function, we will add the following lines of script to our jqueryProgressDialog.js file (so that all the javascript code related to the dialog is at one place):

$(document).ready(function () {

    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(showProgressDialog);
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(hideProgressDialog);
});

With that the infrastructure is complete, now we need to see it work!

And to do that I will create an update panel on the home page and add a simple button in it to invoke a postback.

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" ChildrenAsTriggers="true" UpdateMode="Always">
        <ContentTemplate>
            <p>
                <asp:Button ID="Button1" runat="server" Text="Click here to for a 2 second asynch postback"
                    OnClick="Button1_Click" />
            </p>
        </ContentTemplate>
    </asp:UpdatePanel>

Code behind -

        protected void Button1_Click(object sender, EventArgs e)
        {
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }

And guess what showed up -

jQueryProgressDialog

 

After introduced to the ASP.NET MVC framework, it has been the framework of choice to me. So if you do not like server side ajax or (like me) prefer MVC over web forms –here’s the same trick with the MVC framework!