<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Happy Coding</title><subtitle type="html">Jeffrey Zhao, Microsoft MVP from China, enjoys programming in Microsoft platform every day.</subtitle><id>http://weblogs.asp.net/jeffreyzhao/atom.aspx</id><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/default.aspx" /><link rel="self" type="application/atom+xml" href="http://weblogs.asp.net/jeffreyzhao/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20510.895">Community Server</generator><updated>2008-02-21T23:37:00Z</updated><entry><title>Extend ASP.NET MVC for Asynchronous Action</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2009/01/30/extend-asp-net-mvc-for-asynchronous-action.aspx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2009/01/30/extend-asp-net-mvc-for-asynchronous-action.aspx</id><published>2009-01-30T05:14:00Z</published><updated>2009-01-30T05:14:00Z</updated><content type="html">&lt;P&gt;Numerous new features come into people’s eyes since ASP.NET 2.0 and asynchronous request handling is one of the most important parts. It reduces the working thread number by the async mechanism based on IO completion port when processing IO bound request and improves throughput of web sites significantly (please refer to the &lt;A href="http://www.cnblogs.com/JeffreyZhao/archive/2008/02/24/use-async-operation-properly.html" mce_href="http://www.cnblogs.com/JeffreyZhao/archive/2008/02/24/use-async-operation-properly.html"&gt;theory analyzing&lt;/A&gt; and &lt;A href="http://www.cnblogs.com/JeffreyZhao/archive/2009/01/19/lab-async-request.html" mce_href="http://www.cnblogs.com/JeffreyZhao/archive/2009/01/19/lab-async-request.html"&gt;benchmarks&lt;/A&gt; if you can read Chinese :P). But the current version of ASP.NET MVC doesn’t support async actions and that’s just ‘the missing key feature’ I mentioned before. I gave a so-called solution that introduced the async action to ASP.NET MVC in my session of TechED 2008 China but it’s full of limitations and inappropriate for production use.&lt;/P&gt;
&lt;P&gt;These days I’m preparing for the session in the coming .NET conference in Shanghai (that &lt;A href="http://www.wintellect.com/CS/blogs/jeffreyr/archive/2009/01/16/china-s-very-first-net-conference-in-shanghai.aspx" mce_href="http://www.wintellect.com/CS/blogs/jeffreyr/archive/2009/01/16/china-s-very-first-net-conference-in-shanghai.aspx"&gt;Jeffrey Richter would also attend&lt;/A&gt;) and I think it’s better to release a better solution at that time: straightforward, rather full-featured and light-weighted – the core funtion contains only about 200 lines of codes, which means it maximize the usage of existing framework functions to make the solution more stable, efficient and backward-compatible.&lt;/P&gt;
&lt;P&gt;I built the the new solution based on ASP.NET MVC Beta at first but RC released when I was writing the post. When I was trying to change the implementation for RC I found the improvements in design that impressed me a lot. These improvements change my strategy of building the solution but seems it’s a little easier when building extensions for RC. The ASP.NET MVC team did a good job.&lt;/P&gt;
&lt;P&gt;Now let’s get started.&lt;/P&gt;
&lt;H1&gt;Change the way of request handling&lt;/H1&gt;
&lt;P&gt;It should be clear how ASP.NET MVC handles a request before we make decisions:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;When the application starts (without any incoming requests), route strategies would be registered in ASP.NET Routing module. At that time each strategy object (Route instance) contains a route handler – which is an intance of MvcRouteHandler type in ASP.NET MVC framework. &lt;/LI&gt;
&lt;LI&gt;When the Routing module meets a request that fit one of the strategies, the route handler belongs to the corresponding Route object would be used (by calling GetHttpHandler method) to get an http handler that can process the request. The MvcRouteHandler always returns an MvcHandler object. &lt;/LI&gt;
&lt;LI&gt;When MvcHandler object is processing the request, the ‘controller’ value in RouteData would be retrieved to build a controller object (which implements IController) by a controller factory (which implements IControllerFactory). After that, the controller would be executed (by calling Execute method on it). &lt;/LI&gt;
&lt;LI&gt;Generally, in an ASP.NET MVC application a controller type inherits from the System.Web.Mvc.Controller class. When executing these kind of controllers, the ‘action’ value in RouteData would be retrieved and passed to the action invoker (which is an IActionInvoker object get by the ActionInvoker property) to execute the action. &lt;/LI&gt;
&lt;LI&gt;… &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;If the way of processing requet needs to be async, we have to let it meet the architecture of ASP.NET. There’re several method to enabled the async mechanism such as async page and async http module, but the best one to use in our scenario is using async http handler. To implement an async http handler, we must make the handler type to implement IHttpAsyncHandler instead ot IHttpHandler. The BeginProcessRequest and EndProcessRequest methods compose the ‘two-phase’ processing style which meets the standard APM (Aynchronous Programming Model) pattern in .NET.&lt;/P&gt;
&lt;P&gt;Now you may realized that an IHttpAsyncHandler should be used if we want to execute an action asynchronously, but the default choice of ASP.NET MVC framework is MvcHandler, which is always sync. It’s too late for us to decide whether the executing action is async or not in the handler. We have to move it to Routing. Fortunately, the route handler in ASP.NET Routing is just like IHttpHandlerFactory in ASP.NET architecture, which can be used to create an http handler object dynamiclly by context. So the first step we shoud do is to build a new route handler to replace the default MvcRouteHandler. Here comes the AsyncMvcRouteHandler – you can imagine that part of it is the same as MvcHandler since what we need to do is just to move some code to the earlier stage:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncMvcRouteHandler &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IRouteHandler
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IHttpHandler &lt;/SPAN&gt;GetHttpHandler(&lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;requestContext)
    {
        &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;controllerName = requestContext.RouteData.GetRequiredString(&lt;SPAN style="COLOR: #a31515"&gt;"controller"&lt;/SPAN&gt;);

        &lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt; &lt;/SPAN&gt;factory = &lt;SPAN style="COLOR: #2b91af"&gt;ControllerBuilder&lt;/SPAN&gt;.Current.GetControllerFactory();
        &lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt; &lt;/SPAN&gt;controller = factory.CreateController(requestContext, controllerName);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(controller == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            &lt;SPAN style="COLOR: blue"&gt;throw new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;InvalidOperationException&lt;/SPAN&gt;(...);
        }

        &lt;SPAN style="COLOR: blue"&gt;var&lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt; &lt;/SPAN&gt;coreController = controller &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Controller&lt;/SPAN&gt;;
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(coreController == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
        {
            &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SyncMvcHandler&lt;/SPAN&gt;(controller, factory, requestContext);
        }
        &lt;SPAN style="COLOR: blue"&gt;else
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;actionName = requestContext.RouteData.GetRequiredString(&lt;SPAN style="COLOR: #a31515"&gt;"action"&lt;/SPAN&gt;);
            &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; IsAsyncAction(coreController, actionName, requestContext) ?
                (&lt;SPAN style="COLOR: #2b91af"&gt;IHttpHandler&lt;/SPAN&gt;)&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncMvcHandler&lt;/SPAN&gt;(coreController, factory, requestContext) :
                (&lt;SPAN style="COLOR: #2b91af"&gt;IHttpHandler&lt;/SPAN&gt;)&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SyncMvcHandler&lt;/SPAN&gt;(controller, factory, requestContext);
        }
    }

    &lt;SPAN style="COLOR: blue"&gt;internal static bool &lt;/SPAN&gt;IsAsyncAction(
        &lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;/SPAN&gt;controller, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;actionName, &lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;requestContext)
    {
        ...
    }
}&lt;/PRE&gt;
&lt;P&gt;In GetHttpHandler method, we get the controller name from RouteData and create a controller object by the factory registered in ControllerBuilder. We try to cast the controller object as Controller type since we’ll use the action invoker in it to decide whether the action is async or not. If the controller object is in type Controller, we’ll get the action name from RouteData and try to return an AsyncMvcHandler (which implements IHttpAsyncHandler) or SyncMvcHandler (which implements IHttpHandler) object by the result of IsAsyncAction method.&lt;/P&gt;
&lt;P&gt;To enable the AyncMvcRouteHandler, we should use it to replace the default one while mapping route strategies when application starts.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public static void &lt;/SPAN&gt;RegisterRoutes(&lt;SPAN style="COLOR: #2b91af"&gt;RouteCollection &lt;/SPAN&gt;routes)
{
    routes.IgnoreRoute(&lt;SPAN style="COLOR: #a31515"&gt;"{resource}.axd/{*pathInfo}"&lt;/SPAN&gt;);

    routes.MapRoute(
        &lt;SPAN style="COLOR: #a31515"&gt;"Default"&lt;/SPAN&gt;,                                              &lt;SPAN style="COLOR: green"&gt;// Route name
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #a31515"&gt;"{controller}/{action}/{id}"&lt;/SPAN&gt;,                           &lt;SPAN style="COLOR: green"&gt;// URL with parameters
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;{ controller = &lt;SPAN style="COLOR: #a31515"&gt;"Home"&lt;/SPAN&gt;, action = &lt;SPAN style="COLOR: #a31515"&gt;"Index"&lt;/SPAN&gt;, id = &lt;SPAN style="COLOR: #a31515"&gt;"" &lt;/SPAN&gt;}  &lt;SPAN style="COLOR: green"&gt;// Parameter defaults
    &lt;/SPAN&gt;).RouteHandler = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncMvcRouteHandler&lt;/SPAN&gt;();
}&lt;/PRE&gt;
&lt;H1&gt;Decide whether the action is async or not&lt;/H1&gt;
&lt;P&gt;We made a convention in code above: an async action could only be defined in an controller type which inherits from Controller. Here’s another one: the action invoker in the controller must be an object of ControllerActionInvoker or its child type.&lt;/P&gt;
&lt;P&gt;There’re several ‘helper’ methods in ControllerActionInvoker which can be used to get the descriptors for controller and actions. We can get the action’s information from its descriptor object, such as whether it has been marked with AsyncActionAttribute – that’s the sign of an async action:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;private static object &lt;/SPAN&gt;s_methodInvokerMutex = &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;();
&lt;SPAN style="COLOR: blue"&gt;private static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInvoker &lt;/SPAN&gt;s_controllerDescriptorGetter;

