Thursday, January 12, 2012

Using jQuery to enhance ASP.NET AJAX progress indication

In the spirit of Microsoft’s official embrace of jQuery last week, I’d like to show you an example of how easily you can add jQuery functionality to existing ASP.NET AJAX applications. jQuery allows you to achieve exceptional results with minimal difficulty, and integrating it with ASP.NET is not an exception.
My previous posts about jQuery have been somewhat lower level, incorporating JSONweb services, and the like. While these are important tools to have at your disposal, the realities of software development sometimes leave us scrambling for something quick and dirty.
In those situations, you may find yourself using the UpdatePanel.
To that end, I’m going to show you how easily you can use jQuery’s BlockUI pluginto display a modal progress indicator during an UpdatePanel’s partial postback.

Setting up a sample

new-customer-formTo avoid performance consequences associated with the UpdatePanel, judicious use is key. However, if you find that you need access to the values of several controls on the page, an UpdatePanel may practically be the best way to get the job done.
Take this new customer form (left) for example:
<div id="EntryForm">
  <label for="Name">Name:</label>
  <asp:TextBox runat="server" ID="Name" />
 
  <label for="Address">Address:</label>
  <asp:TextBox runat="server" ID="Address" />
 
  <label for="City">City:</label>
  <asp:TextBox runat="server" ID="City" />
 
  <label for="State">State:</label>
  <asp:TextBox runat="server" ID="State" />
 
  <label for="Zip">Zip:</label>
  <asp:TextBox runat="server" ID="Zip" />
 
  <asp:Button runat="server" ID="Save" OnClick="Save_Click" 
    Text="Add Customer" />
</div>
Assuming the form isn’t something expected to handle heavy usage, this is the type of thing that an UpdatePanel excels at. If the feature were to become popular and suffer from performance trouble, the UpdatePanel could always be refactored out in favor of a web service.

Styling the form

This CSS provides layout and basic styling:
#EntryForm {
  border: 1px solid #999;
  padding: 10px;
  width: 300px;
}
 
  #EntryForm label {
    clear: both;
    float: left;
    margin-bottom: 5px;
    padding-right: 10px;
    text-align: right;
    width: 75px;
  }
 
  #EntryForm input[type=text] {
    float: left;
    margin-bottom: 10px;
    width: 150px;
  }
 
  #EntryForm input[type=button] {
    clear: both;
    margin-left: 85px;
  }
If you prefer using tables to lay out forms, that’s okay too. The jQuery technique described below will work equally well with either layout method.

Using the UpdatePanel to add asynchronicity

To asynchronously handle the server-side click event of the save button, add an UpdatePanel which specifies the save Button as an AsyncPostBackTrigger:
<asp:UpdatePanel runat="server" ID="up1">
  <Triggers>
    <asp:AsyncPostBackTrigger ControlID="Save" />
  </Triggers>
  <ContentTemplate>
    <asp:Panel runat="server" ID="ConfirmSave" Visible="false">
      <h3><asp:Literal runat="server" ID="CustomerName" /> added</h3>
    </asp:Panel>
  </ContentTemplate>
</asp:UpdatePanel>
By positioning the UpdatePanel so that the partial postback is limited to refreshing only what is necessary, you can mitigate as much of its overhead as possible.
The Literal control allows us to provide contextual information to the user after the save completes. Implementing the server-side functionality for our fictitious form might look something like this:
protected void Save_Click(object sender, EventArgs e)
{
  // Save the customer to your data store here.
  System.Threading.Thread.Sleep(2000);
 
  // Display the confirmation.
  ConfirmSave.Visible = true;
 
  // Customize the confirmation.
  CustomerName.Text = Name.Text;
}
After the customer is saved, the confirmation message will be updated and the Panel control that contains it will be made visible.
You may be tempted to skip the Panel control and directly toggle the UpdatePanel’s visibility property instead. Unfortunately, that won’t work. An UpdatePanel is able to refresh its contents, but not itself.

Displaying the modal progress indicator with BlockUI

