March 2009

Volume 24 Number 03

Internet Explorer 8 - New Features To Slice, Store, And Accelerate Your Web Applications

By Daron Yöndem | March 2009

Code download available

This article discusses:

  • Web Slices
  • Accelerators
  • DOM Storage
  • AJAX Navigation
This article uses the following technologies:
AJAX, JavaScript

This article is based on a prerelease version of Internet Explorer 8. All information is subject to change.

Contents

Defining Page Regions with Web Slices
Expiration and Update Frequency
Accelerators
Search Suggestions
AJAX Navigation
DOM Storage
Offline and Online Working Modes
XMLHttpRequest Time Outs
Wrap-Up

Internet Explorer 8 represents a major step in the evolution of the product. It provides new end user features like Web Slices, Accelerators, and search suggestions—and also brings with it more advanced developer features such as AJAX navigation and DOM storage.

In this article, I will look into the details of these features to see how Internet Explorer 8 can make life easier for both developers and users alike. You'll see how these new features allow you to define portions of a page and control its update frequency and expiration, improve the user's search and navigation experience, and lots more.

Defining Page Regions with Web Slices

Web Slices allow you to cut a Web page into pieces so that you can display and update only the parts you are interested in. Web Slices can be a handy solution for a user who wants to follow the updates from your Web site but doesn't want to use an RSS reader. RSS readers can be a little complicated for some end users and are not always appropriate.

Web Slices are programmatically defined parts of a Web page that users discover by moving their mouse over the slice or clicking the "Subscribe to a Web Slice" button on the toolbar. Figure 1shows this in action.

Figure 1 Discovering a Web Slice by Hovering

After subscribing to a Web Slice, the user will be able to see the slice title on the Internet Explorer 8 Favorites bar. Internet Explorer will keep contacting the online source and alert the user about updates by making the slice title text bold. When you click on the title, the content of the slice will be shown in a popup window as shown in Figure 2.

fig02.gif

Figure 2 Finding the Latest Bid on an Auction in a Web Slice

One major benefit of Web Slices is that users don't need to keep refreshing a Web page in order to track changes on the site. Furthermore, depending on how you structure the data sources for your Web Slices, they can help to conserve resources on the Web server since updates will be for only relevant data, not the whole page. Additionally, by using Web Slices, your system can provide deeper statistics about how users access different parts of a Web page, which can impact further design decisions.

As I mentioned earlier, Web Slices are predefined by the developer. So how do you define those parts? First of all, you need to mark an HTML div element as a Web Slice container using the hslice class name. The hslice element will contain all the rest of the definitions you need for your Web Slice. Here's an empty Web Slice definition:

<div class="hslice" id="ProductID1"> </div>

Each Web Slice must have a unique ID, as this is how Internet Explorer distinguishes one from the other on a page. If the ID of a Web Slice changes after users subscribe to it, Internet Explorer will not be able to find it anymore and will not be able update the content on the favorites bar.

Each Web Slice should contain an element to identify the title of the slice; the title is identified by the CSS class entry-title. This content will be shown on the favorites bar and the feed discovery command bar menu. The entry-title text can be changed if you like when the Web Slice updates itself.

To finish creating my first Web Slice I have to add just one more element: the entry-content. I have the Web Slice and the title defined but I don't have any content to show to the user. So let's define the Web Slice content by applying the CSS class entry-content on the content that should be displayed to the user:

<div class="hslice" id="ProductID1"> <h1 class="entry-title"> Brand New Product!</h1> <div class="entry-content"> <p> This is the product definition.</p> </div> </div>

Figure 3 shows my Web Slice definition. My Web Slice, called ProductID1, has a title and content.

fig03.gif

Figure 3 A Simple Web Slice

You can add further richness to the Web Slice user experience with visual elements and inline (or global) CSS styles. The only limitation is that no scripting or ActiveX controls (including Silverlight) are allowed. If you need ActiveX ,you will need to use an alternative display source. An alternative display source can be defined on the entry-content container element of the Web Slice.

As shown here, you don't need to put the content inside the entry-content element. You are simply redirecting the Web Slice and telling the browser that the content will come from another URL:

<div class="hslice" id="ProductID2"> <h1 class="entry-title"> Brand New Product</h1> <div class="entry-content" href="https://www.contoso.com/web_slice/ alternative_display.aspx?ID=2"> </div> </div>

