Published: 31 Mar 2008
By: Bertrand Le Roy
Download Sample Code

Bertrand Le Roy talks about achieving accessibility with the UpdatePanel control.


UpdatePanel is a great way to add Ajax features to an ASP.NET application at a minimal cost. Because it's based on regular postbacks, it also degrades gracefully when JavaScript is not present. But one thing it doesn't do well out of the box - and this is actually the case for any asynchronous update to the DOM - is informing screen readers that new content is present. This article and the accompanying code show how to work around that problem and give assistive technology users access to the benefits of Ajax.

The root of the problem

It seems quite puzzling that screen readers would continue to read the old contents of a page after an asynchronous update. All the more curious that synchronous interactions do trigger an update of their buffer. Why haven't assistive technology providers fixed this bug after the steady rise of Ajax technologies we've seen these last years?

The sad answer is that they couldn't fix it easily: before Internet Explorer 8, the browser wouldn't raise any event that screen readers could handle when the DOM is modified. This explains why synchronous updates that are triggered by user interaction such as a pressed button or a navigated link can and do cause an update of their buffer, because they are triggering events that screen readers can handle. But if the update to the DOM happens asynchronously, detached from the user interaction that caused it, no event is raised and the screen reader has no clue that something changed. The latest state of the page it knows about is the one at the moment of the interaction, not the one after the actual update was performed. This is true of XmlHttpRequest (or XHR) requests as well as of timed updates.

Note: The JAWS 9 screen reader does work around that problem by polling and monitoring changes on the DOM, but other popular screen readers such as Window Eyes don't.

A solution

A technique that was invented by George Young from Microsoft involves simulating browser navigation, which is another case where screen readers update their buffer. What we need to do is to trigger navigation from script without causing our page to actually navigate away, and also without creating an entry in browser history. The trick to achieve that is to navigate a hidden iframe using location.replace, which does exactly what we want, i.e. navigate without creating history points.


To encapsulate that solution, which would otherwise remain relatively complex to set-up, I've built a convenient control that handles it all automatically. Just drop it on your page and it will take care of rendering the iframe to the page and navigate it every time an asynchronous postback comes back from the server. Here's the markup that you need on the page:

And that's it.

Well, almost. One thing that I didn't mention yet about the iframe navigating trick is that every time the navigation happens, Internet Explorer emits a "click" sound. While it's hardly noticeable when it happens due to an explicit user action, it can become an issue when it happens long after the interaction or without a user interaction altogether (like can be the case if you're updating contents based on a timer). It becomes even worse if you're doing several partial updates in rapid succession. That's why most applications that use this trick make it opt-in. The way you would do that with this control would be by making it invisible initially (set Visible to false) and enable the user to turn it on by the click of a button. You can even do that in a partial update as this code demonstrates:

Listing 2: Putting the accessibility helper in an update panel

What about “pure Ajax”?

If you're not using UpdatePanel, or if you're using it in conjunction with "pure Ajax" asynchronous calls that do client-side DOM manipulations in response to a web service call, you still face the problem of updating the screen reader's buffer. To handle this scenario, the AccessibilityHelper control provides a client-side method that you can call every time you need to notify the screen reader of a change in the DOM:

Calling updateBuffer just navigates the hidden iframe, but this time you need to do it explicitly because the control can't guess when it makes sense like it could in the case of UpdatePanel.

A few more things to know about screen reader accessibility

There are still a few more things to know about screen reader accessibility even when using this control. The control takes care of telling the screen reader to refresh its buffer, but it doesn't do anything to give hints to the user about what exactly on the page was updated. Vision impaired users typically access the page as a linear entity whereas others view it more as a two-dimensional graphical entity. The first time the page is read to them, they will form a mental image of the structure of the page and of its different sections. That's why it's important to structure pages with easily identifiable sections (bonus points for providing anchors and links to skip the navigation sections). In particular, using H1 to H6 tags to identify section heads provides easier navigation as most screen readers provide shortcuts to quickly navigate the kind of table of contents this provides to the page. When an asynchronous update happened and the iframe has navigated, the user will need to know what part of the page they need to re-read. The best way of doing that is probably to make interactive UI elements such as buttons and links very explicit about what exactly they will cause to happen and what part of the page will be updated as a result of clicking them. Of course, making the text of the button or link very explicit may make the UI heavier and more verbose than you'd like, so I recommend putting that additional information in the ToolTip attribute if it's a server control, or in the title attribute if it's a client tag.

Finally, a note about focus. Screen reader users will expect the focus to remain stable after any interaction. You should refrain from setting focus to the part of the page that you just updated. As much as possible, focus should remain on the element that the user manipulated last. The user should be in control of moving the focus to the updated part of the page, which makes the previous recommendation about informing him about what exactly happened all the more important.

Wrapping it all together

Here's a simple page that applies all the recommendations in this article to some simple client-side and server-side Ajax updates:

Listing 4: Wrapping it all together: AccessibleUpdatePanel.aspx


In this article, we've learned about the reasons behind accessibility difficulties that Ajax creates. We've learned how to work around them using a simple server control as well as a few best practices to make a page as comfortable as possible for screen reader users while maintaining the Ajax functionality intact.

<<  Previous Article Continue reading and see our next or previous articles Next Article >>

About Bertrand Le Roy

Bertrand Le Roy is a program manager in the ASP.NET team.

This author has published 3 articles on DotNetSlackers. View other articles or the complete profile here.

Other articles in this category

Animating a Web Form using ASP.NET AJAX
In this article you will learn how to animate a webform using ajax.
Jquery Ajax
JQuery makes communicating with the server very, very easy. JQuery uses get(), getJSON(), and post(...
jQuery Deferred Objects Promise Callbacks
jQuery Deferred/Promise objects untangle spaghetti-like asynchronous code.
jQuery in Action 2nd edition: Queuing functions for execution
This article is taken from the book jQuery in Action, second edition. This segment shows how you can...
This is my custom article

You might also be interested in the following related blog posts

Building Interactive User Interfaces with Microsoft ASP.NET AJAX: Triggering Full Page Postbacks From An UpdatePanel read more
Mixing Silverlight and MS ASP.NET AJAX 3.5 in the same web application. read more
VSTS 2008, Web Tests and using Fiddler read more
Multiple UpdatePanels - Who caused the update ? read more
Impressive author lineup over at DotNetSlackers read more
AJAX UpdatePanel - "Statefull" Control Update Trigger read more
April 11th Links: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight read more
How to make UpdatePanel accessible read more
A New AJAX Approach - Client-side Controls Invoking Web Services read more
Results for Ajax usage among .NET developers read more

Please login to rate or to leave a comment.