BlockUI’s functionality comes in two primary variations: blocking the entire page and blocking a particular element.
In this example, we’ll block the entry form’s container div, rather than the entire page. To invoke BlockUI on element(s), create a jQuery selector for the element(s) that you want to block and then call the .block() method on the resulting jQuery object.
To put this into action on our customer entry form, we need to add a client-side onclick handler to the save Button. To illustrate how effortlessly jQuery and ASP.NET AJAX integrate with each other, we can wire this event handler up in the Application.Init event:
Sys.Application.add_init(function() {
  // Allows the div.blockMsg style in CSS to
  //  override BlockUI's defaults.
  $.blockUI.defaults.css = {};
 
  // Add the BlockUI call as an onclick handler
  //  of the Save button.
  $addHandler($get('Save'), 'click', function() {
    $('#EntryForm').block({ message: null });
  });
});
If the jQuery-esque inline callback functions bother you, don’t worry. This style is interchangeable with what you’re used to seeing in most ASP.NET AJAX examples.

Using CSS to style the progress indicator

Screenshot of the styled BlockUI element, with progress indicatorNext, let’s add a bit of custom styling to the BlockUI modal element. BlockUI’s defaults look pretty good, but we’ll need to change things around in order to get the progress indicator background image to display properly.
div.blockMsg {
  background-color: #fff;
  background-image: url(images/progress-indicator.gif);
  background-position: center center;
  background-repeat: no-repeat;
  border: 1px solid #ddd;
  height: 50px;
  width: 270px;
}

Gotcha: the event stops here

Because BlockUI attempts to suppress form submissions as part of its blocking functionality, the save Button’s partial postback will also be blocked. To remedy this, we must set the Button’s UseSubmitBehavior property to false:
<asp:Button runat="server" ID="Save" OnClick="Save_Click" 
  Text="Add Customer" UseSubmitBehavior="false" />
This will cause ASP.NET to render the Button with an onclick handler that executes __doPostBack instead of relying on HTML’s underlying form submission event.

Hiding the progress indicator afterward

BlockUI won’t automatically unblock our form after the partial postback completes. So, we’ll need some code to do that at the end of the UpdatePanel’s refresh.
There are several ways to accomplish this. In this limited example, adding the following code to our existing Application.Init handler is the simplest way:
// Get a reference to the PageRequestManager.
var prm = Sys.WebForms.PageRequestManager.getInstance();
 
// Unblock the form when a partial postback ends.
prm.add_endRequest(function() {
  $('#EntryForm').unblock();
});
We could use ScriptManager.RegisterStartupScript to emit the same unblock code from Save_OnClick, but I’d caution against doing that.
Needlessly mixing client and server side code entangles your presentation and logic together, leaving you with maintenance headaches. If you can avoid doing that, you’ll appreciate it later on.

Alternate event handler coding styles

I’ve been using anonymous functions to declare event handler callbacks inline, instead of the traditional route of using standalone functions. This is a choice of coding style, and is not functionally significant.
For example, this is equivalent to the previous click handler code:
Sys.Application.add_init(AppInit);
 
function AppInit() {
  $.blockUI.defaults.css = {};
 
  $addHandler($get('Save'), 'click', Save_Click);
}
 
function Save_Click() {
  $('#EntryForm').block({ message: null });
}
You could also use jQuery’s events instead of ASP.NET AJAX’s:
$(document).ready(function() {
  $.blockUI.defaults.css = {};
 
  $('#Save').click(function() {
    $('#EntryForm').block({ message: null });
  });
});
Many jQuery examples will use the latter method, so it’s important to understand that they are all roughly interchangeable.
Ultimately, the choice is completely up to you. What’s your preference?

Conclusion

I hope that this example has served to show just how easily jQuery allows you to add slick presentational effects to your ASP.NET AJAX applications.
Considering the amount of overlap between them, both frameworks do a great job of peacefully coexisting with each other. There’s no need to worry about combining the two right away, and then gradually beginning to enhance your existing ASP.NET AJAX functionality with jQuery.
If you enjoyed this example be sure to check out the followup post, Using jQuery to display a modal UpdatePanel confirmation, in which I describe how to implement a similar modal effect for the contextual confirmation Panel.

Try it for yourself

Download Source: jQuery-modal.zip

ref : http://encosia.com/using-jquery-to-enhance-aspnet-ajax-progress-indication/

No comments:

Post a Comment