&lt;SPAN style="COLOR: blue"&gt;internal static bool &lt;/SPAN&gt;IsAsyncAction(
    &lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;/SPAN&gt;controller, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;actionName, &lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;requestContext)
{
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;actionInvoker = controller.ActionInvoker &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ControllerActionInvoker&lt;/SPAN&gt;;
    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(actionInvoker == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;) &lt;SPAN style="COLOR: blue"&gt;return false&lt;/SPAN&gt;;

    &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(s_controllerDescriptorGetter == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
    {
        &lt;SPAN style="COLOR: blue"&gt;lock &lt;/SPAN&gt;(s_methodInvokerMutex)
        {
            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(s_controllerDescriptorGetter == &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
            {
                &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags &lt;/SPAN&gt;bindingFlags = &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.Instance | &lt;SPAN style="COLOR: #2b91af"&gt;BindingFlags&lt;/SPAN&gt;.NonPublic;
                &lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;method = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;ControllerActionInvoker&lt;/SPAN&gt;).GetMethod(
                    &lt;SPAN style="COLOR: #a31515"&gt;"GetControllerDescriptor"&lt;/SPAN&gt;, bindingFlags);
                s_controllerDescriptorGetter = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInvoker&lt;/SPAN&gt;(method);
            }
        }
    }

    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;controllerContext = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ControllerContext&lt;/SPAN&gt;(requestContext, controller);
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;controllerDescriptor = (&lt;SPAN style="COLOR: #2b91af"&gt;ControllerDescriptor&lt;/SPAN&gt;)s_controllerDescriptorGetter.Invoke(
        actionInvoker, controllerContext);
    &lt;SPAN style="COLOR: blue"&gt;var &lt;/SPAN&gt;actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
    &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;actionDescriptor == &lt;SPAN style="COLOR: blue"&gt;null &lt;/SPAN&gt;? &lt;SPAN style="COLOR: blue"&gt;false &lt;/SPAN&gt;:
        actionDescriptor.GetCustomAttributes(&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;AsyncActionAttribute&lt;/SPAN&gt;), &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;).Any();
}&lt;/PRE&gt;
&lt;P&gt;There’s a protected method named ‘GetControllerDescriptor’. It accepts a ControllerContext object as parameter and returns a ControllerDescriptor object to describe the controller. From the descriptor of controller we can get the ActionDescriptor object as the descriptor of the executing action by calling FindAction method with the action name as one of the parameters. IsAsyncAction returns false for a non existing action so that SyncMvcHandler would be used to process the request with the default behavior. If and only if the action is marked with AsyncActionAttribute it would be identified as an async one. BTW, a special class ‘MethodInvoker’ is used above. It is a replacement for the function of MethodInfo.Invoke method and provide huge performance improvement. That’s a helper class from &lt;A href="http://www.codeplex.com/FastReflectionLib" mce_href="http://www.codeplex.com/FastReflectionLib"&gt;Fast Reflection Library&lt;/A&gt; project (I also wrote a &lt;A href="http://weblogs.asp.net/jeffreyzhao/archive/2009/01/27/fast-reflection-library.aspx" mce_href="http://weblogs.asp.net/jeffreyzhao/archive/2009/01/27/fast-reflection-library.aspx"&gt;post about it&lt;/A&gt;) that you can use for your own need.&lt;/P&gt;
&lt;P&gt;Let’s talk about the change of design in ASP.NET MVC RC. There’s nothing like the descriptors but a method to get the MethodInfo of the action in previous ControllerActionInvoker. The current design uses the implementations based on reflection for the abstraction of descriptors by default. e.g., the descriptor of an action we used is an object of RelfectedActionDescriptor class, which implements the abstract class ActionDescriptor. That’s a great improvement. Since we’re using descriptors for elements (controller/action/parameter, etc.),&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;we could use different concrete implementations to describe elements. e.g., we can build descriptors based on configurations rather than the default behavior – reflection – which is more like ‘convention’. &lt;/LI&gt;
&lt;LI&gt;there’s no limitations for the underly form of action. e.g., an async action could be composed by two methods. &lt;/LI&gt;
&lt;LI&gt;it’s easy to add more information on descriptor types. e.g., in the future we could know whether the action disabled session state from an action descriptor. &lt;/LI&gt;
&lt;LI&gt;… &lt;/LI&gt;&lt;/UL&gt;
&lt;H1&gt;Execute an action&lt;/H1&gt;
&lt;P&gt;The SyncMvcHandler type which used to execute a normal action is quite an easy one:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SyncMvcHandler &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IHttpHandler&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IRequiresSessionState
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;SyncMvcHandler(
        &lt;SPAN style="COLOR: #2b91af"&gt;IController &lt;/SPAN&gt;controller,
        &lt;SPAN style="COLOR: #2b91af"&gt;IControllerFactory &lt;/SPAN&gt;controllerFactory,
        &lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;requestContext)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller = controller;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ControllerFactory = controllerFactory;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.RequestContext = requestContext;
    }

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IController &lt;/SPAN&gt;Controller { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;RequestContext { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IControllerFactory &lt;/SPAN&gt;ControllerFactory { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }

    &lt;SPAN style="COLOR: blue"&gt;public virtual bool &lt;/SPAN&gt;IsReusable { &lt;SPAN style="COLOR: blue"&gt;get &lt;/SPAN&gt;{ &lt;SPAN style="COLOR: blue"&gt;return false&lt;/SPAN&gt;; } }

    &lt;SPAN style="COLOR: blue"&gt;public virtual void &lt;/SPAN&gt;ProcessRequest(&lt;SPAN style="COLOR: #2b91af"&gt;HttpContext &lt;/SPAN&gt;context)
    {
        &lt;SPAN style="COLOR: blue"&gt;try
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller.Execute(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.RequestContext);
        }
        &lt;SPAN style="COLOR: blue"&gt;finally
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ControllerFactory.ReleaseController(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller);
        }
    }
}&lt;/PRE&gt;
&lt;P&gt;But I thought a lot for dealing with an async action, or how I can change the default execution style into ‘two-phase’ (BeginXxx/EndXxx). I tried to implement a new action invoker before but found it would take a lot of work. If I want to keep all the current features (action filter, action selector, etc.), it seems the best way is to build a child class of ControllerActionInvoker and use te exsiting functions as much as possible. But I think it’s nealy impossible after reading the code. For example, one of the characters of an action method is that it returns ActionResult (or its child), but the BeginXxx method for an async action returns IAsyncResult so we cannot use the FindAction method in ControllerActionInvoker directly; and, if we want to use FindAction to get the ‘EndAbc’ method by passing the action name ‘Abc’ with ‘End’ before it, what would happen if there’s a request to execute a sync action ‘EndAbc’?&lt;/P&gt;
&lt;P&gt;Since the problems described above, I almost rewrite the whole invoker last year and it brings a lot of complexities and limitations. Developers have to compromise in some aspect when using it. When I introduced the solution in my session of TechED 2008 China I said it should not be used in production environment.&lt;/P&gt;
&lt;P&gt;The current solution is much better. It uses an interesting work around to solve the problems. It’s not perfect but usable. The reason we meet such difficulties is that we break the design of framework, from single action method to a ‘APM-style’ execution. Wait a minute, have you idetified the source of the problems? That’s right, it’s the ‘APM-style’.&lt;/P&gt;
&lt;P&gt;‘APM-style’ separates a single method into a pair of BeginXxx/EndXxx method, but we can just implement an async execute with an ‘two-phase’ style. Since the framework force an action to return an ActionResult, why can’t we keep the reference(s) of method(s) in the object? It’s not ‘APM-style’ but it’s really ‘async-style’, isn’t it?&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncActionResult &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;ActionResult
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;AsyncActionResult(
        &lt;SPAN style="COLOR: #2b91af"&gt;IAsyncResult &lt;/SPAN&gt;asyncResult,
        &lt;SPAN style="COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IAsyncResult&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;ActionResult&lt;/SPAN&gt;&amp;gt; endDelegate)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.AsyncResult = asyncResult;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.EndDelegate = endDelegate;
    }

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IAsyncResult &lt;/SPAN&gt;AsyncResult { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Func&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IAsyncResult&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;ActionResult&lt;/SPAN&gt;&amp;gt; EndDelegate { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }

    &lt;SPAN style="COLOR: blue"&gt;public override void &lt;/SPAN&gt;ExecuteResult(&lt;SPAN style="COLOR: #2b91af"&gt;ControllerContext &lt;/SPAN&gt;context)
    {
        context.Controller
            .SetAsyncResult(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.AsyncResult)
            .SetAsyncEndDelegate(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.EndDelegate);
    }
}&lt;/PRE&gt;
&lt;P&gt;We execute the BeginXxx method in the action method and return an AsyncActionResult instance contains the IAsyncResut object and the reference to the EndXxx method. These two objects will be saved when the result executes and we can get them back in AsyncMvcHandler.EndProcessRequest method. Generally we should build an extension method to help the developers to return an AsyncActionResult object from an action method. Now we get the style of an async action:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;AsyncAction&lt;/SPAN&gt;]
&lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;AsyncAction(&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCallback &lt;/SPAN&gt;asyncCallback, &lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;asyncState)
{
    &lt;SPAN style="COLOR: #2b91af"&gt;SqlConnection &lt;/SPAN&gt;conn = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlConnection&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"...;Asynchronous Processing=true"&lt;/SPAN&gt;);
    &lt;SPAN style="COLOR: #2b91af"&gt;SqlCommand &lt;/SPAN&gt;cmd = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;SqlCommand&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #a31515"&gt;"WAITFOR DELAY '00:00:03';"&lt;/SPAN&gt;, conn);
    conn.Open();

    &lt;SPAN style="COLOR: blue"&gt;return this&lt;/SPAN&gt;.Async(
        cmd.BeginExecuteNonQuery(asyncCallback, asyncState),
        (ar) =&amp;gt;
        {
            &lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;value = cmd.EndExecuteNonQuery(ar);
            conn.Close();
            &lt;SPAN style="COLOR: blue"&gt;return this&lt;/SPAN&gt;.View();
        });
}&lt;/PRE&gt;
&lt;P&gt;No secret for AsyncMvcHandler now:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncMvcHandler &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IHttpAsyncHandler&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IRequiresSessionState
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;AsyncMvcHandler(
        &lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;/SPAN&gt;controller,
        &lt;SPAN style="COLOR: #2b91af"&gt;IControllerFactory &lt;/SPAN&gt;controllerFactory,
        &lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;requestContext)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller = controller;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ControllerFactory = controllerFactory;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.RequestContext = requestContext;
    }

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Controller &lt;/SPAN&gt;Controller { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;RequestContext &lt;/SPAN&gt;RequestContext { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IControllerFactory &lt;/SPAN&gt;ControllerFactory { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;HttpContext &lt;/SPAN&gt;Context { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IAsyncResult &lt;/SPAN&gt;BeginProcessRequest(
        &lt;SPAN style="COLOR: #2b91af"&gt;HttpContext &lt;/SPAN&gt;context,
        &lt;SPAN style="COLOR: #2b91af"&gt;AsyncCallback &lt;/SPAN&gt;cb,
        &lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;extraData)
    {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Context = context;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller.SetAsyncCallback(cb).SetAsyncState(extraData);

        &lt;SPAN style="COLOR: blue"&gt;try
        &lt;/SPAN&gt;{
            (&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller &lt;SPAN style="COLOR: blue"&gt;as &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IController&lt;/SPAN&gt;).Execute(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.RequestContext);
            &lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller.GetAsyncResult();
        }
        &lt;SPAN style="COLOR: blue"&gt;catch
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ControllerFactory.ReleaseController(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller);
            &lt;SPAN style="COLOR: blue"&gt;throw&lt;/SPAN&gt;;
        }
    }

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;EndProcessRequest(&lt;SPAN style="COLOR: #2b91af"&gt;IAsyncResult &lt;/SPAN&gt;result)
    {
        &lt;SPAN style="COLOR: blue"&gt;try
        &lt;/SPAN&gt;{
            &lt;SPAN style="COLOR: #2b91af"&gt;HttpContext&lt;/SPAN&gt;.Current = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Context;
            &lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;actionResult = &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller.GetAsyncEndDelegate()(result);
            &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(actionResult != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
            {
                actionResult.ExecuteResult(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller.ControllerContext);
            }
        }
        &lt;SPAN style="COLOR: blue"&gt;finally&lt;/SPAN&gt;
        {
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.ControllerFactory.ReleaseController(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.Controller);
        }
    }&lt;SPAN style="COLOR: blue"&gt;
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;We save the current HttpContext object in BeginProcessRequest – that’s important since HttpContext.Current is based on the call context and it would be thrown after an async callback, which means we shoud set it back in EndProcessRequest for the rest functions. After saving the HttpContext object, we should also save the async callback and async state parameters, and next, execute the controller. The whole progress is finished after Execute method’s return, which means the IAsyncResult object and the reference to the EndXxx method haved been saved. We get the IAsyncResult object back and return from BeginProcessRequest. In EndProcessRequest method, we retrive the saved reference to the EndXxx method and get another ActionResult by calling it. Finally we execute the new result and complete the whole async processing.&lt;/P&gt;
&lt;P&gt;The code above only considers the logic of normal state. You can get more (e.g. logic to deal with the exceptional state) in the source code of the solution. Both the BeignProcessRequest and EndProcessRequest methods take care of error handling to make the controller released at a property time.&lt;/P&gt;
&lt;H1&gt;ModelBinder support&lt;/H1&gt;
&lt;P&gt;Actually you cannot use async action so far, since the default model binder don’t know how to bind an AsyncCallback object and the AsyncCallback parameter in the action method is always null. That’s easy. We could build a AsyncCallbackModelBinder whose only purpose is to return the AsyncCallback object saved in controller:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public sealed class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCallbackModelBinder &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IModelBinder
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public object &lt;/SPAN&gt;BindModel(
        &lt;SPAN style="COLOR: #2b91af"&gt;ControllerContext &lt;/SPAN&gt;controllerContext,
        &lt;SPAN style="COLOR: #2b91af"&gt;ModelBindingContext &lt;/SPAN&gt;bindingContext)
    {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;controllerContext.Controller.GetAsyncCallback();
    }
}&lt;/PRE&gt;
&lt;P&gt;We should register the model binder for AsyncCallback type when application starts.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;protected void &lt;/SPAN&gt;Application_Start()
{
    RegisterRoutes(&lt;SPAN style="COLOR: #2b91af"&gt;RouteTable&lt;/SPAN&gt;.Routes);
    &lt;SPAN style="COLOR: #2b91af"&gt;ModelBinders&lt;/SPAN&gt;.Binders[&lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCallback&lt;/SPAN&gt;)] = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCallbackModelBinder&lt;/SPAN&gt;();&lt;SPAN style="COLOR: green"&gt;
&lt;/SPAN&gt;}&lt;/PRE&gt;
&lt;P&gt;It’s inappropriate to do so for async state parameter in an action method since object is the base class of all the types and it’s not specific to the async state. I suggest that you mark an attribute for the async state parameter in each action method. Here’s the AsyncStateAttribute, which has been built into the solution with AsyncStateModelBinder:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;AttributeUsage&lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;AttributeTargets&lt;/SPAN&gt;.Parameter, AllowMultiple = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;, Inherited = &lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;)]
&lt;SPAN style="COLOR: blue"&gt;public sealed class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncStateAttribute &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;CustomModelBinderAttribute
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;private static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncStateModelBinder &lt;/SPAN&gt;s_modelBinder = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;AsyncStateModelBinder&lt;/SPAN&gt;();

    &lt;SPAN style="COLOR: blue"&gt;public override &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IModelBinder &lt;/SPAN&gt;GetBinder()
    {
        &lt;SPAN style="COLOR: blue"&gt;return &lt;/SPAN&gt;s_modelBinder;
    }
}&lt;/PRE&gt;
&lt;P&gt;Here’s the way to use it:&lt;/P&gt;&lt;PRE class=code&gt;[&lt;SPAN style="COLOR: #2b91af"&gt;AsyncAction&lt;/SPAN&gt;]
&lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ActionResult &lt;/SPAN&gt;AsyncAction(&lt;SPAN style="COLOR: #2b91af"&gt;AsyncCallback &lt;/SPAN&gt;cb, [&lt;SPAN style="COLOR: #2b91af"&gt;AsyncState&lt;/SPAN&gt;]&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;state) { ... }&lt;/PRE&gt;
&lt;P&gt;Actually it won’t be a big deal even if you ignore the async state parameter since it’s always useless when processing a request aynchronously. And, you can also get the async callback and async state object by the extensions methods (GetAsyncCallback and GetAsyncState) defined for Controller type, but it reduces the testability.&lt;/P&gt;
&lt;H1&gt;Limitations and drawbacks&lt;/H1&gt;
&lt;P&gt;The solution definitely has limitations and drawbacks:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;It doesn’t follow the standard APM pattern.&lt;/LI&gt;
&lt;LI&gt;Since the solution is based on the existing functions in framework, all the filters would be executed when BeginXxx method finished.&lt;/LI&gt;
&lt;LI&gt;Some features are missed since the filters cannot be applied to EndXxx method and the final action result.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;ASP.NET MVC will introduce the ‘async controller’ in the future according to the official roadmap. Actually the MvcFuture project in the source of ASP.NET MVC RC has already contains the code about async features. You can found serveral new types such as IAsyncController, AsyncController, IAsyncActionInvoker, AsyncControllerActionInvoker, etc.. All types are inherited from exsiting type but as I predicted before, the AsyncControllerActionInvoker class rewrites almost all the code. I cannot tell the quality of design before reading it – hope it is as good as the current one.&lt;/P&gt;
&lt;P&gt;I’m going do more for the drawbacks listed above. I hope it would become a solution good enough for production. &lt;A href="http://code.msdn.microsoft.com/AsyncMvc" mce_href="http://code.msdn.microsoft.com/AsyncMvc"&gt;The whole solution&lt;/A&gt;, &lt;A href="http://code.msdn.microsoft.com/AsyncMvc/Release/ProjectReleases.aspx?ReleaseId=2197" mce_href="http://code.msdn.microsoft.com/AsyncMvc/Release/ProjectReleases.aspx?ReleaseId=2197"&gt;source code&lt;/A&gt; and &lt;A href="http://code.msdn.microsoft.com/AsyncMvc/Wiki/View.aspx?title=Benchmark&amp;amp;referringTitle=Home" mce_href="http://code.msdn.microsoft.com/AsyncMvc/Wiki/View.aspx?title=Benchmark&amp;amp;referringTitle=Home"&gt;benchmark&lt;/A&gt; have been published in &lt;A href="http://code.msdn.microsoft.com/" mce_href="http://code.msdn.microsoft.com"&gt;MSDN Code Gallery&lt;/A&gt;. Please feel free to &lt;A href="mailto:jeffz@live.com" mce_href="mailto:jeffz@live.com"&gt;contact me&lt;/A&gt; for any comments and suggestions.&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6868972" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="C#" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/.NET/default.aspx" /><category term="ASP.NET MVC" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/ASP.NET+MVC/default.aspx" /><category term="MVC" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/MVC/default.aspx" /><category term="ASP.NET" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/ASP.NET/default.aspx" /></entry><entry><title>Fast Reflection Library</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2009/01/27/fast-reflection-library.aspx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2009/01/27/fast-reflection-library.aspx</id><published>2009-01-26T18:01:00Z</published><updated>2009-01-26T18:01:00Z</updated><content type="html">&lt;P&gt;This is a project I've created in &lt;A href="http://www.codeplex.com/" mce_href="http://www.codeplex.com/"&gt;CodePlex&lt;/A&gt; under &lt;A href="http://www.opensource.org/licenses/ms-pl.html" mce_href="http://www.opensource.org/licenses/ms-pl.html"&gt;Microsoft Public License (Ms-PL)&lt;/A&gt;. You can find it &lt;A href="http://www.codeplex.com/FastReflectionLib" mce_href="http://www.codeplex.com/FastReflectionLib"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;H1&gt;Simple Usage&lt;/H1&gt;
&lt;P&gt;Reflection is one of the most important features of .NET platform. The way of accessing/assigning a property or invoking a method dynamically is widely used by numerous projects. As we all know, invoke-by-reflection is much less efficient than direct access. FastReflectionLib provide the same as part of the refection features like executing method dynamically but give simple and faster implementations. It can be use as the foundation of reflection-based scenarios such as ORM framework.&lt;/P&gt;
&lt;P&gt;Please look at the code snippets below:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;System;
&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;System.Reflection;
&lt;SPAN style="COLOR: blue"&gt;using &lt;/SPAN&gt;FastReflectionLib;