This way you will be able to track how many times each Web Slice is updated and how many users are following which slices by simply tracking the display source pages. In addition, in the target alternative_display.aspx page you are allowed to use ActiveX controls.

Expiration and Update Frequency

Sometimes you will need Web Slices to expire in a timely manner even if the user is offline and the Web Slice can't get updated. This is especially true for sites such as online auctions or online sales campaigns. You can set the end time of a Web Slice by adding the endtime class name and the appropriate date time value inside an HTML abbreviation element, like so:

<div class="hslice" id="ProductID1"> <h1 class="entry-title"> Brand New Product!</h1> <div class="entry-content"> <p> This is the product definition.</p> <p> This is the end time: <abbr class="endtime" title="2008-10-12T11:00:00-12:00:00"> 12:00</abbr></p> </div> </div>

Users are able to set the update frequency by right-clicking the Web Slice title on the favorites bar and clicking the Properties command. As shown in Figure 4, custom schedules are allowed.

fig04.gif

Figure 4 Users Can Set the Update Frequency of a Web Slice

In addition to the user-defined settings, you can programmatically specify frequencies by providing time to live (ttl) values:

<div class="hslice" id="ProductID6"> <h1 class="entry-title"> Brand New Product!!!!</h1> <div class="entry-content"> <p> This is the product definition.</p> <div class="ttl" style="display: none;"> 15</div> </div> </div>

To specify a frequency, I have created a DIV element with the CSS class ttl and the content 15. This tells the browser to check the content of this Web Slice every 15 minutes for possible updates. Notice that as a design choice I set the visibility of the DIV element to invisible by setting the display CSS value to none.

As I mentioned, you can use alternative display sources, but sometimes it can be useful to simply have a Web Slice fetch its data from an external data source. You have two choices when using external data sources. One option is to use an external Web Slice on another page, as you'll see in the next code snippet.

<div class="hslice" id="ProductID10"> <div class="entry-title"> Product Name </div> <a rel="feedurl" href="https://www.contoso.com/ external.aspx#ProductID1"></a> </div>

This Web Slice definition is pulling another Web Slice from external.aspx. The target Web Slice is found by its ID which is ProductID1 and attached as an anchor to the URL. The presence of the rel attribute on the anchor tag instructs Internet Explorer to use the anchor tag's URL as the Web Slice data source rather than displaying the contents in the div tag.

The second option is to use an external RSS feed. Internet Explorer will always use the first item inside the RSS feed and show the entry content from the incoming RSS XML:

<div class="hslice" id="ProductID10"> <div class="entry-title"> Product Name </div> <a rel="feedurl" href="/slicefeed.xml"></a> </div>

Here the Web Slice has a feedurl anchor targeting an XML source, which could be easily replaced by a generic handler that outputs XML on the fly depending on some parameter. The XML source in our example is shown here:

<?xml version="1.0" encoding="utf-8" ?> <rss version="2.0"> <channel> <title>WebSlice RSS</title> <ttl>120</ttl> <item> <title>Product Name Here</title> <description>HTML &lt;b&gt;codes&lt;/b&gt; can be used</description> </item> </channel> </rss>

Instead of defining the settings of our Web Slice in the entry-content HTML code, you can define them in your XML data source. In the previous code, the XML source provides values for ttl and title properties of a Web Slice. The description tag can contain rich HTML without causing any problems.

Accelerators

Accelerators exist to make common tasks faster and more automated while browsing the Web. For example, think about how often you copy and paste content from one Web site to another. Let's say you just found the address you were looking for on a corporate Web site and now you need driving directions. You copy the address, launch the Live Maps Web site and paste in the address. You can automate this process using an accelerator.

Figure 5shows an Accelerator that finds a location on the map when the user clicks on the address. Writing your own accelerator is simple. As a developer, you just need to define what your accelerator will do using an XML OpenService Description file. Let's dig into the details of the OpenService Description format. The following shows a basic OpenService Description file:

<?xml version="1.0" encoding="utf-8" ?> <openServiceDescription xmlns="https://www.microsoft.com/schemas/ openservicedescription/1.0"> <homepageUrl>https://www.contoso.com/</homepageUrl> <display> <name>Translate it with Contoso</name> <icon>https://www.contoso.com/favicon.ico</icon> </display> <activity category="translate"> ... </activity> </openServiceDescription>

