Oct 24, 2006 07:37 PM|Eilon|LINK
With the recent Microsoft ASP.NET AJAX Extensions release there has been a lot of feedback, both positive and negative, about the changes made to UpdatePanels. The feedback
has ranged from “wow, finally validators work” all the way to “what the $%*@, my custom control doesn’t work!”
The biggest change we made was related to script registration during async posts. We used to do some extremely hacky parsing work to detect the scripts rendered in a page
and try to execute them on the client.
Atlas CTPs (pre-beta):
In the CTPs we had a special response writer that would parse the rendered contents of the page. It would look for specific items such as <script> tags, <input> tags, and
a few other things. It worked really well for trivial scenarios such as a GridView with a textbox and a validator on the page. Unfortunately for us it turned out that most pages are significantly more complex.
A classic example that didn’t work was a page that had an UpdatePanel with a wizard. Each step of the wizard contained a validator and a textbox. As you go through the wizard
Microsoft ASP.NET AJAX Extensions 1.0 beta:
To overcome the problem of blindly reexecuting scripts that we parsed from the page we came up with an explicit registration model for scripts. This way the UpdatePanel can
known exactly which scripts to execute, and when. The ScriptManager now has a set of static script registration methods. They are static so that they work on pages that don’t use partial rendering, including those that don’t even have a ScriptManager. You
do, however, have to link to the Microsoft.Web.Extensions.dll to be able to call these.
If you used to call:
Page.ClientScript.RegisterClientScriptBlock(typeof(Foo), "key", "alert('hello'); ", true);
You would now call:
ScriptManager.RegisterClientScriptBlock(this, typeof(Foo), "key", "alert('hello');", true);
If you look closely, there’s a new parameter for the method of type Control. This parameter is the precise reason why we needed the new set of registration methods. We use
that parameter to detect whether the control registering the script is inside an UpdatePanel, and if so, whether that UpdatePanel is being refreshed during a given async post.
We also require that controls implement dispose logic so that when an UpdatePanel is cleared out during an update the scripts inside it can tear down anything they need. This
is done through a number of techniques, which I won’t go in too much depth here. The technique the validators use is to have a “dispose” expando on their rendered elements and the UpdatePanel client code will execute all the “dispose” expandos inside a panel
that is getting cleared.
Implications of having new registration APIs:
One of the biggest implications of this is that existing controls that register scripts don’t work inside UpdatePanels. We are aware that this is a problem but we saw that
it was necessary in order to make UpdatePanels work at all.
Controls that shipped in ASP.NET 2.0:
We have updated versions of the ASP.NET 2.0 validators that are tag-mapped to the old versions (this means that if you have an <asp:RequiredFieldValidator> tag it will use
the updated one and not the old one. These updated validators use the new registration APIs.
Other controls, such as WebParts, TreeView, and Menu were not updated to use the new registration APIs primarily due to time constraints. We felt that it was far less common
to have these controls inside UpdatePanels compared to the validators. The TreeView control has built-in AJAX functionality anyway. In a future version of Atlas or ASP.NET we will have updated versions of these controls, however.
3rd party controls:
We have been working closely with custom control vendors to have them learn about the new APIs and many of them will be releasing updated versions of their controls that are
compatible with UpdatePanel.
We’ve still got a few things to work out for custom control vendors. And there are also some issues remaining for page developers. We
love hearing this feedback from you since it makes a huge difference in how we build this awesome framework.
I hope this helps explain some of our decisions in one place instead of scattering it in varied responses to several posts.