&lt;SPAN style="COLOR: blue"&gt;namespace &lt;/SPAN&gt;SimpleConsole
{
    &lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Program
    &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;static void &lt;/SPAN&gt;Main(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] args)
        {
            &lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;propertyInfo = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;).GetProperty(&lt;SPAN style="COLOR: #a31515"&gt;"Length"&lt;/SPAN&gt;);
            &lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;methodInfo = &lt;SPAN style="COLOR: blue"&gt;typeof&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;).GetMethod(&lt;SPAN style="COLOR: #a31515"&gt;"Contains"&lt;/SPAN&gt;);

            &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;s = &lt;SPAN style="COLOR: #a31515"&gt;"Hello World!"&lt;/SPAN&gt;;

            &lt;SPAN style="COLOR: green"&gt;// get value by normal reflection
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;length1 = (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)propertyInfo.GetValue(s, &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;);
            &lt;SPAN style="COLOR: green"&gt;// get value by the extension method from FastReflectionLib,
            // which is much faster
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;length2 = (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)propertyInfo.FastGetValue(s);

            &lt;SPAN style="COLOR: green"&gt;// invoke by normal reflection
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;result1 = (&lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt;)methodInfo.Invoke(s, &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;[] { &lt;SPAN style="COLOR: #a31515"&gt;"Hello" &lt;/SPAN&gt;});
            &lt;SPAN style="COLOR: green"&gt;// invoke by the extension method from FastReflectionLib,
            // which is much faster
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;result2 = (&lt;SPAN style="COLOR: blue"&gt;bool&lt;/SPAN&gt;)methodInfo.FastInvoke(s, &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;[] { &lt;SPAN style="COLOR: #a31515"&gt;"Hello" &lt;/SPAN&gt;});
        }
    }
}&lt;/PRE&gt;
&lt;P&gt;When we get the MethodInfo object, we can call the Invoke method to execute the method. FastReflectionLib contains several extension methods on these types (such as MethodInfo), so we can just put "Fast" before the method to replace the build-in ones. Comparing with the build-in functions, these new implementations get big performance improvements.&lt;/P&gt;
&lt;H1&gt;Use the worker object directly&lt;/H1&gt;
&lt;P&gt;For example, the extension method "FastInvoke" defined for MethodInfo type gets the corresponding worker object by the MethodInfo instance as the key from cache, and execute the Invoke method in the worker object. Apparently keeping the worker object and use it directly after getting it would give us better perfermance than retrieving it from cache again and again.&lt;/P&gt;
&lt;P&gt;Here's the list of worker types for each XxxInfo type:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;PropertyInfo: IPropertyAccessor &lt;/LI&gt;
&lt;LI&gt;MethodInfo: IMethodInvoker &lt;/LI&gt;
&lt;LI&gt;ConstructorInfo: IConstructorInvoker &lt;/LI&gt;
&lt;LI&gt;FieldInfo: IFieldAccessor &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;We can get an IMethodInvoker object from FastReflectionCaches.MethodInvokerCache by a MethodInfo object: &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;static void &lt;/SPAN&gt;Execute(&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;methodInfo, &lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;instance, &lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;times)
{ 
    &lt;SPAN style="COLOR: #2b91af"&gt;IMethodInvoker &lt;/SPAN&gt;invoker = &lt;SPAN style="COLOR: #2b91af"&gt;FastReflectionCaches&lt;/SPAN&gt;.MethodInvokerCache.Get(methodInfo);
    &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[] parameters = &lt;SPAN style="COLOR: blue"&gt;new object&lt;/SPAN&gt;[0];
    &lt;SPAN style="COLOR: blue"&gt;for &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;i = 0; i &amp;lt; times; i++)
    {
        invoker.Invoke(instance, parameters);
    }
}&lt;/PRE&gt;
&lt;H1&gt;Default implementations of worker types and extensions&lt;/H1&gt;
&lt;P&gt;FastReflectionLib has already provide default implementations for each worker interfaces. These implementations generate lambda expressions and compile them (by call Compile method) to delegate objects with the same signatures as the corresponding reflection methods. The implementation is simle, general and safe than directly Emit and the performance is good enough for most scenarios (please refer to the Benchmarks section).&lt;/P&gt;
&lt;P&gt;But it's not the most efficient way to do so. The best optimized way by Emit could get better performance than directly access the members in code (&lt;A href="http://www.codeplex.com/Dynamic" mce_href="http://www.codeplex.com/Dynamic"&gt;Dynamic Reflection Library&lt;/A&gt; is one of these implementations). You can build your one worker interface implementation and factory to replace the build-in ones if necessary:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BetterPropertyAccessor &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IPropertyAccessor
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;BetterPropertyAccessor(&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;propertyInfo) { ... }

    ...
}

&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BetterPropertyAccessorFactory &lt;/SPAN&gt;:
    &lt;SPAN style="COLOR: #2b91af"&gt;IFastReflectionFactory&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IPropertyAccessor&lt;/SPAN&gt;&amp;gt;
{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IPropertyAccessor &lt;/SPAN&gt;Create(&lt;SPAN style="COLOR: #2b91af"&gt;PropertyInfo &lt;/SPAN&gt;key)
    {
        &lt;SPAN style="COLOR: blue"&gt;return new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BetterPropertyAccessor&lt;/SPAN&gt;(key);
    }
}