Figure 5 Live Maps Accelerator Provides Instant Location Search

The main properties of an Accelerator are the homepageUrl, display, and activity tags. The homepageUrl is the URL of the service you are providing. All the URLs used in other tags and settings should use the same domain as the homepageUrl. The display tag sets the visual aspects of an accelerator's command button on the Internet Explorer right-click menu. When the user right-clicks on the page, the accelerator will be revealed by its name and icon.

The activity element defines the service that the accelerator provides. In this example, the accelerator will provide a translation activity. You can control how Internet Explorer groups your accelerator on the context menu by using different categories like Add (to add a link), Blog (to blog on a remote service), Define (to look for definition), Map (to look for map) and Translate (to translate the selected text). You can also define your own categories. The suggested rules for category definitions are that they should be a verb and generic enough to let other accelerator developers use the same category.

Now is the time to define our activitiyActions inside our activity tags. Here you can see one activityAction with a context value of selection:

<activityAction context="selection" > <preview action="https://www.contoso.com/translateacc.aspx" method=" get" > <parameter name="word" value="{selection}" /> </preview> <execute action=" https://www.contoso.com/translate.aspx " method=" post" > <parameter name="word" value="{selection}" /> </execute> </activityAction>

The context attribute is the key component of an activityAction. The context defines when this action will be available. If the accelerator doesn't provide an action suitable for the current context, it will not be visible on the accelerator's menu in Internet Explorer. The current context choices are selection and link. If the context is selection, the user needs to select text and go to the accelerators menu in order to use your accelerator. If the context is link, the user should right-click on a hyperlink to start the action.

In each activityAction you can have an execute and a preview definition. Execute is launched when the user clicks the accelerator command from the accelerators menu. Preview action is launched when the user hovers the mouse over the accelerator command on the menu. Both the Preview and Execute tags can have an action URL and a method. You can use GET or POST as methods of data transfer.

Parameters are defined for each action as name/value pairs. The values come automatically from keywords in brackets. For instance, {selection} means that the text selected by the user will be the value of the associated parameter. A list of possible value keywords is shown in Figure 6.

Figure 6 Keyword Options
Name Description
documentDomain The domain address of the current page.
documentTitle The title of the current page.
documentUrl The full URL of the current page.
link If the user clicked a link, this provides the full address of the link.
linkDomain If the user clicked a link, this provides the domain address of the link.
linkRel If the user clicked a link, this provides the rel property of the link.
linkText If the user clicked a link, this provides the text of the link.
selection The selected text on the current page.

The preview window works like an IFrame, which means that you can use any kind of interaction inside the preview window. It is more appropriate to design a specific interface and distinguish the preview and execute action URLs.

The final OpenService Description file for the example is shown in Figure 7. Now it's time to let the visitor of our Web site install this accelerator to her PCs. Here is the script needed to install the accelerator:

<div> <input id="Button1" type="button" value="Click to Install" onclick="window.external.AddService('myaccelerat.xml');" /> </div>

Figure 7 The Final OpenService Description File

<?xml version="1.0" encoding="utf-8" ?> <openServiceDescription xmlns="https://www.microsoft.com/schemas/ openservicedescription/1.0"> <homepageUrl>https://www.contoso.com/</homepageUrl> <display> <name>Translate with Contoso</name> <icon>https://www.contoso.com/favicon.ico</icon> </display> <activity category="translate"> <activityAction context="selection" > <preview action="https://www.contoso.com/translate.asp"> <parameter name="Word" value="{selection}" /> </preview> <execute action="https://www.contoso.com/translate.asp"> <parameter name="Word" value="{selection}" /> </execute> </activityAction> </activity> </openServiceDescription>

The AddService method gets the URL of our OpenService Description XML file and starts the installation. In order to find out if an accelerator is already installed you can call the isServiceInstalled method.

Search Suggestions

Internet Explorer 7.0 introduced a new feature called Search Providers. Users were able to integrate different search providers into their browser and use the search bar to easily navigate to their favorite search engine. This is possible because of the XML-based OpenSearch specification files. Internet Explorer 8 further improves search with a feature called search suggestions. As the name implies, the browser makes suggestions while you type your search keyword.

