The ASP.NET AJAX UpdatePanel control provides us a quick and easy way to AJAX enable websites without changing our familiar design patterns. It’s certainly much better than using full postbacks in many situations.
However, it lacks usability. While the user waits on the async postback to occur, they are left without any of the usual indicators. We’ve spent decades training our users to wait when they see an hourglass icon. Why throw all that away for a spinning Web 2.0 progress indicator that means little to an average user?
Luckily, the ASP.NET AJAX framework provides us with tools to correct this shortcoming.
We’ll start with a run of the mill UpdatePanel setup:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"Inherits="_Default" %>
<html>
<body>
<div id="Container">
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="Label1" runat="server"
Text="Update Me" />
<br /><br />
<asp:Button ID="Button1" runat="server"
OnClick="Button1_Click" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</div>
</body>
</html>
public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
Thread.Sleep(3000);
Label1.Text = DateTime.Now.ToString();
}
}This is how it works with just an UpdatePanel:
First, we need to expand the Container div to fill the entire page using CSS:
html,body
{
height:99%
}
#Container
{
height:99%;
min-height:99%;
}
html>body #outer
{
height:auto
}Next, we need to hook and handle the initializeRequest and endRequest events exposed by the ASP.NET AJAX framework, using this JavaScript embedded in the page anywhere after the ScriptManager control:
To further enhance usability, we can disable the update button for the duration of the async postback:
<script language="javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
function InitializeRequest(sender, args)
{
$get('Container').style.cursor = 'wait';
}
function EndRequest(sender, args)
{
$get('Container').style.cursor = 'auto';
}
</script>
<script language="javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
function InitializeRequest(sender, args)
{
$get('Container').style.cursor = 'wait';
// Get a reference to the element that raised the postback,
// and disables it.
$get(args._postBackElement.id).disabled = true;
}
function EndRequest(sender, args)
{
$get('Container').style.cursor = 'auto';
// Get a reference to the element that raised the postback
// which is completing, and enable it.
$get(sender._postBackSettings.sourceElement.id).disabled = false;
}
</script>Now, we have a much better user experience:Of course, this is only the tip of the iceberg. The code could use some refinement, but it demonstrates the concept well.
ASP.NET AJAX Timer Trouble? Location is key.
If you’ve made much use of the ASP.NET AJAX Timer control, you may have noticed that it can behave somewhat unexpectedly. In this post, I’m going to take a closer look at how the Timer works and the most significant factor that influences it: Location.
Where the timer is placed on the page actually varies how it operates. As a Timer’s delay interval approaches the processing time of its resulting PostBack, the difference that the Timer’s location makes becomes very significant.
That said, I know that you’re probably still going to be using them even when you shouldn’t. So, let’s take a closer look at how the Timer actually works.
The Timer control’s underlying mechanism
It’s important to understand that the Timer control is simply an elaborate abstraction for combining JavaScript’s setTimeout and ASP.NET’s __doPostBack.
Assuming that UpdatePanel1’s OnLoad event was handled in the same way that the Timer1’s OnTick was handled, a Timer declared like this:
<asp:Timer runat="server" id="Timer1" Interval="5000" />
Could be very roughly approximated by JavaScript such as:
function pageLoad() {
window.setTimeout("__doPostBack('UpdatePanel1', '')", 5000);
}There’s nothing magic about the Timer control. It attempts to approximate the Timer control that we’re used to in WinForms development, but is still subject to the limitations of the stateless HTTP protocol.
Keeping this in mind, let’s look at two cases. In both, the Timer will have an Interval of five seconds and will trigger a partial postback taking four seconds to complete. However, due to Timer placement, the actual time between updates in these two cases will differ by around 80%.
Case 1: A Timer inside UpdatePanel content
protected void Timer1_Tick(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(4000);
Literal1.Text = DateTime.Now.ToLongTimeString();
}This is probably the easiest way of implementing a Timer. You can just drop it in the UpdatePanel, create an OnTick handler, and not worry about setting up triggers or anything else.
Because the Timer is inside the UpdatePanel’s ContentTemplate, it will be reinitialized every time the UpdatePanel refreshes. It actually comes within one second of triggering another OnTick event, but is reset by the partial postback’s return.However, even though the Timer interval is very clearly specified as five seconds, this UpdatePanel will actually take just over nine seconds for each Tick to fire. The reason for this large discrepancy is the location of the Timer. Take a look at the partial postback response, and it becomes clear why:
This may or may not be desirable in a given scenario, but can be fairly unexpected.
Case 2: A Timer outside UpdatePanel content
<asp:ScriptManager runat="server" ID="ScriptManager1" />
<asp:Timer runat="server" ID="Timer1"
Interval="5000" OnTick="Timer1_Tick" />
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
<ContentTemplate>
<asp:Literal runat="server" ID="Literal1" />
</ContentTemplate>
</asp:UpdatePanel>
protected void Timer1_Tick(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(4000);
Literal1.Text = DateTime.Now.ToLongTimeString();
}Implementing the Timer this way removes the reinitialization interference, but exposes another potential problem. Since the Timer ticks are now fixed at an absolute five second interval, only one second less than our partial postback requires to complete, the UpdatePanel spends nearly all of its time in async postback.
Depending on your application this may be exactly what you want, but it also might be very detrimental to the usability and performance of the application. For example, if you were to locate a one second Timer outside an UpdatePanel that took two seconds to refresh, it would never manage to complete a single update.
If you have better solution, just tell me
Create New ASP.NET 2.0 with ASP.NET AJAX 1.0 Projects
ASP.NET AJAX 1.0 Multi-Targeting Support
VS 2008 out of the box allows you to open and edit existing ASP.NET 2.0 applications built with the separate ASP.NET AJAX 1.0 download we shipped last year. The VS 2008 multi-targeting support works just fine with these projects, and you can use the improved JavaScript and web designer support with them - while still targeting .NET 2.0 and ASP.NET AJAX 1.0.
New ASP.NET AJAX 1.0 Project Templates for VS 2008
Out of the box VS 2008 doesn't include project templates for creating brand new ASP.NET 2.0 with ASP.NET AJAX 1.0 applications. Right before Christmas we shipped a web free web download for VS 2008 that enables these project templates options. You can download them here (note: you also need to make sure you have ASP.NET AJAX 1.0 installed on your machine in order to use them).
Once these additional project templates are installed, you can use File->New Project or File->New Web Site within VS 2008 to create ASP.NET AJAX 1.0 applications that run on ASP.NET 2.0:
New ASP.NET AJAX 1.0 Web Site:
![]()
New ASP.NET AJAX 1.0 Web Application:
![]()
Applications built using these project templates do not require .NET 3.5 to be installed on a server in order to work - you can copy them to any existing web server that has .NET 2.0 and ASP.NET AJAX 1.0 installed and they will work fine.
Source: ScottAJAX Control Toolkit Release Notes - May 2009 Release
New controls
This release includes three important new controls:Community effort
- HTMLEditor
The HTMLEditor control allows you to easily create and edit HTML content. You can edit in design mode, as a rich text editor, or in source view to edit the HTML markup directly.
Many thanks to by Obout http://www.obout.com/ for building this- ComboBox
The ComboBox control provides a DropDownList of items, combined with TextBox. Different modes determine the interplay between the text entry and the list of items.
Many thanks to Dan Ludwig for building this.- ColorPicker
The ColorPicker Control Extender can be attached to any ASP.NET TextBox control. It provides client-side color-picking functionality with UI in a popup control.
Many thanks to Alexander Turlov for building this.More than twenty important bug fixes have been made in this release, across many controls, corresponding to some of the most requested fixes.We would like to specially thank all the patch contributors from the Toolkit community whose fixes helped make this release possible. We recognize their names on the Toolkit Patch Hall of Fame.
New tutorials have been created, with improved integration in the ASP.NET AJAX Web site.
The TemplateVSI project has been removed. See the new tutorial: Creating a New Extender for information on how to create an Extender, without needing a Visual Studio Extender project template.
Source : AjaxControlToolkitASP.NET MVC Tip #5 - Submitting an AJAX Form with jQuery
This is one of the neatest, straightforward, and down right coolest way to submit a form with the ASP.NET MVC Framework. I've blogged in the past about jQuery and how useful it is. Combining MVC with jQuery can produce some really neat Web 2.0 style applications and today we'll take a look at some first steps. I'd like to get into some more advanced usage of jQuery. In particular, how it can integrate with ASP.NET MVC Framework.
Once you've downloaded the latest jQuery library, drop the script into your \Content folder in the MVC project. I usually create a sub folder in Content to organize my javascript files.
Anything you're going to do with jQuery requires this file. Depending on how often you use jQuery on your site, you might want to put the script on your MasterPage or if you only use it on a single page, you could drop it on that specific page.
We will now create a simple action to handle a basic contact form on our site. In this case I put the action in my Home controller. Also notice that by checking the HttpMethod I can handle both the GET and POST of the contact form with the same action. Note: The upcoming release of the MVC framework will not require the ControllerAction attribute on the action.
![]()
Looking at the view, we have a very simple contact form to capture the sender's email, the subject, and the body of the message. There's also a submit button to submit the form. We've also created the action using the Url helper.
Next, we are going to create a jQuery handler to wire up the form's submit event and run some jQuery scripts instead of a full server post.
![]()
First thing we do with jQuery is make sure the document is ready and all the DOM element have been loaded. Then we find our form element and wire up the "onsubmit" event so we can intercept it and do some jQuery magic. It's really easy to create an AJAX request using the $.post function; we just need some information about the form we're posting. I'm also showing off a couple of cool jQuery functions to do some neat UI updates. We'll fade out the contact form when the AJAX request starts, then fade it back in and show an alert. You can imagine how you could fit progress indicators in here as well.
That's it. When you hit the submit button, the javascript will take over the post and execute the action you specified.
Hope this helps!A JavaScript Stack Trace in ASP.NET AJAX
Something came up in that work recently that I’ve found to be quite useful in my day to day coding sessions and that’s how to create a stack trace in ASP.NET AJAX.
For starters, JavaScript doesn’t provide an easy way of pulling the stack trace of the call so we’re going to have to roll our own.I’ve seen a couple of different methods of creating the stack trace and the one I’m going to use comes from Helephant.com. I really like this implementation and I’m glad that I was able to poach somebody else’s code to create the stack trace (thx Helen!) rather than have to create mine from scratch.
From Helen’s post on Helephant.com we can see that there are three main functions to generate the stack trace: getFunctionName, getSignature, and stackTrace. Since we’re deep in the ASP.NET AJAX world I’ve updated the code to rely upon it and look more like code written for it. The code is below.
/// <reference name=”MicrosoftAjax.js />
/// Adopted from: http://www.helephant.com/Article.aspx?ID=675
_StackTrace = function() {
_StackTrace.initializeBase(this);
};
_StackTrace.prototype = {
_getFunctionName: function(theFunction) {
if(theFunction.name) {
return theFunction.name;
}
var definition = theFunction.toString();
var name = definition.substring(definition.indexOf(‘function’) + 8,definition.indexOf(‘(’));
if(name) {
return name;
}
return“anonymous”;
},
_getSignature: function(theFunction) {
var signature = newSys.StringBuilder(this._getFunctionName(theFunction));
signature.append(“(”);
for(var x=0; x < theFunction.arguments.length; x++) {
var nextArgument = theFunction.arguments[x];
if(nextArgument.length > 30) {
nextArgument = nextArgument.substring(0, 30) + “…”;
}
signature.append(String.format(“‘{0}’”, nextArgument));
// comma separator
if(x < theFunction.arguments.length – 1) {
signature.append(“, “);
}
}
signature.append(“)”);
return signature.toString();
},
createStackTrace: function(startingPoint) {
var stackTraceMessage = newSys.StringBuilder(“Stack trace: \n”);
var nextCaller = startingPoint;
while(nextCaller) {
stackTraceMessage.appendLine(this._getSignature(nextCaller));
nextCaller = nextCaller.caller;
}
stackTraceMessage.appendLine();
stackTraceMessage.appendLine();
return stackTraceMessage;
}
};
_StackTrace.registerClass(“_StackTrace”);
Sys.Application.add_init(
function() {
StackTrace = new_StackTrace();
}
);
Sys.Application.notifyScriptLoaded();Looking at the code, its basic job is to walk the caller pointer attached to the implicit arguments variable available in every function and derive a stack trace. Pretty straigh-forward.
So you might be thinking, if somebody else wrote the stack trace code, why is this guy writing a blog entry and not providing anything new except for a few minor tweaks to the stack trace code? Well, turns out that the stack trace is only 1/2 the battle. If you use this stack trace code or any other stack trace code that you might have written or come across, you’re going to run into a seriously annoying problem if your JavaScript uses the prototyping feature to construct objects. If you use the prototype feature to create your object and then attempt to pull the stack trace, all of your method names are going to be anonymous, which is really unhelpful. To illustrate this problem, we’ll use another object defined below and then execute the sayHello method from a test page.
/// <reference name=”MicrosoftAjax.js” />
Type.registerNamespace(“Animal”);Animal.Dog = function() {this._speech = “Arf!”;};
Animal.Dog.prototype = {
_speak: function() {
var trace = StackTrace.createStackTrace(arguments.callee);
alert (trace);
},
sayHello: function() {
this._speak();
}
};
Sys.Application.notifyScriptLoaded();In this object we expose a public method, sayHello off of our Animal.Dog object. Nothing important at here except that in our _speak method we make a call to our StackTrace class and execute the createStackTrace method.
Finally, we create a small test page that executes the sayHello method when it loads. The important section is listed below.
Executing the following code gives us the following output.<asp:ScriptManagerID=”SM1″runat=”server”>
<Scripts>
<asp:ScriptReferencePath=”~/StackTrace.js” />
<asp:ScriptReferencePath=”~/StackTraceTester.js” />
</Scripts>
</asp:ScriptManager>
<script type=”text/javascript”>
functiontester () {
var test = newAnimal.Dog();
test.sayHello();
}
Sys.Application.add_init(tester);
</script>
Reading the stack trace from top to bottom states that we executed an anonymous method, followed by another anonymous method, followed by our tester method, and so on. What’s striking about this stack trace is how useless it is! The anonymous method name does not help us at all for figuring out where our stack trace originated from. Can you imagine how much of a pain this would be if our stack was deeper and we had a large library of code?
Anyways, we can fix this problem, and it requires us using a technique seen in the MicrosoftAjax.debug.js file; the main ASP.NET AJAX file. In that file, Microsoft provides what can best be described as debug method names for its methods so that “anonymous” doesn’t appear in the call stack. For this example, we’ll update our Animal.Dog classes well as our StackTrace class using this method. Below is the code from the updated Animal.Dog class and the StackTrace class is updated similarly.
/// <reference name=”MicrosoftAjax.js />
Type.registerNamespace(“Animal”);
Animal.Dog = functionAnimal$Dog() {
this._speech = “Arf!”;
};
Animal.Dog.prototype = {
_speak: functionAnimal$Dog$_speak() {
var trace = StackTrace.createStackTrace(arguments.callee);
alert (trace);
},
sayHello: functionAnimal$Dog$sayHello() {
this._speak();
}
};
Sys.Application.notifyScriptLoaded();We’ve made changes to both the constructor and the methods. In the constructor we named our constructor function Animal$Dog. We named it using the dollar sign instead of the period (.) because in JavaScript a period is not valid in a function name. For the functions, we named them using the object type followed by the name of the function.
Now when we execute our test page we get the following output.
As you can see, our anonymous methods that were present in the first stack trace have turned into named methods. This is quite useful for tracing our execution. Not only does this provide us with a way to build a stack using our StackTrace object, but it gives us the method names in the Call Stack window in Visual Studio.
If you have better solution, just tell me
ASP.NET AJAX and SharePoint
One of the questions I was recently asked at a user group meeting in Europe was whether it was possible to use ASP.NET AJAX within SharePoint 2007 solutions. This was a common enough question that the SharePoint team recently blogged about their plans with ASP.NET AJAX to help answer it. You can read their post here.
At a highlevel, official support for ASP.NET AJAX within SharePoint will be coming with the first service pack of SharePoint 2007. This is because SharePoint 2007 shipped before ASP.NET AJAX 1.0 did, and so there is some work the SharePoint team needs to-do to make it integrate nicely.
In the meantime, though, you can read the SharePoint team's blog post here on how to install ASP.NET AJAX 1.0 on a SharePoint 2007 site and start using its functionality today. There are some caveats to using it until the first service pack ships - but the steps in their blog post will help you start using it immediately. Also make sure to check out Eric Schoonover's blog post on a custom AjaxBasePart web part that his team has created to help with using ASP.NET AJAX within custom web parts you build.
SharePoint and ASP.NET Developer Information
For more information on SharePoint and Web Parts, please check out these past posts of mine:
SharePoint 2007 -- Built on ASP.NET 2.0
Office 2007, VS 2005 Tools for Office, and VS 2005 Extensions for SharePoint
Writing Custom Web Parts for SharePoint 2007
Also check out the SmartPart control plug-in for SharePoint 2007 that allows you to deploy any ASP.NET 2.0 user control as a web part within SharePoint 2007.SharePoint and ASP.NET Web Part Development Books
While on the subject of SharePoint Developer and ASP.NET Web Parts, there are two great books on SharePoint development that I've been hearing very good things about lately. The first book is Todd Bleeker's "Developer's Guide to the Windows SharePoint Services v3 Platform" which has a 5 star rating (out of 5) on Amazon after 11 reviews, and which has been burning up the Amazon most popular lists the last few months:
The second book is Darren Neimke's "ASP.NET 2.0 Web Parts in Action: Building Dynamic Web Portals" which provides a great way to learn how to build sites that use ASP.NET 2.0 Web Parts, as well as how to build custom Web Parts of your own:
The beauty of web parts is that with ASP.NET 2.0 you can now build ones that can work and be customized by end-users within any ASP.NET web site/application (no SharePoint required), as well as have these same web parts work and run within SharePoint 2007 (both the free Windows SharePoint Services edition as well as the Microsoft Office SharePoint Server version). This provides a tremendous amount of developer power, and opens up a lot of options.
Free Application Templates for Windows SharePoint Services 3.0
One of the things the SharePoint team has been very focused on the last few months has been with putting together free application templates that you can download and use with Windows SharePoint Services 3.0 (which is the free version of SharePoint that you can download and install on any Windows Server box).
![]()
You can learn more about these application templates here. Below is a list of some of the templates with custom web parts provided for free download today:Board of Directors
Business Performance Reporting Case Management for Government Agencies Classroom Management Clinical Trial Initiation and Management Competitive Analysis Site Discussion Database Disputed Invoice Management Employee Activities Site Employee Self-Service Benefits Employee Training Scheduling and Materials Equity Research Integrated Marketing Campaign Tracking Manufacturing Process Management New Store Opening Product and Marketing Requirements Planning Request for Proposal Sports League Team Work Site Timecard ManagementWhat is great about these templates is that once you download and install them, you can optionally add custom ASP.NET web parts to it, and use standard ASP.NET 2.0 techniques to customize it further. This makes it dramatically easier to build and deploy common solution applications.

The beauty of web parts is that with ASP.NET 2.0 you can now build ones that can work and be customized by end-users within any ASP.NET web site/application (no SharePoint required), as well as have these same web parts work and run within SharePoint 2007 (both the free Windows SharePoint Services edition as well as the Microsoft Office SharePoint Server version). This provides a tremendous amount of developer power, and opens up a lot of options.