&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Program
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;static void &lt;/SPAN&gt;Main(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] args)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;FastReflectionFactories&lt;/SPAN&gt;.PropertyAccessorFactory =
            &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BetterPropertyAccessorFactory&lt;/SPAN&gt;();

        ...
    }
}&lt;/PRE&gt;
&lt;H1&gt;Default implementaions of caches and extensions&lt;/H1&gt;
&lt;P&gt;FastReflectionLib uses the caches based on System.Collections.Generic.Dictionary&amp;lt;TKey, TValue&amp;gt;. When we invoke a FastXxx extension method, the library would retrieve the worker object from the cache container and execute it. If the worker object cannot be found in the cache, a new one would be created by the corresponding factory. In the Benchmarks section we can found that considerable time is "wasted" in searching the cache.&lt;/P&gt;
&lt;P&gt;If you have better cache implementation you can replace the build-in one as following:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BetterMethodInvokerCache &lt;/SPAN&gt;:
    &lt;SPAN style="COLOR: #2b91af"&gt;IFastReflectionCache&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #2b91af"&gt;IMethodInvoker&lt;/SPAN&gt;&amp;gt;
{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IMethodInvoker &lt;/SPAN&gt;Get(&lt;SPAN style="COLOR: #2b91af"&gt;MethodInfo &lt;/SPAN&gt;key) { ... }
}