As the user types, the browser goes to the selected search suggestions provider and requests suggestions related to the search keywords. The resulting data is instantly shown to the user to create a better search experience (see Figure 8).

Figure 8 Easily Access Suggestions for Search Keywords without Navigating Away from Current Page

Before getting into the details of how Search suggestions work, you will need a search provider. A search provider consists of three main elements: a name, a search URL, and an icon. Those are all well defined in the OpenSearch specification XML. The following is a full-featured search provider written for Internet Explorer 7.0 without search suggestions:

<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="https://a9.com/-/spec/opensearch/1.1/"> <ShortName>Contoso Search</ShortName> <Url type="text/html" template="https://www.contoso.com/?key2search= {searchTerms}"/> <Image height="16" width="16" type="image/icon"> https://www.contoso.com/favicon.ico</Image> </OpenSearchDescription>

The ShortName tag includes the search provider name and the URL tag defines the search path of the search engine. The searchTerms keyword in the URL pattern will be replaced by the search keywords written by the user. Finally, the Image tag points to an icon file for the search provider.

In order to install a search provider, users will need to click an HTML element on your page or discover the search provider through the search box of Internet Explorer 8. And in a similar manner as accelerators, search providers can be installed using the window.external.AddSearchProvider JavaScript function:

<a href="#" onclick="window.external.AddSearchProvider('https:// www.contoso.com/provider.xml')"> Add Search Provider </a>

Note that the AddSearchProvider JavaScript function requires the OpenSearch XML file URL as a parameter in order to initialize the install process.

As an alternative to the explicit reference to your OpenSearch XML file, you can let the browser explore your Web page and discover your search provider. To make your search provider discoverable, you will need to put a hidden link to your OpenSearch XML file in your HTML pages header. The following is a hidden link to a search provider:

<link title="Contoso Search" rel="search" type="application/ opensearchdescription+xml" href="https://www.contoso.com/provider.xml" />

The title of the link is the name of the search engine shown in the browser. The rel and type properties of the hidden link should be exactly the same as I've used here. This is how the browser knows that it is a link to a search provider. Finally, the href attribute contains a URL to the OpenSearch description XML file.

Now that you have your Search Provider ready, you can go on and add search suggestions to it. First, you will need to modify the OpenSearch description XML file and specify your search suggestion data source:

<?xml version="1.0" encoding="UTF-8"?> <OpenSearchDescription xmlns="https://a9.com/-/spec/opensearch/1.1/"> <ShortName>Contoso Search</ShortName> <Url type="text/html" template="https://www.contoso.com/?key2search= {searchTerms}"/> <Url type="application/x-suggestions+json" template="https:// www.contoso.com/json.ashx? key2search ={searchTerms}"/> <Image height="16" width="16" type="image/icon">https:// www.contoso.com/favicon.ico</Image> </OpenSearchDescription>

Here you will see that I've added one additional line of XML to the previous search provider description file—a new URL tag with a different type value. In order to use the search suggestions feature, you will need a service that can evaluate the search keywords being provided by the user and is able to supply the appropriate suggestion list.

The list can be provided in XML or JSON format. In the example, I have added pointers to the suggestion service using JSON. However, I could have easily consumed an XML-based service with the following XML:

<Url type="application/x-suggestions+xml" template="https:// www.contoso.com/xml.ashx? key2search ={searchTerms}"/>

There are important differences between XML and JSON data sources. A JSON data source can provide a list of suggestions including the suggested results, one description for each result and a URL if needed. Here's an example:

["con", ["contoso soft", "contoso books", "contoso rent"], ["software company", "book store", "rent a car"], ["https://www.contoso.com/soft", "https://www.contoso.com/books", "https://www.contoso.com/rent"]]

fig10.gif

Figure 10 A Sample Search Suggestion List

Internet Explorer 8 will pull the JSON data on the fly and show the autocomplete list instantly. Be aware that the search keyword should be included in the data returned from the provider. The first element in our JSON example contains our search keyword "con."

If you choose to use the XML format to provide search suggestion lists for Internet Explorer, you will be able to choose a title for your result list, to split the results with separators, and to provide visual suggestions as well.

At first I will provide a Search suggestion list with only two results and one separator. The XML response in Figure 9contains the submitted keyword in the Query tags and provides two Items in a Section tag. The section tag has a title and each item has a Text, Description and a Url to navigate.