&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Program
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;static void &lt;/SPAN&gt;Main(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] args)
    {
        &lt;SPAN style="COLOR: #2b91af"&gt;FastReflectionCaches&lt;/SPAN&gt;.MethodInvokerCache = 
            &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;BetterMethodInvokerCache&lt;/SPAN&gt;();

        ...
    }
}&lt;/PRE&gt;
&lt;H1&gt;Cache the worker objects by your own&lt;/H1&gt;
&lt;P&gt;FastReflectionLib uses the reflection objects (such as PropertyInfo) as key to cache the worker object (such as PropertyAccessor). But in some scenarios, we can cache the worker objects by your own. Here's an sample web site "CustomCache" release with the source of FastReflectionLib, which contains a series of overloaded FastEval extension methods that can be used as an efficient replacement for the build-in Eval method in some cases. The sample:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;uses both the Type of class and the property name as a "joint key" to cache the PropertyAccessor objects. &lt;/LI&gt;
&lt;LI&gt;uses PropertyAccessor to get the value of property defined in an "anonymous object". &lt;/LI&gt;
&lt;LI&gt;caches in the scope of "page" instead of the whole AppDomain.&amp;nbsp; &lt;/LI&gt;&lt;/UL&gt;
&lt;H1 name="Benchmarks"&gt;Benchmarks&lt;/H1&gt;
&lt;P&gt;A benchmark project is provided with the source of FastReflectionLib. Here's part of the results (the benchmarks were run on my laptop with release build):&lt;/P&gt;
&lt;P&gt;Execute the following method 1,000,000 times:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;public class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Test
&lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;MethodWithArgs(&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;a1, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;a2) { }
}&lt;/PRE&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=5 border=1&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;STRONG&gt;The way to execute&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD class=""&gt;&lt;STRONG&gt;Time elapsed (in second)&lt;/STRONG&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Directly invoke&lt;/TD&gt;
&lt;TD class=""&gt;0.0071397&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;Build-in reflection&lt;/TD&gt;
&lt;TD class=""&gt;1.4936181&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;MethodInvoker.Invoke&lt;/TD&gt;
&lt;TD class=""&gt;0.0468326&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class=""&gt;FastInvoke&lt;/TD&gt;
&lt;TD class=""&gt;0.1373712&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6860830" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="C#" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/C_2300_/default.aspx" /><category term="Reflection" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/Reflection/default.aspx" /><category term="CodePlex" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/CodePlex/default.aspx" /></entry><entry><title>Build a Simple Control to Refresh UpdatePanel from Client Side</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2008/04/28/build-a-simple-control-to-refresh-updatepanel-from-client-side.aspx" /><link rel="enclosure" type="application/zip" length="20523" href="http://weblogs.asp.net/jeffreyzhao/attachment/6135085.ashx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2008/04/28/build-a-simple-control-to-refresh-updatepanel-from-client-side.aspx</id><published>2008-04-28T01:15:00Z</published><updated>2008-04-28T01:15:00Z</updated><content type="html">&lt;p&gt;&lt;i&gt;(It's the post I wrote one year ago in my previous blog which has been cancelled now.)&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://daron.yondem.com/" mce_href="http://daron.yondem.com/"&gt;Daron Yondem&lt;/a&gt; &lt;a href="http://daron.yondem.com/PermaLink.aspx?guid=52b9bf2e-bf76-439d-8a5f-e9b1c70ce9e2" mce_href="http://daron.yondem.com/PermaLink.aspx?guid=52b9bf2e-bf76-439d-8a5f-e9b1c70ce9e2"&gt;provided a solution&lt;/a&gt; to refresh UpdatePanels from client side. He built an Extender control (with AjaxControlTookit) and use an invisible textbox as an trigger to raise an async postback. The extender model in ASP.NET AJAX is an light-weight solution to build extensions for existing controls, but these extenders based on AjaxControlToolkit is realy heavy. Using a single extender control build upon AjaxControlToolkit will cause all the base scripts to load on the page. It's probably not a good idea to use such a heavy model and some simple solution is just enough for some simple objectives.&lt;/p&gt;  &lt;p&gt;All we should do for the current feature is just to generate JavaScript proxies in the page. Actually I've also build an simple control to help the devs to raise async postbacks from client side, encapsulated the way described &lt;a href="http://weblogs.asp.net/jeffreyzhao/archive/2008/04/26/refresh-the-updatepanel-using-javascript-code.aspx" mce_href="http://weblogs.asp.net/jeffreyzhao/archive/2008/04/26/refresh-the-updatepanel-using-javascript-code.aspx"&gt;in this post&lt;/a&gt;. It can be used as following:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ajaxExt&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;JavaScriptUpdater&lt;/span&gt;&lt;span&gt; &lt;span style="color: red;"&gt;ID&lt;/span&gt;&lt;span style="color: blue;"&gt;="Updater1"&lt;/span&gt; &lt;span style="color: red;"&gt;runat&lt;/span&gt;&lt;span style="color: blue;"&gt;="server"&lt;/span&gt; &lt;span style="color: red;"&gt;MethodName&lt;/span&gt;&lt;span style="color: blue;"&gt;="Refresh"&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;TriggeredPanels&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ajaxExt&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;TriggeredPanel&lt;/span&gt; &lt;span style="color: red;"&gt;UpdatePanelID&lt;/span&gt;&lt;span style="color: blue;"&gt;="up1"&lt;/span&gt; &lt;span style="color: blue;"&gt;/&amp;gt;        &lt;br&gt;&lt;/span&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0, 128, 0);"&gt;&amp;lt;!-- other UpdatePanels need to be updated --&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;TriggeredPanels&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ajaxExt&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;JavaScriptUpdater&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt; &lt;/p&gt;  &lt;p&gt;The MethodName property in this control indicates the name of the proxy method generated in the client. Each control will be provided a collection of references to the UpdatePanels on the page. And now, devs can raise an async postback to refresh those UpdatePanels by executing the following method:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;UpdatePanels.Refresh();&lt;/p&gt;  &lt;p&gt;First of all, we should define a class as the element for the collection of UpdatePanel would be triggered. It can't be easier:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;TriggeredPanel&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; UpdatePanelID { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Of course we'll expose the collection in the control:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span&gt;[&lt;span style="color: rgb(43, 145, 175);"&gt;PersistChildren&lt;/span&gt;(&lt;span style="color: blue;"&gt;false&lt;/span&gt;)]&lt;/span&gt;     &lt;br&gt;&lt;span&gt;[&lt;span style="color: rgb(43, 145, 175);"&gt;ParseChildren&lt;/span&gt;(&lt;span style="color: blue;"&gt;true&lt;/span&gt;)]&lt;/span&gt;     &lt;br&gt;&lt;span&gt;[&lt;span style="color: rgb(43, 145, 175);"&gt;NonVisualControl&lt;/span&gt;]&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;JavaScriptUpdater&lt;/span&gt; : &lt;span style="color: rgb(43, 145, 175);"&gt;Control&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;...&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43, 145, 175);"&gt;TriggeredPanel&lt;/span&gt;&amp;gt; m_triggeredPanels = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43, 145, 175);"&gt;TriggeredPanel&lt;/span&gt;&amp;gt;();&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;[&lt;span style="color: rgb(43, 145, 175);"&gt;PersistenceMode&lt;/span&gt;(&lt;span style="color: rgb(43, 145, 175);"&gt;PersistenceMode&lt;/span&gt;.InnerProperty)]&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43, 145, 175);"&gt;TriggeredPanel&lt;/span&gt;&amp;gt; TriggeredPanels&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;get&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; m_triggeredPanels;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;...&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Please note that the MethodName can only be modified during initialize period. It's the way which has been widely used in ASP.NET AJAX to keep the consistency of an control's settings in the lifecycle. Please see the following code:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;bool&lt;/span&gt; m_pageInitialized = &lt;span style="color: blue;"&gt;false&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; m_methodName;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; MethodName&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;get&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_methodName;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;set&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_initialized)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;throw&lt;/span&gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;InvalidOperationException&lt;/span&gt;(&lt;span style="color: rgb(163, 21, 21);"&gt;"..."&lt;/span&gt;);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_methodName = &lt;span style="color: blue;"&gt;value&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;protected&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;override&lt;/span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnInit(&lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt; e)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;base&lt;/span&gt;.OnInit(e);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page.InitComplete += (sender, ev) =&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_pageInitialized = &lt;span style="color: blue;"&gt;true&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;};&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page.Load += &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;EventHandler&lt;/span&gt;(OnPageLoad);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (!&lt;span style="color: rgb(43, 145, 175);"&gt;ScriptManager&lt;/span&gt;.GetCurrent(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page).IsInAsyncPostBack)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page.PreRenderComplete += &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;EventHandler&lt;/span&gt;(OnPagePreRenderComplete);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Each helper control on the page will put a invisible button on the page as the trigger. The following code will dynamically generate an LinkButton control on the page and handle its Click event:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; m_triggerUniqueId = &lt;span style="color: blue;"&gt;null&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnPageLoad(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt; e)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;LinkButton&lt;/span&gt; button = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;LinkButton&lt;/span&gt;();&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;button.Text = &lt;span style="color: rgb(163, 21, 21);"&gt;"Update"&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;button.ID = &lt;span style="color: blue;"&gt;this&lt;/span&gt;.ID + &lt;span style="color: rgb(163, 21, 21);"&gt;"_Trigger"&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;button.Style[&lt;span style="color: rgb(43, 145, 175);"&gt;HtmlTextWriterStyle&lt;/span&gt;.Display] = &lt;span style="color: rgb(163, 21, 21);"&gt;"none"&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;button.Click += &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;EventHandler&lt;/span&gt;(OnTriggerClick);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page.Form.Controls.Add(button);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_triggerUniqueId = button.UniqueID;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ScriptManager&lt;/span&gt;.GetCurrent(&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page).RegisterAsyncPostBackControl(button);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Before page's rendering, we should register the proxy to the page:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;static&lt;/span&gt; &lt;span style="color: blue;"&gt;readonly&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; BaseScripts =&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;@"if (!window.UpdatePanels) window.UpdatePanels = {};&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;UpdatePanels.__createUpdateMethod = function(triggerUniqueId)&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return function()&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;__doPostBack(triggerUniqueId, '');&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;}"&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;const&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; RegisterMethodTemplate = &lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;"\nUpdatePanels['{0}'] = UpdatePanels.__createUpdateMethod('{1}');"&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnPagePreRenderComplete(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt; e)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page.ClientScript.RegisterClientScriptBlock(&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.GetType(),&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;"BasicScripts"&lt;/span&gt;,&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;JavaScriptUpdater&lt;/span&gt;.BaseScripts,&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;true&lt;/span&gt;);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Page.ClientScript.RegisterClientScriptBlock(&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.GetType(),&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_triggerUniqueId,&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;String&lt;/span&gt;.Format(&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;JavaScriptUpdater&lt;/span&gt;.RegisterMethodTemplate,&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.MethodName,&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.m_triggerUniqueId),&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;true&lt;/span&gt;);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;When the page received an async postback raised by the proxy, the Click event of the dynamic button would be fired. As you can see later, I defined three events in the contorl. The ResolveTriggeredPanel event is to help the control to find the specified UpdatePanels. In addition, the other two events,&amp;nbsp; Updating and Updated will be fired before and after refreshing the UpdatePanels:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;EventHandler&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43, 145, 175);"&gt;ResolveTriggeredPanelEventArgs&lt;/span&gt;&amp;gt; ResolveTriggeredPanel;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;EventHandler&lt;/span&gt; Updating;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;EventHandler&lt;/span&gt; Updated;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;void&lt;/span&gt; OnTriggerClick(&lt;span style="color: blue;"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt; e)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Updating != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Updating(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt;.Empty);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(43, 145, 175);"&gt;TriggeredPanel&lt;/span&gt; panel &lt;span style="color: blue;"&gt;in&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;.TriggeredPanels)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;UpdatePanel&lt;/span&gt; updatePanel = &lt;span style="color: blue;"&gt;this&lt;/span&gt;.FindTriggeredPanel(panel.UpdatePanelID);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (updatePanel != &lt;span style="color: blue;"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; updatePanel.UpdateMode != &lt;span style="color: rgb(43, 145, 175);"&gt;UpdatePanelUpdateMode&lt;/span&gt;.Always)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;updatePanel.Update();&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Updated != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.Updated(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt;.Empty);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;private&lt;/span&gt;&lt;span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;UpdatePanel&lt;/span&gt; FindTriggeredPanel(&lt;span style="color: blue;"&gt;string&lt;/span&gt; id)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;UpdatePanel&lt;/span&gt; triggeredPanel = &lt;span style="color: blue;"&gt;null&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (id != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;triggeredPanel = &lt;span style="color: blue;"&gt;this&lt;/span&gt;.NamingContainer.FindControl(id) &lt;span style="color: blue;"&gt;as&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;UpdatePanel&lt;/span&gt;;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (triggeredPanel == &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ResolveTriggeredPanelEventArgs&lt;/span&gt; e = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;ResolveTriggeredPanelEventArgs&lt;/span&gt;(id);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ResolveTriggeredPanel != &lt;span style="color: blue;"&gt;null&lt;/span&gt;)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ResolveTriggeredPanel(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, e);&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;triggeredPanel = e.TriggeredPanel;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; triggeredPanel;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Oh, I've missed the ResolveUpdatePanelEventArgs class. Here it is:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt;&lt;span&gt; &lt;span style="color: blue;"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;ResolveTriggeredPanelEventArgs&lt;/span&gt; : &lt;span style="color: rgb(43, 145, 175);"&gt;EventArgs&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: blue;"&gt;string&lt;/span&gt; ID { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;private&lt;/span&gt; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;UpdatePanel&lt;/span&gt; TriggeredPanel { &lt;span style="color: blue;"&gt;get&lt;/span&gt;; &lt;span style="color: blue;"&gt;set&lt;/span&gt;; }&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;public&lt;/span&gt; ResolveTriggeredPanelEventArgs(&lt;span style="color: blue;"&gt;string&lt;/span&gt; id)&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.ID = id;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;     &lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Here we have finished the control. Let's see a simple demo of it. The following is the declarative code in aspx file:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;asp&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;UpdatePanel&lt;/span&gt;&lt;span&gt; &lt;span style="color: red;"&gt;runat&lt;/span&gt;&lt;span style="color: blue;"&gt;="server"&lt;/span&gt; &lt;span style="color: red;"&gt;ID&lt;/span&gt;&lt;span style="color: blue;"&gt;="up1"&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="color: blue;"&gt;=&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;DateTime&lt;/span&gt;.Now.ToString() &lt;span style="background: yellow none repeat scroll 0% 50%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"&gt;%&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;asp&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;UpdatePanel&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ajaxExt&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;JavaScriptUpdater&lt;/span&gt;&lt;span&gt; &lt;span style="color: red;"&gt;ID&lt;/span&gt;&lt;span style="color: blue;"&gt;="Updater1"&lt;/span&gt; &lt;span style="color: red;"&gt;runat&lt;/span&gt;&lt;span style="color: blue;"&gt;="server"&lt;/span&gt; &lt;span style="color: red;"&gt;MethodName&lt;/span&gt;&lt;span style="color: blue;"&gt;="Refresh"&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;TriggeredPanels&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ajaxExt&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;TriggeredPanel&lt;/span&gt; &lt;span style="color: red;"&gt;UpdatePanelID&lt;/span&gt;&lt;span style="color: blue;"&gt;="up1"&lt;/span&gt; &lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;TriggeredPanels&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;ajaxExt&lt;/span&gt;&lt;span style="color: blue;"&gt;:&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;JavaScriptUpdater&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;nbsp;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;input&lt;/span&gt;&lt;span&gt; &lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;="button"&lt;/span&gt; &lt;span style="color: red;"&gt;onclick&lt;/span&gt;&lt;span style="color: blue;"&gt;="UpdatePanels.Refresh()"&lt;/span&gt; &lt;span style="color: red;"&gt;value&lt;/span&gt;&lt;span style="color: blue;"&gt;="Refresh"&lt;/span&gt; &lt;span style="color: blue;"&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;When we click the button, the UpdatePanel will be refresh without updating the whole page. Let's see the proxy code generated in client side:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;script&lt;/span&gt;&lt;span&gt; &lt;span style="color: red;"&gt;type&lt;/span&gt;&lt;span style="color: blue;"&gt;="text/javascript"&amp;gt;&lt;/span&gt;&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (!window.UpdatePanels) window.UpdatePanels = {};&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;UpdatePanels._createUpdateMethod = &lt;span style="color: blue;"&gt;function&lt;/span&gt;(triggerUniqueId)&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;$get(triggerUniqueId).click();&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;UpdatePanels[&lt;span style="color: rgb(163, 21, 21);"&gt;'Refresh'&lt;/span&gt;] = UpdatePanels._createUpdateMethod(&lt;span style="color: rgb(163, 21, 21);"&gt;'Updater1_Trigger'&lt;/span&gt;);&lt;/span&gt;    &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;script&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;    &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;nbsp;&lt;/span&gt;    &lt;br&gt;&lt;span&gt;...&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;    &lt;br&gt;&lt;span style="color: blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;a&lt;/span&gt;&lt;span&gt; &lt;span style="color: red;"&gt;id&lt;/span&gt;&lt;span style="color: blue;"&gt;="UpdaterButton"&lt;/span&gt; &lt;span style="color: red;"&gt;href&lt;/span&gt;&lt;span style="color: blue;"&gt;="javascript:__doPostBack('UpdaterButton','')"&lt;/span&gt;&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: red;"&gt;style&lt;/span&gt;&lt;span style="color: blue;"&gt;="&lt;/span&gt;&lt;span style="color: red;"&gt;display&lt;/span&gt;:&lt;span style="color: blue;"&gt;none&lt;/span&gt;;&lt;span style="color: blue;"&gt;"&amp;gt;&lt;/span&gt;Update&lt;span style="color: blue;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;a&lt;/span&gt;&lt;span style="color: blue;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;The attachment is the source code of the JavaScriptUpdater control.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6135085" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="ASP.NET AJAX" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/ASP.NET+AJAX/default.aspx" /><category term="UpdatePanel" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/UpdatePanel/default.aspx" /><category term="JavaScript" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/JavaScript/default.aspx" /></entry><entry><title>Refresh the UpdatePanel using JavaScript Code</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2008/04/26/refresh-the-updatepanel-using-javascript-code.aspx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2008/04/26/refresh-the-updatepanel-using-javascript-code.aspx</id><published>2008-04-26T12:38:00Z</published><updated>2008-04-26T12:38:00Z</updated><content type="html">&lt;p&gt;&lt;i&gt;(It's the post I wrote one year ago in my previous blog which has been cancelled now.)&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;Lots of customers asked me that how to refresh the UpdatePanel - it actually is to raise an async postback using JavaScript code. The feature is quite important in some scenarios but unfortunately, ASP.NET AJAX does not give any native support, so we should find work arounds to do that.&lt;/p&gt;  &lt;p&gt;An UpdatePanel will be refreshed if the user clicks the specific control in the page and the control is the trigger that raises the async postback. The straightest thought of raising an async postback is to simulate a button's clicking. There're several kinds of buttons in ASP.NET (we use the concept in ASP.NET rather than the concept in HTML since the server side konws ASP.NET better). They are Butto&lt;strike&gt;&lt;/strike&gt;n, LinkButton, ImageButton, etc. Let's just look at the LinkButton control since it will shows the things we need. (I use an master page here to show the effect of NamingContainer.):&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;lt;!-- Declarative code in ASPX page --&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(199, 21, 133);"&gt;asp&lt;/span&gt;:&lt;span style="color: rgb(128, 0, 0);"&gt;LinkButton&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;ID&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"LinkButton1"&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;runat&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"server"&amp;gt;&lt;/span&gt;LinkButton&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(199, 21, 133);"&gt;asp&lt;/span&gt;:&lt;span style="color: rgb(128, 0, 0);"&gt;LinkButton&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;     &lt;br&gt;    &lt;br&gt;&lt;span style="color: rgb(0, 128, 0);"&gt;&amp;lt;!-- The html generated in client side --&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;a&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;id&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"ctl00_Main_LinkButton1"&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;href&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"javascript:__doPostBack('ctl00$Main$LinkButton1','')"&amp;gt;&lt;/span&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LinkButton     &lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;a&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;A LinkButton on server side generates an anchor tag on the page. The way to submit the form when click the anchor is to execute the JavaScript method "__doPostBack". Please note that it's really simple for us to simulate that. The only thing we should pay attention to is the first parameter passed to the method. What's that? &lt;/p&gt;  &lt;p&gt;An experience ASP.NET programmer will easily figure out that a string separated by dollar signs ($) is most likely the UniqueID of the control, which is used to indicate the control at server-side, and then the proper event will be raised, etc. So, if we are going to simulate the postback raised by the LinkButton, its UniqueID shoud be write to clint side for further use. &lt;/p&gt;  &lt;p&gt;I'm going to show you a demo here to tell the way discussed above. At first, we should build a page with an UpdatePanel and a invisible LinkButton in it. Please note that we set the style of the LinkButton to "display:none" rather than set its Visibile property to false, otherwise the LinkButton won't be rendered on the page, which will cause an exception when postback:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(199, 21, 133);"&gt;asp&lt;/span&gt;:&lt;span style="color: rgb(128, 0, 0);"&gt;UpdatePanel&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;ID&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"UpdatePanel1"&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;runat&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"server"&amp;gt;&lt;/span&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: black; background-color: rgb(255, 255, 0);"&gt;&amp;lt;%&lt;/span&gt;= DateTime.Now &lt;span style="color: black; background-color: rgb(255, 255, 0);"&gt;%&amp;gt;&lt;/span&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(128, 0, 0);"&gt;ContentTemplate&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(199, 21, 133);"&gt;asp&lt;/span&gt;:&lt;span style="color: rgb(128, 0, 0);"&gt;UpdatePanel&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: rgb(199, 21, 133);"&gt;asp&lt;/span&gt;:&lt;span style="color: rgb(128, 0, 0);"&gt;LinkButton&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;ID&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"LinkButton1"&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;runat&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"server"&lt;/span&gt; &lt;span style="color: rgb(255, 0, 0);"&gt;style&lt;/span&gt;=&lt;span style="color: rgb(0, 0, 255);"&gt;"display:none;"&amp;gt;&lt;/span&gt;     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LinkButton     &lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: rgb(199, 21, 133);"&gt;asp&lt;/span&gt;:&lt;span style="color: rgb(128, 0, 0);"&gt;LinkButton&lt;/span&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&amp;gt;&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Secondly, write the following code to the page. You can find that we should write the UniqueID of the LinkButton to the client:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;function&lt;/span&gt; raiseAsyncPostback()     &lt;br&gt;{     &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __doPostBack("&lt;span style="color: rgb(139, 0, 0);"&gt;&amp;lt;%= this.LinkButton1.UniqueID %&amp;gt;&lt;/span&gt;", "");     &lt;br&gt;}&lt;/p&gt;  &lt;p&gt;The last thing to do is to make the LinkButton raising an async postback, so add the code to the code behind file:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ScriptManager&lt;/span&gt;.GetCurrent(&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;).RegisterAsyncPostBackControl(&lt;span style="color: rgb(0, 0, 255);"&gt;this&lt;/span&gt;.LinkButton1);&lt;/p&gt;  &lt;p&gt;Now we can simply call the raiseAsyncPostBack method defined in the page when we want to raise an async postback using JavaScript code. Both the client and server will think the LinkButton is clicked. The client side will raise an async postback and the server will fire the Click event of the LinkButton. If we want to refresh some UpdatePanels when we execute the JavaScirpt method, we can just assign the LinkButton to the UpdatePanels as an AsyncPostBackTrigger.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6132010" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="AJAX" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/AJAX/default.aspx" /><category term="ASP.NET AJAX" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/ASP.NET+AJAX/default.aspx" /><category term="UpdatePanel" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/UpdatePanel/default.aspx" /></entry><entry><title>LINQ to SQL Extension: Batch Deletion with Lambda Expression</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2008/03/06/linq-to-sql-extension-batch-deletion-by-lambda-expression.aspx" /><link rel="enclosure" type="application/zip" length="21187" href="http://weblogs.asp.net/jeffreyzhao/attachment/5919866.ashx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2008/03/06/linq-to-sql-extension-batch-deletion-by-lambda-expression.aspx</id><published>2008-03-06T08:40:00Z</published><updated>2008-03-06T08:40:00Z</updated><content type="html">&lt;p&gt;Batch deletion in the O/R Mapping frameworks is always depressing. We need to query all the entities we want to delete from the database, pass them to the DeleteOnSubmit or DeleteAllOnSubmit methods of DataContext, and finally invoke SubmitChanges to delete the records form database. In this case, we will cost an additional query and send lots of "DELETE" commands to database. How wasteful!&lt;/p&gt;  &lt;p&gt;So if we want to make batch deletion with LINQ to SQL, we'll probably execute a SQL command in souce code:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;&lt;span&gt; db = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;();&lt;/span&gt;     &lt;br&gt;&lt;span&gt;db.ExecuteCommand(&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(163, 21, 21);"&gt;"DELETE FROM Item WHERE [CreateTime] &amp;lt; {0}"&lt;/span&gt;, &lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;DateTime&lt;/span&gt;.UtcNow.AddMonths(-1));&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;But in my opinion, it's ugly if we put SQL commands in source code. Ideally, the developers should focus on the business logics, data access logics or domain models, and the database operations are encapsulated by some other layers. In the days without O/R Mapping frameworks, we always defines Stored Procedures in databases and make calls in the source code. And finally we get O/R Mapping frameworks such as Hibernate and LINQ to SQL, so in most cases we could write code to query the database without dealing with SQL commands.&lt;/p&gt;  &lt;p&gt;But batch deletion is one of the exceptions, as I said minutes ago. To avoid making batch deletion with SQL commands, I build an extension method for LINQ to SQL. Now we can delete the records from database with lambda expression:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;&lt;span&gt; db = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;();&lt;/span&gt;     &lt;br&gt;&lt;span&gt;db.Items.Delete(item =&amp;gt; item.CreateTime &amp;lt; &lt;/span&gt;&lt;span&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;DateTime&lt;/span&gt;.UtcNow.AddMonths(-1));&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;Of course, we could use more complicated expressions to indicate the entities to delete:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;&lt;span&gt; db = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;();&lt;/span&gt;     &lt;br&gt;&lt;span&gt;db.Items.Delete(item =&amp;gt;&lt;/span&gt;     &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;item.CreateTime &amp;lt; &lt;span style="color: rgb(43, 145, 175);"&gt;DateTime&lt;/span&gt;.UtcNow.AddMonths(-1) || &lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;item.ViewCount &amp;lt; item.CommentCount &amp;amp;&amp;amp; item.UserName != &lt;span style="color: rgb(163, 21, 21);"&gt;"jeffz"&lt;/span&gt;);&lt;/span&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;For the extensions I built for LINQ to SQL, most of them are based on DataContext. But now I extended the Table&amp;lt;TEntity&amp;gt; class. The implementation is not so difficult as I thought before I finish it. The key part of extending with LINQ/Lamba Expression is parsing the Expression Tree, but in this case, most of the expressions are binary expression and that's almost all of the extension - I just implemented the common used conditions. For instance, it doesn't support the expressions like "item.Introduction.Length &amp;lt; 10" and it should be converted to the use of LEN function in an completely implemented version.&lt;/p&gt;  &lt;p&gt;The "Where Condition" in the SQL command converted from lambda expression is built in 3 steps, you can see the corresponding classes in the source code for more details:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Use PartialEvaluator class to replce the expressions which can be evaluated directly with the constant expressions indicated the calculated results (E.g., replace the expression "3 * 3" with the constant expression of "9", or replace the variables with the values of them). &lt;/li&gt;    &lt;li&gt;Use ConditionBuilder class to collect all the constants in the expression tree as parameters for te SQL command, and generate the SQL where condition with the parameters' placeholders in it (E.g., "[CreateTime] &amp;lt; {0} AND [UserName] &amp;lt;&amp;gt; {1}"). &lt;/li&gt;    &lt;li&gt;Use DataContext.ExecuteCommand method to execute the whole SQL command with parameters and return the number of effected records. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Now we have the function of batch deletion but what about batch updating? Actually I'm working on it. I'm going to let the developers updating the records in the database like this:&lt;/p&gt;  &lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; margin-left: 20px; color: black; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New'; background-color: rgb(255, 255, 225);"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;&lt;span&gt; db = &lt;span style="color: blue;"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;ItemDataContext&lt;/span&gt;();&lt;/span&gt;    &lt;br&gt;&lt;span&gt;db.Items.Update(&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;item =&amp;gt; &lt;span style="color: blue;"&gt;new &lt;span style="color: rgb(43, 145, 175);"&gt;Item&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Introduction = item.Title + &lt;span style="color: rgb(163, 21, 21);"&gt;"Hello World"&lt;/span&gt;,&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ViewCount = item.ViewCount + 1,&lt;/span&gt;    &lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}, &lt;span style="color: green;"&gt;// &lt;/span&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;SET [Introduction] = [Title] + 'Hello World', ...&lt;/span&gt;&lt;span style="color: green;"&gt;     &lt;br&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;item =&amp;gt; item.CommentCount &amp;gt; 100 &lt;span style="color: green;"&gt;/* &lt;/span&gt;&lt;/span&gt;&lt;span style="color: green;"&gt;WHERE condition&lt;/span&gt;&lt;span style="color: green;"&gt; */&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;For more details about the batch deletion extionsion please see the attachment.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.cnblogs.com/JeffreyZhao/archive/2008/03/05/LINQ-to-SQL-Batch-Delete-Extension.html" mce_href="http://www.cnblogs.com/JeffreyZhao/archive/2008/03/05/LINQ-to-SQL-Batch-Delete-Extension.html" target="_blank"&gt;Chinese version of this post&lt;/a&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5919866" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="Lambda Expression" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/Lambda+Expression/default.aspx" /><category term="Batch Deletion" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/Batch+Deletion/default.aspx" /><category term="Expression Tree" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/Expression+Tree/default.aspx" /><category term="LINQ" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/LINQ/default.aspx" /><category term="C#" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/C_2300_/default.aspx" /><category term=".NET" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/.NET/default.aspx" /><category term="LINQ to SQL" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/LINQ+to+SQL/default.aspx" /></entry><entry><title>Giving rich styles to auto-complete feature using StyledAutoCompleteExtender</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2008/03/04/giving-rich-styles-to-auto-complete-feature-using-styledautocompleteextender.aspx" /><link rel="enclosure" type="application/zip" length="458351" href="http://weblogs.asp.net/jeffreyzhao/attachment/5902340.ashx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2008/03/04/giving-rich-styles-to-auto-complete-feature-using-styledautocompleteextender.aspx</id><published>2008-03-04T02:15:00Z</published><updated>2008-03-04T02:15:00Z</updated><content type="html">&lt;P&gt;Auto-complete is one of the key features in ajax style applications. As the most popular ajax toolkit for asp.net development, &lt;A href="http://ajax.asp.net/ajaxtoolkit" mce_href="http://ajax.asp.net/ajaxtoolkit"&gt;Ajax Control Toolkit&lt;/A&gt; provides &lt;A href="http://ajax.asp.net/ajaxtoolkit/AutoComplete/AutoComplete.aspx" mce_href="http://ajax.asp.net/ajaxtoolkit/AutoComplete/AutoComplete.aspx"&gt;AutoCompleteExtender&lt;/A&gt; control to build the feature without writing any JavaScript codes. The current version of AutoCompleteExtender is more powerful than before because that the user can input multiple words in the same text box by setting delimiter characters now. But it's still not so useful in some kinds of scenarios - in my opinion - since the control can only support plain text as the choices.&lt;/P&gt;
&lt;P&gt;"How can we build the auto-complete feature like &lt;A href="http://www.google.com/webhp?complete=1&amp;amp;hl=en" mce_href="http://www.google.com/webhp?complete=1&amp;amp;hl=en"&gt;Google Suggest&lt;/A&gt; using AutoCompleteExtender?" The question like this has been asked times by the developers. The answser is "No, we can't" at the curent moment. But I've extended the AutoCompleteExtender to solve the problem.&lt;/P&gt;
&lt;P&gt;The control I build which I called "StyledAutoCompleteExtender" extends the AutoCompleteExtender and the behavior class it uses on client-side extends the AutoCompleteBehavior. I keep most of the features the same as before to give the best compatibility. We can use the control just like the current AutoCompleteExtender and get the same result. But the new StyleAutoCompleteExtender control will accept a ItemTemplete value as the html template to display a single item. ItemTemplate gives us the flexibility to show the choices as the styles we want.&lt;/P&gt;
&lt;P&gt;For example, we are building the auto-complete features like Google Suggest. What we should do first is to write the declarative code as following:&lt;/P&gt;
&lt;P style="BORDER-RIGHT: rgb(192,192,192) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(192,192,192) 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 20px; BORDER-LEFT: rgb(192,192,192) 1px solid; COLOR: black; MARGIN-RIGHT: 20px; PADDING-TOP: 5px; BORDER-BOTTOM: rgb(192,192,192) 1px solid; FONT-FAMILY: 'Lucida Sans Typewriter','Courier New'; BACKGROUND-COLOR: rgb(255,255,225)"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;asp&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;TextBox&lt;/SPAN&gt;&lt;SPAN&gt; &lt;SPAN style="COLOR: red"&gt;runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="server"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="myTextBox"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="400"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;margin&lt;/SPAN&gt;:&lt;SPAN style="COLOR: blue"&gt;auto&lt;/SPAN&gt;;&lt;SPAN style="COLOR: blue"&gt;"/&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;jeffz&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;StyledAutoCompleteExtender&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="server"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;BehaviorID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="AutoCompleteEx"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="autoComplete1"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;TargetControlID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="myTextBox"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ServicePath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="AutoComplete.asmx"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ServiceMethod&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="GetSearchCompletionList"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;MinimumPrefixLength&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="2"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionInterval&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1000"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;EnableCaching&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="true"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionSetCount&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="10"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListCssClass&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="completionListElement"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListItemCssClass&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="listItem"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListHighlightedItemCssClass&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="highlightedListItem"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListElementID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Panel1"&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ItemTemplate&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;float&lt;/SPAN&gt;:&lt;SPAN style="COLOR: blue"&gt;left&lt;/SPAN&gt;;&lt;SPAN style="COLOR: blue"&gt;"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="keywords"&amp;gt;&lt;/SPAN&gt;{0}&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;span&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;float&lt;/SPAN&gt;:&lt;SPAN style="COLOR: blue"&gt;right&lt;/SPAN&gt;;&lt;SPAN style="COLOR: blue"&gt;"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;class&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="result"&amp;gt;&lt;/SPAN&gt;{1}&lt;SPAN style="COLOR: red"&gt;&amp;amp;nbsp;&lt;/SPAN&gt;results&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;span&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;div&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;clear&lt;/SPAN&gt;:&lt;SPAN style="COLOR: blue"&gt;both&lt;/SPAN&gt;;&lt;SPAN style="COLOR: blue"&gt;"&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ItemTemplate&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;jeffz&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;StyledAutoCompleteExtender&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;asp&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Panel&lt;/SPAN&gt;&lt;SPAN&gt; &lt;SPAN style="COLOR: red"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="Panel1"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="server"&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;asp&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;Panel&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Please focus on the ItemTemplate set in the AutoCompleteExtender. There're format parameters like "{0}" and "{1}" in it. It will be replaced by the value get from the method on server-side - I'll give more information of that later. Actuallly the value of ItemTemplate is the format string witch will be used as the paratemer of String.format() method so we can utilize the localization features in ASP.NET AJAX by setting format parameters as "{0:d}".&lt;/P&gt;
&lt;P&gt;The values to replace the format item would be get from the web service method on server-side. Apparently, we'll probably get multiple values for a single chioces so the return type of the method should be modified. The following is web service method used for our "Google Suggest":&lt;/P&gt;
&lt;P style="BORDER-RIGHT: rgb(192,192,192) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(192,192,192) 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 20px; BORDER-LEFT: rgb(192,192,192) 1px solid; COLOR: black; MARGIN-RIGHT: 20px; PADDING-TOP: 5px; BORDER-BOTTOM: rgb(192,192,192) 1px solid; FONT-FAMILY: 'Lucida Sans Typewriter','Courier New'; BACKGROUND-COLOR: rgb(255,255,225)"&gt;&lt;SPAN&gt;[&lt;SPAN style="COLOR: rgb(43,145,175)"&gt;WebMethod&lt;/SPAN&gt;]&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&lt;SPAN&gt; &lt;SPAN style="COLOR: rgb(43,145,175)"&gt;IList&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&amp;gt; GetSearchCompletionList(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; prefixText, &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; count)&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (count == 0)&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;count = 10;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(43,145,175)"&gt;Random&lt;/SPAN&gt; random = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(43,145,175)"&gt;Random&lt;/SPAN&gt;();&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(43,145,175)"&gt;IList&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&amp;gt; items = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(43,145,175)"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&amp;gt;(count);&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;for&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; i = 0; i &amp;lt; count; i++)&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt; c1 = (&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt;)random.Next(65, 90);&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt; c2 = (&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt;)random.Next(97, 122);&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt; c3 = (&lt;SPAN style="COLOR: blue"&gt;char&lt;/SPAN&gt;)random.Next(97, 122);&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;items.Add(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;prefixText + c1 + c2 + c3,&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;random.Next(10000, 300000)&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;});&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; items;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;The new method should return a list contains an array of objects. Each array will be used to display a single item of choices. The objects in the array will be used as the rest paramesters when calling String.format() method. Please note that if the method returns an array of string as before, the ItemTemplate set in the control would be ignored and everything will work like the traditional AutoCompleteExtender. The final result is just like the following image (the css style defined in the page has been omitted).&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://weblogs.asp.net/blogs/jeffreyzhao/post_images/StyledAutoComplete/my_google_suggest.jpg" mce_src="http://weblogs.asp.net/blogs/jeffreyzhao/post_images/StyledAutoComplete/my_google_suggest.jpg"&gt; &lt;/P&gt;
&lt;P&gt;The most important modification of StyleAutoCompleteExtender is the separation of "the text to complete user's typing" and "the content in the choices".&amp;nbsp; In the current version of StyledAutoCompleteExtender, the first object in the array for each choise will be selected as "the text to complete user's typing". That means the first object could be ignored in ItemTemplate if necessary. The following sample is to simulate the email selection when using &lt;A href="http://mail.live.com/" mce_href="http://mail.live.com"&gt;Windows Live Mail&lt;/A&gt;. Please note that the real feature is purely implemented on client-side but we're using StyleAutoCompleteExtender, which will get the choises from server-side.&lt;/P&gt;
&lt;P&gt;Here're the defined css styles and the declarative code:&lt;/P&gt;
&lt;P style="BORDER-RIGHT: rgb(192,192,192) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(192,192,192) 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 20px; BORDER-LEFT: rgb(192,192,192) 1px solid; COLOR: black; MARGIN-RIGHT: 20px; PADDING-TOP: 5px; BORDER-BOTTOM: rgb(192,192,192) 1px solid; FONT-FAMILY: 'Lucida Sans Typewriter','Courier New'; BACKGROUND-COLOR: rgb(255,255,225)"&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;.completionListElement&lt;/SPAN&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;{&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;visibility&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;hidden&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;margin&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;0px! important&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;background-color&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;inherit&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;color&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;black&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;border&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;solid&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;1px&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;gray&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;cursor&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;pointer&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;text-align&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;left&lt;/SPAN&gt;; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;list-style-type&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;none&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;font-family&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;Verdana&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;font-size&lt;/SPAN&gt;: &lt;SPAN style="COLOR: blue"&gt;11px&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;padding&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;0&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;}&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;.listItem&lt;/SPAN&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;background-color&lt;/SPAN&gt;: &lt;SPAN style="COLOR: blue"&gt;white&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;padding&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;1px&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;}&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;.highlightedListItem&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;background-color&lt;/SPAN&gt;: &lt;SPAN style="COLOR: blue"&gt;#c3ebf9&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;padding&lt;/SPAN&gt; : &lt;SPAN style="COLOR: blue"&gt;1px&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P style="BORDER-RIGHT: rgb(192,192,192) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(192,192,192) 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 20px; BORDER-LEFT: rgb(192,192,192) 1px solid; COLOR: black; MARGIN-RIGHT: 20px; PADDING-TOP: 5px; BORDER-BOTTOM: rgb(192,192,192) 1px solid; FONT-FAMILY: 'Lucida Sans Typewriter','Courier New'; BACKGROUND-COLOR: rgb(255,255,225)"&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;asp&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;TextBox&lt;/SPAN&gt;&lt;SPAN&gt; &lt;SPAN style="COLOR: red"&gt;runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="server"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="myTextBox"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;Width&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="500"&lt;/SPAN&gt; &lt;SPAN style="COLOR: red"&gt;style&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="&lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;height&lt;/SPAN&gt;:&lt;SPAN style="COLOR: blue"&gt;14px&lt;/SPAN&gt;;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;border&lt;/SPAN&gt;: &lt;SPAN style="COLOR: blue"&gt;solid&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;1px&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;gray&lt;/SPAN&gt;; &lt;SPAN style="COLOR: red"&gt;font-family&lt;/SPAN&gt;:&lt;SPAN style="COLOR: blue"&gt;Verdana&lt;/SPAN&gt;; &lt;SPAN style="COLOR: red"&gt;font-size&lt;/SPAN&gt;: &lt;SPAN style="COLOR: blue"&gt;11px&lt;/SPAN&gt;;&lt;SPAN style="COLOR: blue"&gt;"&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;jeffz&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;StyledAutoCompleteExtender&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="server"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;BehaviorID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="AutoCompleteEx"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="autoComplete1"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;TargetControlID&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="myTextBox"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ServicePath&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="AutoComplete.asmx"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;ServiceMethod&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="GetEmailCompletionList"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;MinimumPrefixLength&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="2"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionInterval&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="1000"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;EnableCaching&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="true"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionSetCount&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="10"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListCssClass&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="completionListElement"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListItemCssClass&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="listItem"&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;CompletionListHighlightedItemCssClass&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;="highlightedListItem"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: red"&gt;DelimiterCharacters&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;=",;"&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ItemTemplate&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;{1}&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;ItemTemplate&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;jeffz&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;:&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;StyledAutoCompleteExtender&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And here's the corresponding web service method. Please note that each item in the list is an array with 2 elements. The first one is the text would be set in the textbox and second one is the html string for a single choise.&lt;/P&gt;
&lt;P style="BORDER-RIGHT: rgb(192,192,192) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(192,192,192) 1px solid; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 20px; BORDER-LEFT: rgb(192,192,192) 1px solid; COLOR: black; MARGIN-RIGHT: 20px; PADDING-TOP: 5px; BORDER-BOTTOM: rgb(192,192,192) 1px solid; FONT-FAMILY: 'Lucida Sans Typewriter','Courier New'; BACKGROUND-COLOR: rgb(255,255,225)"&gt;&lt;SPAN style="COLOR: blue"&gt;private&lt;/SPAN&gt;&lt;SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;static&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] s_emails = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[]&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"\"jeffrey zhao at yahoo\" &amp;amp;lt;jeffz@yahoo.com&amp;amp;gt;"&lt;/SPAN&gt;,&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"\"jeffrey zhao at yahoo china\" &amp;amp;lt;jeffz@yahoo.com.cn&amp;amp;gt;"&lt;/SPAN&gt;,&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"\"jeffrey zhao at live mail\" &amp;amp;lt;jeffz@live.com&amp;amp;gt;"&lt;/SPAN&gt;,&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"\"jeffrey zhao at gmail\" &amp;amp;lt;jeffz@gmail.com&amp;amp;gt;"&lt;/SPAN&gt;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;};&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;[&lt;SPAN style="COLOR: rgb(43,145,175)"&gt;WebMethod&lt;/SPAN&gt;]&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&lt;SPAN&gt; &lt;SPAN style="COLOR: rgb(43,145,175)"&gt;IList&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&amp;gt; GetEmailCompletionList(&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; prefixText, &lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt; count)&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(43,145,175)"&gt;IList&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&amp;gt; items = &lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: rgb(43,145,175)"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&amp;gt;();&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;prefixText = prefixText.Trim();&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;foreach&lt;/SPAN&gt; (&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; email &lt;SPAN style="COLOR: blue"&gt;in&lt;/SPAN&gt; s_emails)&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt; (email.Contains(prefixText))&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt; encoded = email.Replace(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; prefixText,&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN&gt;&lt;SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"&amp;lt;b&amp;gt;"&lt;/SPAN&gt; + prefixText + &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;"&amp;lt;/b&amp;gt;"&lt;/SPAN&gt;);&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;items.Add(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt; &lt;SPAN style="COLOR: blue"&gt;object&lt;/SPAN&gt;[]&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;{&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: rgb(43,145,175)"&gt;HttpUtility&lt;/SPAN&gt;.HtmlDecode(email) + &lt;SPAN style="COLOR: rgb(163,21,21)"&gt;";"&lt;/SPAN&gt;,&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;encoded&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;});&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;}&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt; items;&lt;/SPAN&gt; &lt;BR&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Since we have set the DelimiterCharacters property int the control we can type multiple words in the textbox. The final result is showing in the following image.&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://weblogs.asp.net/blogs/jeffreyzhao/post_images/StyledAutoComplete/my_live_mail.jpg" mce_src="http://weblogs.asp.net/blogs/jeffreyzhao/post_images/StyledAutoComplete/my_live_mail.jpg"&gt; &lt;/P&gt;
&lt;P&gt;The implementation of StyleAutoCompleteExtender is not so complex as I thought before and I'll explain it in another post. The attachment is the code of the control with two samples. Please feel free to contract me if you found problems and any suggestions would be better. :)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5902340" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="AJAX" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/AJAX/default.aspx" /><category term="AJAX Control Toolkit" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/AJAX+Control+Toolkit/default.aspx" /><category term="AutoComplete" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/AutoComplete/default.aspx" /><category term="ASP.NET AJAX" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/ASP.NET+AJAX/default.aspx" /></entry><entry><title>IE will be stuck when requests too much? Fake the XHR!</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/jeffreyzhao/archive/2008/02/21/ie-will-be-stuck-when-requests-too-much-fake-the-xhr.aspx" /><link rel="enclosure" type="application/zip" length="1317" href="http://weblogs.asp.net/jeffreyzhao/attachment/5835742.ashx" /><id>http://weblogs.asp.net/jeffreyzhao/archive/2008/02/21/ie-will-be-stuck-when-requests-too-much-fake-the-xhr.aspx</id><published>2008-02-21T15:37:00Z</published><updated>2008-02-21T15:37:00Z</updated><content type="html">&lt;p&gt;It's one of the articles I wrote in &lt;a href="http://www.codeproject.com" title="CodeProject" mce_href="http://www.codeproject.com"&gt;CodeProject&lt;/a&gt;, click &lt;a href="http://www.codeproject.com/KB/ajax/fake-xhr-type.aspx" title="Fake XHR type" mce_href="http://www.codeproject.com/KB/ajax/fake-xhr-type.aspx"&gt;here&lt;/a&gt; to read the original one.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Months ago, a friend of mine, who is a also a consultant and trainer, told me that one of his customers met a problem. IE will be stuck when too many connections have been set up in the page at the same time. The problem is becoming more and more popular since AJAX technology has been widely used these days. When an AJAX application is composed of smaller ones - that we call it "mash up" - the problem will be likely to occur.&lt;/p&gt;

&lt;p&gt;It's a bug in Internet Explorer. When you make a lot of AJAX calls, the browser keeps all the requests in a queue and executes two at a time. So, if you click on something to try to navigate to anthoer page, the browser has to wait for running calls to complete before it can take another one. The bug is quite serious in IE 6 and unfortunately, it still exists in IE 7.&lt;/p&gt;
&lt;h2&gt;Manage the requests programically&lt;/h2&gt;
&lt;p style="color: black; font-size: 10pt;"&gt;The solution is simple. We should maintain the queue ourselves and send requests to the browser's queue from our queue one by one. Thus I wrote a queue to manage the requests. It's really a piece of cake:&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt;&lt;span&gt; (!window.Global)&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;window.Global = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Object();&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;Global._ConnectionManager = &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestDelegateQueue = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Array();&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestInProgress = 0;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._maxConcurrentRequest = 2;&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;Global._ConnectionManager.prototype =&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;enqueueRequestDelegate : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(requestDelegate)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestDelegateQueue.push(requestDelegate);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._request();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;next : &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestInProgress --;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._request();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_request : &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestDelegateQueue.length &amp;lt;= 0) &lt;span style="color: blue;"&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestInProgress &amp;gt;= &lt;span style="color: blue;"&gt;this&lt;/span&gt;._maxConcurrentRequest) &lt;span style="color: blue;"&gt;return&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestInProgress ++;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; requestDelegate = &lt;span style="color: blue;"&gt;this&lt;/span&gt;._requestDelegateQueue.shift();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;requestDelegate.call(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;Global.ConnectionManager = &lt;span style="color: blue;"&gt;new&lt;/span&gt; Global._ConnectionManager();&lt;/span&gt;&lt;/p&gt;

&lt;p mce_keep="true"&gt;I build the component names ConnectionManager using pure JavaScript code without any dependence on any AJAX/JavaScript framework/library. If users want to use this component to manage the request, they should use enqueueRequestDelegate method to put an delegate into the queue. The delegate will be executed when there's no or only one request is running in the browser. And after receiving the response from the server, the user must call the next method to notify the ConnectionManager, and then the ConnectionManager will execute the next pending request delegate if the queue is not empty.&lt;br&gt;&lt;br&gt;For example, if we are using &lt;a href="http://www.prototypejs.org/" title="prototype" target="_blank" mce_href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt; framework to make ten AJAX calls continuously:&lt;br&gt;&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span&gt; requestWithoutQueue()&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; i = 0; i &amp;lt; 10; i++)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;new&lt;/span&gt; Ajax.Request(&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;url,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;method: &lt;span style="color: rgb(163, 21, 21);"&gt;'post'&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;onComplete: callback&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span&gt; callback(xmlHttpRequest)&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: green;"&gt;// do sth.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;And we'll use the ConnectionManager to queue the requests as following:&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span&gt; requestWithQueue()&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; i = 0; i &amp;lt; 10; i++)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; requestDelegate = &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;new&lt;/span&gt; Ajax.Request(&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;url,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;method: &lt;span style="color: rgb(163, 21, 21);"&gt;'post'&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;onComplete: callback,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;onFailure: Global.ConnectionManager.next,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;onException: Global.ConnectionManager.next&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Global.ConnectionManager.enqueueRequestDelegate(requestDelegate);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;&lt;span&gt; callback(xmlHttpRequest)&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: green;"&gt;// do sth.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Global.ConnectionManager.next();&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Please note that we assign the next method to both the onFailure and onException callback handlers to guarantee that it will be called after receiving the response from the server, since the rest delegate in the queue will be failed to execute and the system cannot raise a new call anymore if the next method hasn't been executed.&lt;br&gt;&lt;br&gt;I send the file to my friend and serveral days later he told me that his customer said the component is hard to use. I agreed. It's really verbose and error prone. Apparently the ConnectionManager is not so convenient to be integrated into the existing codes. The devs must make sure that all the requests should be queued in ConnectionManager and the next method must be executed in any case when the request finishes. But it's far from enough yet. More and more AJAX applications will execute scripts created by the server. Perhaps the dynamically created file cannot be loaded successfully if the internet connection of client side is not stable enough. At that time, the scripts execution throws exceptions and the next method which should be executed by design will probably be missed.&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Build a fake XMLHttpRequest type&lt;/h2&gt;
&lt;p&gt;I got an idea after days of thinking. That will be perfect if we can use another component to replace the native XMLHttpRequest object and provide the build-in request queue. If so, devs can solve the problem by putting the script file in the page without changing a single line of code.&lt;br&gt;&lt;br&gt;The solution is much easier than I thought before and now I'm going to show you how to build it.&lt;br&gt;&lt;br&gt;The first thing we should do is to keep the native XHR type. Please note that the follow code has solved the compatibility problem of XHR in different browsers.&lt;br&gt;&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span&gt;window._progIDs = [ &lt;span style="color: rgb(163, 21, 21);"&gt;'Msxml2.XMLHTTP'&lt;/span&gt;, &lt;span style="color: rgb(163, 21, 21);"&gt;'Microsoft.XMLHTTP'&lt;/span&gt; ];&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt;&lt;span&gt; (!window.XMLHttpRequest)&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;window.XMLHttpRequest = &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; i = 0; i &amp;lt; window._progIDs.length; i++)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;try&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; xmlHttp = &lt;span style="color: blue;"&gt;new&lt;/span&gt; _originalActiveXObject(window._progIDs[i]);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; xmlHttp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;catch&lt;/span&gt; (ex) {}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;null&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt;&lt;span&gt; (window.ActiveXObject)&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;window._originalActiveXObject = window.ActiveXObject;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;window.ActiveXObject = &lt;span style="color: blue;"&gt;function&lt;/span&gt;(id)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;id = id.toUpperCase();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;for&lt;/span&gt; (&lt;span style="color: blue;"&gt;var&lt;/span&gt; i = 0; i &amp;lt; window._progIDs.length; i++)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (id === window._progIDs[i].toUpperCase())&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; XMLHttpRequest();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;new&lt;/span&gt; _originalActiveXObject(id);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;window._originalXMLHttpRequest = window.XMLHttpRequest;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;And then, we should create a new class to replace the native XHR type. Most of the methods are just delegated to the corresponding one in the native object.&amp;nbsp;&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span&gt;window.XMLHttpRequest = &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest = &lt;span style="color: blue;"&gt;new&lt;/span&gt; _originalXMLHttpRequest();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.readyState = &lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.readyState;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.onreadystatechange = &lt;/span&gt;&lt;br&gt;&lt;span style="color: blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; this&lt;/span&gt;&lt;span&gt;._createDelegate(&lt;span style="color: blue;"&gt;this&lt;/span&gt;, &lt;span style="color: blue;"&gt;this&lt;/span&gt;._internalOnReadyStateChange);&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;span&gt;window.XMLHttpRequest.prototype = &lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;open : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(method, url, async)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.open(method, url, async);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.readyState = &lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.readyState;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;setRequestHeader : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(header, value)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.setRequestHeader(header, value);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;getResponseHeader : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(header)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.getResponseHeader(header);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;getAllResponseHeaders : &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.getAllResponseHeaders();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;abort : &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.abort();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_createDelegate : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(instance, method)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;return&lt;/span&gt; method.apply(instance, arguments);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;_internalOnReadyStateChange : &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;{&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt; &lt;span style="color: green;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;},&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;send : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(body)&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;{&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt; &lt;span style="color: green;"&gt;/* ... */&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The key points are the implementations of the send method and _internalOnReadyStateChange method. The send method will put a delegate of the native XHR type's method into the queue. The delegate will be executed by the ConnectionManager at a proper time.&amp;nbsp;&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span&gt;send : &lt;span style="color: blue;"&gt;function&lt;/span&gt;(body)&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; requestDelegate = &lt;span style="color: blue;"&gt;this&lt;/span&gt;._createDelegate(&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.send(body);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.readyState = &lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest.readyState;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;});&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Global.ConnectionManager.enqueueRequestDelegate(requestDelegate);&lt;/span&gt;&lt;br&gt;&lt;span&gt;},&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We assign the _internalOnReadyStateChange method as the onreadystatechange callback handler of the native XHR object in the constructor. When the callback function raises, we'll keep all the native properties into our object and execute our onreadystatechange handler. Please note that our new component take the responsibility of executing the next method of ConnectionManager when the readyState equals to 4, which means the current request is "completed", so that the next method can been executed automatically from the devs' point of view.&amp;nbsp;&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span&gt;_internalOnReadyStateChange : &lt;span style="color: blue;"&gt;function&lt;/span&gt;()&lt;/span&gt;&lt;br&gt;&lt;span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;var&lt;/span&gt; xmlHttpRequest = &lt;span style="color: blue;"&gt;this&lt;/span&gt;._xmlHttpRequest;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;try&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.readyState = xmlHttpRequest.readyState;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.responseText = xmlHttpRequest.responseText;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.responseXML = xmlHttpRequest.responseXML;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.statusText = xmlHttpRequest.statusText;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.status = xmlHttpRequest.status;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;catch&lt;/span&gt;(e){}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (4 == &lt;span style="color: blue;"&gt;this&lt;/span&gt;.readyState)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Global.ConnectionManager.next();&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;if&lt;/span&gt; (&lt;span style="color: blue;"&gt;this&lt;/span&gt;.onreadystatechange)&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: blue;"&gt;this&lt;/span&gt;.onreadystatechange.call(&lt;span style="color: blue;"&gt;null&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;/span&gt;&lt;br&gt;&lt;span&gt;},&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;We have tried our best to let the new component behaves as the same as the native XHR type. But it still exists an little thing we can't do it. When we access the status property in the native XHR object, an error would be thrown if the object cannot recieve the headers from server side. But in IE, we can't define the object's property as a method like using __setter__ keyword in FireFox. It's the only difference between the native XHR type and our new one when use the two components.&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;How to use&lt;br&gt;&lt;/h2&gt;
&lt;p&gt;And now, we can easily reference the js file in the page to solve the problem when the user browses the page using IE.&lt;/p&gt;

&lt;p style="border: 1px solid rgb(192, 192, 192); padding: 5px; color: black; background-color: rgb(255, 255, 225); margin-left: 20px; margin-right: 20px; font-family: 'Lucida Sans Typewriter','Courier New';"&gt;&lt;span style="color: green;"&gt;&amp;lt;!--[if IE]&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span style="color: green;"&gt;&amp;lt;script type="text/javascript" src="ConnectionManager.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span style="color: green;"&gt;&amp;lt;script type="text/javascript" src="MyXMLHttpRequest.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span style="color: green;"&gt;&amp;lt;![endif]--&amp;gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;I sent the script files (see attachment)&amp;nbsp;to my friend. It seems that his customer is quite pleased with this solution.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5835742" width="1" height="1"&gt;</content><author><name>JeffreyZhao</name><uri>http://weblogs.asp.net/members/JeffreyZhao.aspx</uri></author><category term="XmlHttpRequest" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/XmlHttpRequest/default.aspx" /><category term="AJAX" scheme="http://weblogs.asp.net/jeffreyzhao/archive/tags/AJAX/default.aspx" /></entry></feed>