Figure 9 XML for Search Suggestions

<SearchSuggestion> <Query>con</Query> <Section title="First Section"> <Item> <Text>Result 1</Text> <Description>Description 1</Description> <Url>https://www.contoso.com?id=1</Url> </Item> <Separator title="Others"/> <Item> <Text>Result 2</Text> <Description>Description 2</Description> <Url>https://www.contoso.com?id=2</Url> </Item> </Section> </SearchSuggestion>

You can use separator tags with titles to provide different lists of results in the search suggestion box. The URLs will be used when the user clicks a suggested item in the list. In Figure 10, you can see how the XML data will be shown in Internet Explorer 8.

In addition to the classical view of a search suggestion list, you can use images to enhance the user experience and provide an image with each suggestion. All you need to do is and add an Image tag to the appropriate Item tags, like so:

<Item> <Text>Result 1</Text> <Description>Description 1</Description> <Url>https://www.contoso.com?id=1</Url> <Image Source=https://www.contoso.com/image.jpg alt="A picture is worth thousand words" width="70"></Image> </Item>

AJAX Navigation

AJAX is one of the major components of rich Internet applications (RIA) and will remain so as long as HTML is in use. You can use AJAX to update pieces of the UI without requiring entire page refreshes and server-client cycles for each user action. But AJAX has its drawbacks.

When you use AJAX to modify your Web page content you will notice that the address bar doesn't change. This makes sense. But what if the user wants to have a consistent URL of the current page's state, say for adding to favorites and so forth? What if the user clicks the back button in her browser? She will be sent to the Web site she visited previously.

Somehow you have to reflect the URL change without refreshing the Web site. Enter the fragment identifier. The fragment identifier does exactly what it sounds like it does—identifies the state of part of the page.

Each URL can have a fragment identifier; you just need to append a pound sign "#" to the end of the URL (for example, www.contoso.com/default.aspx\#5). If you change the content after the # sign, the Web page will not refresh but the history log of the browser will record the change and provide back and forth navigation.

In Internet Explorer 8, this feature is provided with the window.location.hash property and the new hashChanged event. Whenever you change the window.location.hash property, the address bar will get an update and the content of the hash property will be placed after the # sign. When the user tries to navigate to another Web page through the browsers buttons, the hashChanged event will fire and provide the target hash value which is the value after the target pages # sign.

Let's create a simple Web site with a WebMethod in order to service AJAX calls. This sample Web site will contain an HTML button and a DIV element. Each time someone clicks the HTML button, the numeric content of the DIV element will be sent to the WebMethod:

<form id="form1" runat="server"> <asp:ScriptManager EnablePageMethods="true" ID="ScriptManager1" runat="server"> </asp:ScriptManager> <div> <input id="Button1" onclick="GetNext();" type="button" value="button" /> <div id="content">0</div> </div> </form>

In order to call the service, add the following JavaScript:

function GetNext() { PageMethods.GetNext($get("content").innerHTML, Done); } function Done(sender) { $get("content").innerHTML = sender; window.location.hash = sender; }

Finally, create the WebMethod in the page's codebehind file in order to increment the integer parameter and return it to the AJAX caller:

<System.Web.Services.WebMethod()> _ Public Shared Function GetNext(ByVal x As Integer) As Integer Return x + 1 End Function

The JavaScript method named GetNext makes an XMLHttpRequest to the server. The parameters for the GetNext method are simply the content of the DIV element and a callback method. When the callback method, Done, is called as a result of the service response, the new value is simply put back into the DIV element.

Here comes the interesting point. After modifying the Web page with the new content, I assign a unique identifier to the window.location.hash property in order to identify the current state of my Web page. For this simple example, that value is the same number displayed in my DIV element. After changing the hash property, if you take a look in the browser history you will notice the new entries that are now listed there.

Whenever the user navigates back or forward in the browser history, the hash property will be handed back to a JavaScript function that handles the onhashchange event. This is accomplished using the following line of code:

<body onhashchange="HashChanged();">

This function will be called whenever the user navigates backward or forward, and Internet Explorer 8 will update the window.location.hash property according to the values in the browser history. This enables me to easily get the hash value and update my page, whether that action is as simple as updating the page with the hash data itself, as shown below or whether it involves requesting data from the server based on a unique identifier stored in the hash:

function HashChanged() { $get("content").innerHTML = window.location.hash; }

DOM Storage

Currently, if you need to store data on the client, the only standardized way, and the old standby, is to use document.cookie. Unfortunately, this method is simply not flexible or powerful enough for today's online applications. One of the most significant shortcomings of cookies is the 4KB limit. Internet Explorer 8 has an answer—DOM storage.

DOM storage is part of the HTML 5 Working Draft and provides a huge data store (about 10MB) on the client side. This storage can be so much larger in part because the data is not sent with each request to the server as it is with cookies. Plus, the localStorage never expires.

In order to store and retrieve data from DOM storage, all you need is a key/value pair. The localStorage JavaScript class provides the methods setItem, getItem and removeItem to access all the features of DOM Storage:

function Save() { localStorage.setItem("MyItem", $get("Text1").value); } function Load() { $get("Text1").value = localStorage.getItem("MyItem"); }

This code performs the equivalent of a property get and set operation in C# or Visual Basic using DOM Storage as the backing store. First of all, the Save function stores the value of a TextBox to DOM Storage with a key name of MyItem. Then the Load function retrieves the data from DOM Storage by providing the same key name.

Offline and Online Working Modes

Like many Web developers, I've long been dreaming of the day when I could detect if the current user has a healthy connection to the Internet and provide an appropriate level of functionality. Now, Internet Explorer 8 provides the status of the host PCs Internet connection with onLine property of window.navigator. While in the past, this property represented whether the user had chosen to work offline, it now indicates whether the current user has an established connection to the network.

In addition to the onLine property, Internet Explorer 8 has now two new callback handlers ononline and onoffline (see " ononline Event" and " onoffline Event"). The onoffline handler is raised when the system loses the network connection and the ononline handler is raised when the connection is restored. You can attach event listeners and be warned instantly about the state of the connection so that you can provide you users a blended experience during both online and offline functionality.

Figure 11 shows a simple usage of ononline and onoffline events defined in the body of a Web page. Each time the user gets connected to the network, the Online JavaScript method will launch. Likewise, each time the users disconnects, the network the Offline method will fire.

Figure 11 Using Ononline and Onoffline Events

<html > <head runat="server"> <title></title> <script type="text/javascript" language="javascript"> function Online() { alert("I'm online"); } function Offline() { alert("I'm offline"); } </script> </head> <body ononline="Online();" onoffline="Offline();"> <form id="form1" runat="server"> </form> </body> </html>

XMLHttpRequest Time Outs

The new XMLHttpRequest in Internet Explorer 8 has a TimeOut property and an ontimeout event. This enables you to define XMLHttpRequests which will timeout and allow other requests to move ahead in the request queue.In the following code, I create a new XmlHttpRequest and set the timeout property and ontimeout event listener:

function GetAReqeust() { var MyRequest = XMLHttpRequest(); MyRequest.ontmeout = TimeOutHere; MyRequest.open("GET","https://www.contoso.com/data.xml"); MyRequest.timeout = 2000; MyRequest.send(null); } function TimeOutHere() { alert("Request to Contoso timed out!"); }

There are two rules you really should follow when defining timeout settings: the timeout event listener should be bound before opening the request and the timeout property should be set after opening the request.

One of the major problems you will encounter when designing your AJAX applications involves communicating with services in various remote domains thanks to the same-origin-policy.

There are some workarounds you could perform, but none of them provide what you need: both a straightforward and a secure method of communication. Internet Explorer 8 provides a new client-side object called XDomainRequest, which allows developers to access remote domains without requiring implementation of a a server-side proxy.

If the remote server provides an Http Header called Access-Control-Allow-Origin:* all other remote sites will be able to request data from the current Web page. The client-side use of XDomainRequest object is the same as the ordinary XmlHttpRequest.

As you can see, Internet Explorer 8 offers a number of features that solve many problems Web developers have been hoping to solve for a long time. Whether it's in more deeply integrating your content and services into the browser or leveraging new browser platform services to provide for a more seamless user experience, Internet Explorer 8 gives you the tools to build richer, more seamless experiences for your users.

Daron Yöndem is the founder of Deveload Software based in Turkey. He is a Microsoft Regional Director and MVP in ASP.NET. Daron is an international speaker leading the INETA MEA Speaker Bureau and author of two ASP.NET AJAX books.