First of all, if you haven't already done so, download the ASP.NET AJAX 4.0 Preview 3 now and try it out! And after you're done with that, come back here, or there, or there, or there, and let us know what you think and what you like or don't like about it. We love feedback, and it really does have an impact on the product. We wouldn't go through all the trouble of releasing preview bits or presenting these things if it didn't.

So, I thought I would detail one of the interesting yet behind-the-scenes features in the 4.0 preview, because on its own it is pretty useful. I say behind-the-scenes, because it is used by and invented for many of the features in the preview, such as Bindings and the DataView control, but it is also a public API that you can use for your own purposes.

A bit about JavaScript Objects

Objects in JavaScript are associative arrays. If you are familiar with the .NET Hashtable or any equivalent data structure in any other language, it's like that. It's a collection of keys and values -- where keys are strings and values are anything (not accurate to say they are 'Objects' since not everything in JavaScript is an Object, like strings).

var obj = new Object();
obj.foo = "string";
obj.bar = new Date();
obj["abc def"] = [1, 2, 3];

Which of course can be expressed a little more compactly:

var obj = { foo: "string", bar: new Date(), "abc def": [1, 2, 3] };

JSON Web Services

When you call a service that returns JSON, you end up with one of these "plain 'ole JavaScript objects". Plain, because there's nothing 'activate' about it. There's no code that runs within the object when you get and set values, etc. In this world of AJAX frameworks and features, it is just a plain object.

But what if you are plugging that data into a component, which then consumes those values. If you ever change any of the values, the component won't know about it unless you tell it. Wouldn't it be nice if the component could be notified of any changes to the object automatically? That way, for example, if you were rendering out a list of Widgets based on an array of POJO objects containing widget data, you could, say, edit the name of one of the widgets and the rendered list could automatically reflect the updated value, without you having to force it or re-render everything. Doing it manually you may think wouldn't be so bad -- but it means coupling logic with UI, or at least deriving some custom mechanism for decoupling them. But there is no mechanism by which you can be notified of changes to a POJO.

var widget = { name: "widget1" };
renderWidget(widget);
widget.name = "newname";
renderWidget(widget);

A possible solution would be to create an actual class to represent a Widget, and bind to that instead. Then instead of saying widget.name =" newname", you can call a method, like widget.set_name("newname"). The code could then execute a callback to notify anyone interested that there is a new name. The problem here is that the web service you called just returned a POJO. So now you have to convert the POJO to this business class object, or wrap it in one. If there is a lot of data, that could be quite expensive and slow, and it just complicates things.

var widget = { name: "widget1" }; // came from a JSON service
var businessObject = new Widget(widget); // warps or converts it
renderWidget(businessObject);
businessObject.set_name("newname");

Introducing Sys.Observer

The Microsoft AJAX 4.0 preview includes this Sys.Observer class that allows you to be notified of updates to POJO's, provided you use its APIs to modify them. It is named observer of course after the Observer design pattern. Used internally by the live bindings feature and the DataView control, it was necessary to support these features without requiring wrapped business objects, but it is so useful on its own we decided to make it public and independent, so you can use it in your own scenarios too. The above example can be expressed like this.

var widget = { name: "widget1" }; // came from a JSON service
renderWidget(widget);
Sys.Observer.setValue(widget, "name", "newname");

Notice the call to Sys.Observer.setValue(). This sets the "name" field on the POJO, but in a manner that knows how to notify any "observers". Ok -- so, how do you become an observer of the object? The pattern is very similar to the INotifyPropertyChanged interface that Microsoft AJAX Components can implement, but without the interface and bloat of implementing a component. The hypothetical "renderWidget" function here could look something like this:

function renderWidget(widget) {
    Sys.Observer.addPropertyChanged(widget, showWidget);
    showWidget(widget);
}
function showWidget(widget, args) {
    $get('div1').innerHTML = widget.name;
}

The Sys.Observer.addPropertyChanged() method "adds" a "propertyChanged" event handler. You can also stop observing the object by removing the handler with Sys.Observer.removePropertyChanged(). When the component changes because someone calls setValue(), the observers are notified by raising the property changed event for that object. The arguments to the callback are just like a typical AJAX event exposed by an AJAX component -- the first is the "sender", the object that raised the event, and in this case that is the widget, and "args" that is information about the event. The "args" is a familiar type that is already in the AJAX framework -- Sys.PropertyChangedEventArgs. From those args you can get the name of the property which as changed (in this case, "name").

An alternate syntax - giving your POJOs just a little MOJO

The "add" and "remove" prefixes are analogous to the "add_" and "remove_" prefixes that AJAX Components use when exposing events. There is no "_" here though, because these methods don't have the typical signature of an AJAX event adder or remover -- they take the object as a parameter, rather than you calling the adder or remover directly on the object. It may or may not seem to you that the syntax for changing a value on the POJO is a bit verbose. The APIs on Sys.Observer are all static, meaning you have to pass in the object (e.g. 'widget') as the first parameter to all of them. The reason for that obviously is that the object does not have any functions on it which you can execute, it is a POJO after all. However, you can optionally "convert" the object to an observable one, which adds the necessary methods to it for you.

var widget = Sys.Observer.observe({ name: "widget1" }); // make pojo observable
renderWidget(widget);
widget.setValue("name", "newname");

What is the difference you ask? Functionally speaking, there is no difference at all. The two methods are equivalent. In fact, internally the one just calls the other. Practically speaking, converting the object to be an observable object may be convenient in certain cases, but also has the side effect of adding "gunk" onto the plain object. It is no longer a "plain" JavaScript object, since it now has some actual meat on it.  But, just a little bit. Not enough that it loses its "simplicity" that the "P" in POJO gives you. Just a little meat on its legs. I guess that makes it a MOJO, "meaty 'ole JavaScript object" :) But hey, the choice is yours! By the way, none of the internal usage of Sys.Observer calls observe(), so the framework itself will never "gunkify" your POJOs automatically. We made sure of that, we know you are very fond of your POJOs and you don't want some presumptuous framework messing with them and turning them into MOJOs. Ok then.

What about Sys.Observer.getValue()? It doesn't exist. It really doesn't need to -- you can get the value directly off the POJO. No need for the indirection.

What about JavaScript Arrays?

This is great and all, but JSON web services don't return a single widget. They return a lot of widgets, usually. So you are dealing with, uhh, a POJA... a "plain ole javascript array". That's right -- a POJA. You heard it here first. Kind of abusing the POJO term here, but for a good reason -- we COULD have a fat collection type class in the AJAX Framework, but we don't. Arrays have the same problem POJOs have, in that any time they are added to or removed from, there is no logic behind that operation, so there's no way for interested observers to realize when the array has been modified automatically (at least, not without a polling operation).

Observing POJAs

Some of the logical operations you can perform which modify the array using the various JavaScript APIs that exist are add, addRange, insert, remove, removeAt, and clear. The Microsoft AJAX library provides methods named like these as static methods on the Array type. So you have the corresponding APIs on Sys.Observer.

var a = [1, 2, 3]; // POJA
Sys.Observer.add(a, 4);
Sys.Observer.addRange(a, [5, 6]);
Sys.Observer.insert(a, 0, 0);
Sys.Observer.remove(a, 6);
Sys.Observer.removeAt(a, 0); // now [1,2,3,4,5]
Sys.Observer.clear(a);

It's kind of interesting what this support means. I have seen some complaints in the past that the Microsoft AJAX library does not have any "collection" classes. The reason those complaining wanted a collection class was because, well, they wanted to be able to 'observe' the array, even if they didn't realize it. Sys.Observer provides this capability, without the unnecessary bloat of an actual "collection" class that would then only be useful if every component you wanted to use with it knew about it. Since this array is still just an array, it is compatible existing code.

Observing the changes on an array is a little more interesting than on objects. When you add or remove items, you might want to know what index they are on or were on. And in the case of removal, you may want to know what the item was. All of this is available through the new Sys.NotifyCollectionChangeEventArgs class that is passed into the "collection change" event.

function onChanged(a, args) {
    // args is Sys.NotifyCollectionChangedEventArgs();
    var i, j, changes = args.get_changes();
    for (i = 0; i < changes.length; i++) {
        var change = changes[i];
        switch (change.action) {
            case Sys.NotifyCollectionChangedAction.add:
                for (j = 0; j < change.newItems.length; j++) {
                    alert("Added '" + change.newItems[j].name + "' at index " + change.newStartingIndex + j);
                }
                break;
            case Sys.NotifyCollectionChangedAction.remove:
                for (j = 0; j < change.oldItems.length; j++) {
                    alert("Removed '" + change.oldItems[j].name + "' at index " + change.oldStartingIndex + j);
                }
                break;
            case Sys.NotifyCollectionChangedAction.reset:
                alert("Array was cleared.");
                break;
        }
    }
}
 
var widgets = [
    { name: "widget1" },
    { name: "widget2" },
    { name: "widget3"}];
 
Sys.Observer.addCollectionChanged(widgets, onChanged);
 
Sys.Observer.add(widgets, { name: "widget4" });
Sys.Observer.addRange(widgets, [{ name: "widget5" }, { name: "widget6"}]);
Sys.Observer.insert(widgets, 0, { name: "widget0" });
Sys.Observer.remove(widgets, widgets[1]);
Sys.Observer.removeAt(widgets, 0);
Sys.Observer.clear(widgets);

So there you go -- all the information you could possibly need to know about what is happening to the array. Of course, just like turning POJOs into MOJOs, you can optionally turn POJAs into... uhh, MOJAs? I should point out that in addition to the change operations becoming available right on the object/array, so too do the add and remove event handler methods:

var widgets = Sys.Observer.observe(
    [   { name: "widget1" },
        { name: "widget2" },
        { name: "widget3" }
    ]);
 
widgets.add_collectionChanged(onChanged);
 
widgets.add({ name: "widget4" });
widgets.addRange([{ name: "widget5" }, { name: "widget6"}]);
widgets.insert(0, { name: "widget0" });
widgets.remove(widgets[1]);
widgets.removeAt(0);
widgets.clear();

Only, notice the difference in the name. It is "add_collectionChanged", which follows the traditional Microsoft AJAX library event pattern with an "adder" and a "remover". This time, with the "_" since it now follows the correct signature and can be thought of as an actual event on the object rather than a helper method for adding an event to a different object, like the static Sys.Observer.addCollectionChanged() method does.

But wait, there's more!

You may have noticed in the onChanged handler that each change operation can have a list of operations. And, each operation can have a list of "new" or "old" items. The reason for the "new" or "old" items is because of the batch operations you can do in one shot, like addRange(). When you use addRange, there is a single change operation with the new items in the newItems field, for example. But still, that is a single change operation, so why the list of change operations?

Say you have a few different operations you need to perform. You need to remove one item and then add two items. Obviously you must remove the item and then add the new item -- there's no operation that will do both of these steps at once. Any observers of the array are going to be notified of each operation separately, one after the other. If those observers are doing something expensive with that knowledge, you could have a flickering problem. Perhaps the observer renders out the list of items, refreshing the view each time the array is modified. There would be no point in refreshing when you remove an item, only to have to refresh again when you add one right afterwards.

Declaring the beginning and end of an operation

Well, this is a pattern that is actually already employed by the Microsoft AJAX library. When you need to tell a component to hold off on actually doing anything with the changes being made to it, you first call beginUpdate() on it. When you are done, you call endUpdate(), at which point all the changes you made in the meantime are processed at once. The base Sys.UI.Component class provides these beginUpdate and endUpdate methods, but of course, it is up to the implementation of the component to actually honor this behavior. Sys.Observer is not a component, but provides the methods as well, and honors your wishes. Observers are not notified until you call endUpdate().

Sys.Observer.beginUpdate(widgets); // hold your horses man
Sys.Observer.add(widgets, { name: "widget4" });
Sys.Observer.addRange(widgets, [{ name: "widget5" }, { name: "widget6"}]);
Sys.Observer.insert(widgets, 0, { name: "widget0" });
Sys.Observer.remove(widgets, widgets[1]);
Sys.Observer.removeAt(widgets, 0);
Sys.Observer.clear(widgets);
Sys.Observer.endUpdate(widgets); // ok I'm done!
// all operations passed to onChange at once here

The same thing applies to POJOs -- the propertyChanged event is held off until you call endUpdate().

What about Foo.Bar?

Even POJOs can be more complex than what I've been talking about so far. You might have nested POJOs, where the field of a POJO contains another POJO -- a "sub property", if you will. For example, here is a contact POJO.

var contact = { name: "Dave Reed",
    address: { street: "1 Microsoft Way",
        city: "Redmond",
        state: "WA",
        building: 41
    }
};
contact.address.building = 42;

Building 41 is wrong -- gotta change that to 42! But no one will know I've done that. Even if someone is observing the contact object, how will they know the address field has been updated? No problem -- just set the value using the supported "dotted" syntax.

var contact = { name: "Dave Reed",
address:street: "1 Microsoft Way",
            city: "Redmond",
            state: "WA",
            building: 41 }
};
Sys.Observer.addPropertyChanged(contact, contactChanged);
function contactChanged(contact, args) {
    if (args.get_propertyName() === "address") {
        alert(contact.address.building);
    }
}
Sys.Observer.setValue(contact, "address.building", 42);

Even though the address field of the contact has not itself changed, a value on it has. That qualifies as a property change for the address field, so it shows up as a change to the address, not to the 'building' field. That's important, because if I want to observe changes to the contact object as a whole, I wouldn't always know that a field on contact may have sub-fields. It wouldn't be nice to have to observe changes to address directly, too. If I want specific information on what fields of the address changed, well then I can observe that directly instead.

Not just for Objects and Arrays

You can use these APIs on more than just objects or arrays. You can use it on DOM Elements, or on AJAX controls, components, and behaviors. Any AJAX class, or even components from other libraries. You can even use it on the global "window" object, which means you could use it to monitor changes to global variables. You could combine the observation of arrays and objects, for example, to be notified of any changes to an array OR any of the objects it contains. The caveat of course is that you must use Sys.Observer's APIs to change the value rather than doing it directly.

Remember our discussion of JSON web services returning plain data, and you having to wrap that data or convert it to get this functionality? Well here you go -- and one of the great things about the approach this technique uses is that you don't have to pay the cost for wrapping or converting objects that you don't actually need to 'observe'. If you don't observe an object, and you don't change its value, there is 0 cost. If all you do is change its value with setValue(), but no one is listening, the overhead of checking for any registered observers is very tiny.

All of this has been a pretty hypothetical discussion, with no real concrete examples of how you might use this feature. Well, I'll put together some examples if the interest is there. But a good place to start is to take a look at the Microsoft AJAX 4.0 Preview 3 Live Bindings feature, and realize that it is the flux capacitor, err, I mean, this functionality that makes that feature possible. A great place to get an idea of what live bindings has to offer is this excellent example.

Happy Coding!

Plenty of people have already seen this... interesting... error screen in chrome.

image

I wanted to see what a run-away script would do to Chrome. There's always a warning that the script is taking too long, giving you a chance to shut it down. Here's what Chrome does...

image

What is that icon? Is the page COLD or something? It's snowing! It's wearing a scarf! I guess the connection is that the page is "frozen."

EDIT: If I decide to "kill" it, they should have an animation of a spear going through it or something. Is it even acceptable to say you can "kill" the page? :)

Aw, snap!

Lately I've been using a laptop more often than a desktop to work in Visual Studio, and of course like most laptop keyboards, the keys are jammed close together. The most annoying thing I keep doing by mistake is hitting F1 instead of Escape, which of course begins the not-so-quick process of bringing up help. Every time I do it, I sigh, wait, and close it.

No longer... realizing I can just disable F1 has made my day.

F1HelpBefore

F1HelpAfter

Now I can hit escape without fear.

Sky Lynn Reed's 0th birthday is 5/15/2008 at 5:44pm, when she weighed 8 pounds, 0 ounces. A nice round binary number. Our first born! There are simply no words to describe the experience. We debated on whether we should have kids for a long time. After being married almost 5 years now, we finally decided to take the plunge. Now that she's here, and about 5 weeks old, we couldn't imagine our lives without her.

SkyLynnReed

Of course, being a programmer daddy should be fun. We'll just see how early it is possible to learn to type. Imagine having an email address that you've had since before you were born? Oh, and a birthday cake with a number 0 candle on it makes sense to me. You're how old? Yeah, but you've only had that many traditional "birthdays". You've been robbed of the most important birthday there is -- your BIRTH day. As soon as she fits into it, I'll post a picture of her wearing her "Microsoft Future Developer" outfit. Dad is a geek, Sky, you better get used to it.

I look forward to just about everything that is to come. Of course it will be difficult. There will be major hurdles to jump over. Good times and bad times. But what a gift -- I get to live life all over again. I get to experience childhood as an adult.

UPDATE 

This issue is officially fixed in .NET 3.5 SP1. If you have applied the workaround in this blog post, you no longer need it. But the story of this bug is still rather interesting. 

UPDATE

If you upgrade from Microsoft ASP.NET AJAX Extensions 1.0 to 3.5, and you have a TabContainer inside an update panel, like this:

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
 
        <act:TabContainer runat="server">
            <act:TabPanel runat="server">
                <HeaderTemplate>
                    Tab
                </HeaderTemplate>
                <ContentTemplate>
                    Tab Content
                </ContentTemplate>
            </act:TabPanel>
        </act:TabContainer>
 
    </ContentTemplate>
</asp:UpdatePanel>    

...you may notice a change in behavior. When the update panel updates, the UI seems to flicker off and on again, whereas with AJAX 1.0 it seemed to update instantly without any flicker. You may have noticed a similar problem with other components as well, depending on what they are doing.

This is one of those interesting bugs with a convoluted history, driven by browser quirky behavior.

The Tale -- First, some background

Update panels basically work by replacing their content with the new content from the server by setting its innerHTML. However, there may also be components defined within that HTML that register script. Those components need to be recreated now that there is a new set of HTML. UpdatePanel runs those scripts by dynamically creating a new <script> element, setting its content, and then appending the script element to the DOM. It goes something like this:

var script = document.createElement("script");
script.type = "text/javascript";
script.text = "[script that creates a new component]"
document.getElementsByName("head")[0].appendChild(script);

After it has done this for all of the components in the new content, it raises the load event on Sys.Application, among some other page request manager events.

The Browser Quirk

When you append a script element dynamically like this, would you expect the script it contains to execute immediately, or later? Keep in mind we're talking about literal script here, not a reference to another script by url. Remember once all the scripts are appended, page request manager proceeds with raising events. So whether the script executes immediately or later affects whether that component will be created and initialized before, or after those events. That's an important difference.

The intention is for the script to execute immediately. And that was a valid assumption that IE, FireFox, Opera, and Safari all agreed with at the time. That is, until FireFox 2.0.0.2 was released. With that release, FireFox started delaying the execution of the script until later. This caused components to be created after the load events, which broke some AJAX controls that depended on the ordering.

What we did about it

At the time we were in development of Microsoft AJAX Extensions 3.5. We certainly felt that this was a breaking change in FireFox that should be fixed. But we couldn't count on that. We had to fix this problem in AJAX so it wouldn't be a problem whether or not FireFox, or any browser, exhibited this quirk. The fix was to ensure the script executed first, by deferring future operations with a window.setTimeout. It goes something like this:

var script = document.createElement("script");
script.type = "text/javascript";
script.text = "..."
document.getElementsByName("head")[0].appendChild(script);
window.setTimeout(doContinue, 0);
function doContinue() {
    alert('definitely after script executes');
}

window.setTimeout is one of those poorly understood JavaScript features. JavaScript is single threaded. All setTimeout does is queue the referenced function for execution at a later time, when the timeout period has expired and there is no other javascript operation occurring (since only one train can be active at a time). Queuing the script element either executed the script, or it queued it for executing. The window.setTimeout just ensures that 'doContinue' is queued up afterwards. I often see people using this trick, but using a timeout value of "1" or something else very small. There's no reason for that, 0 does the trick, which is easily understood if you understand what it's really doing.

Problem Solved

This indeed solved the problem -- scripts would now execute in the order we intended, regardless of whether the browser executes dynamic inline script elements immediately. And so this fix was released with AJAX Extensions 3.5.

Thankfully, FireFox was also quick to respond. Likely this behavioral change broke other frameworks as well (I can only guess), so there was probably enough of a splash with it to get them to fix it in quick order -- because soon after 2.0.0.2 was released, 2.0.0.3 came out and this behavior reverted back to it's pre-2.0.0.2 behavior. But still, it was good that we had the workaround in place in case this issue ever came up again.

Problem Caused

We didn't see any adverse side effects with the setTimeout work-around, other than a small performance hit on initializing components after an asynchronous update from an update panel. Unfortunately, this turned out to affect some components much more than others. The point at which the setTimeout occurs is after the innerHTML has been replaced, but before component initialization occurs. Any component that performs any serious DOM manipulation from its initialize() method would now be doing so later than it used to. The setTimeout not only delays execution, it also gives the browser more opportunity to draw stuff on the screen. So a component that say, creates a bunch of new elements from initialize, would be causing a FOUC ("flash of uninitialized content"), since the user would first see the natural HTML of the component and then a split second later, the manipulated DOM. This is the cause of the 'flicker' you see with the TabContainer!

The Real Solution

First of all, if at all possible, AJAX components should rely as little as possible on DOM manipulation to create their initial UI. Especially if they are server components as well -- they should render out the initial UI and only manipulate it as needed. This is better practice for FOUC purposes, performance, and probably SEO or script disabled browsers too. I don't know for a fact that the TabContainer is doing this, or if it is really necessary for it to do it, I can only infer that it is based on this behavior.

The Actual Solution

Barring that, the framework should do whatever it can to improve the experience of any controls that need to rely on DOM manipulation from initialize.

Since FireFox fixed the quirk, and no other browsers have experienced it, we have decided the workaround is no longer necessary. All it is doing is hurting performance. If any browser makes this kind of change again, or if a new browser is released that exhibits this quirk, it may not be compatible with some components or applications that rely on the ordering of events (but at least it won't flicker). But the number of components and applications that would have a problem should be very small, and such a quirk we hope would be deemed incorrect behavior and fixed in that browser. It may not be specifically called out in any W3C recommendations (provide me a link if you find one), but it should be, and the fact that the 4 major browsers of today are consistent with this really says something about what the correct behavior is. So all in all, the workaround just it isn't worth the cost anymore.

So the workaround is removed in the upcoming 3.5 Extensions release. But if you want to apply the fix to your 3.5 scripts today without waiting, here is how to do it. The goal is to replace the internal method used by PageRequestManager to load scripts, in the ScriptLoader component. The easiest/simplest way to do it would be to put this script in your own JS file, and then reference it on every AJAX page with the ScriptManager. There other ways of patching it, such as by extracting the AJAX scripts and using the ScriptManager.ScriptPath or ScriptReference.Path feature to point to your modified copy of MicrosoftAjax.js and MicrosoftAjax.debug.js (copies of which are in your program files directory).

Sys._ScriptLoader.getInstance()._loadScriptsInternal = function() {
    if (this._scriptsToLoad && this._scriptsToLoad.length > 0) {
        var nextScript = Array.dequeue(this._scriptsToLoad);
        var scriptElement = this._createScriptElement(nextScript);
 
        if (scriptElement.text && Sys.Browser.agent === Sys.Browser.Safari) {
            scriptElement.innerHTML = scriptElement.text;
            delete scriptElement.text;
        }            
 
        if (typeof(nextScript.src) === "string") {
            this._currentTask = new Sys._ScriptLoaderTask(scriptElement, this._scriptLoadedDelegate);
            this._currentTask.execute();
        }
        else {
            document.getElementsByTagName('head')[0].appendChild(scriptElement);
            Sys._ScriptLoader._clearScript(scriptElement);
            this._loadScriptsInternal();
        }
    }
    else {
        var callback = this._allScriptsLoadedCallback;
        this._stopLoading();
        if(callback) {
            callback(this);
        }
    }

Include this script on your page with a TabContainer, and volia, the flickering will be gone.

This has been a bug tale! Happy coding, I wish you all a non-flickering UI.

UPDATE 05/02/08: Removed the bit about 3.5 extensions preview. The fix isn't in the extensions preview as I originally thought.

Many of the comments I've received in the various dynamic controls entries I've written have been questions for help with a specific scenario. A lot of those scenarios are similar. One in particular I keep hearing is something as follows:

The user is presented with a drop down list of potential items to add to a list of items. As they select an item, it is added to the list. A different type of control is designated to represent each type of item the user can select. Each control provides a unique user interface that is unique to the type it represents.

Dynamic Controls Scenario

The uniqueness of the scenario is that there is a different control designated to 'represent' each data item, depending on the type of that data. The data itself might also be editable within each control.

It is of course necessary to 'dynamically' load the control responsible for each item, since you can't know what they are ahead of time. You also don't know how many there are, and they can be added and removed by the user in the meantime.

Rather than discuss designs for such a page at length (boring!!!), I decided to implement the scenario in a sample application. Also great for really understanding things, I implemented it in 3 different ways, each one progressively better than the last. Hopefully that helps with not only understanding dynamic control scenarios, but understanding alternatives to them or ways of minimizing their use when possible. If a picture is worth a 1000 words, a sample application is worth a 1000 blog entries, I say! Please have a look!

Dynamic Controls By Example Sample Application

Download the sample application here:

TRULY Understanding Dynamic Controls By Example

I get this question a lot for some reason. The more general question is whether it is better to override a virtual method on the page or control in question (OnLoad, OnInit, OnPreRender, etc), or to hook into the corresponding event. For page development you have yet another choice; that magical Page_Load method.

I'm not the first blog out there to talk about this, but I haven't really read them, just skimmed a few. Didn't want to taint my opinion too much... here's my take on it all.

Let's throw it all together... just so we know what we're talking about here.

public partial class _Default : System.Web.UI.Page 
{
    public _Default() {
        Init += new EventHandler(_Default_Init);
        Load += new EventHandler(_Default_Load);
    }
 
    void _Default_Load(object sender, EventArgs e) {
        // load event
    }
 
    void _Default_Init(object sender, EventArgs e) {
        // init event
    }
 
    protected override void OnLoad(EventArgs e) {
        // do something here
        base.OnLoad(e);
        // or should I do something here?
    }
 
    protected void Page_Load(object sender, EventArgs e) {
        // what on earth calls this anyway?
    }
 
    protected override void OnPreRender(EventArgs e) {
        // pre pre render?
        base.OnPreRender(e);
        // post pre render?
    }
}

I think I get this question so much just because my posted samples usually override OnLoad, OnInit, etc, even though the default page-generated code uses Page_Load. So it strikes people as odd, and then they start looking into it too deeply and thinking I have some super secret reason for doing it...

Not really. I just prefer it. But we may as well really look into it.

Performance?
Strictly speaking, calling a virtual method that is overridden should certainly be faster than invoking a delegate (which is what an event is). I don't have proof of this. I haven't done any performance testing. But it makes sense. Page_Load has its own story about this. It's hooked up through the AutoEventWireup feature, which can only be even slower than a traditional event handler. But it should be the last thing on your mind. The difference in performance is probably analogous to a jockey getting a hair cut before a big race, to gain a weight advantage! Yeah... it will help. Some law of thermodynamics probably proves that. But you'd probably get a thousand fold better results out of putting in one more practice instead! Better to worry about the bottlenecks in your app, not low level details like this. Still -- overriding OnX wins here.

Object Oriented?
A component listening to its own event just doesn't seem right to me. Why? Overriding the method is simpler, and less code. (I tried to think of a funny analogy for this one -- talking to yourself, reminding yourself of your own birthday, etc). As for Page_Load, if you were designing a base class for some purpose, would you consider documenting for derived classes that "hey, if you make a method named XYZ_Foo", it will be called when the Foo event occurs!" No, probably not... it's unnecessary complexity, isn't it? Just create a method for them to override! Why reinvent the wheel? You wouldn't automatically go to an event I don't think either, for the same reason.

Consistency/Deterministic Behavior?
What happens when multiple components all subscribe to the same event from the same component, and the event fires? Well you might ask yourself what order they hooked into the event in, and you'd expect them to fire in that order. Nope... .NET makes no promises, there's no first-come-first-serve service here. MulticastDelegates may very well always fire the listeners in the order they were added, but you still wouldn't easily know what order they were subscribed in. Also, components don't have to use one for their events. When you publish an event, you can provide your own custom add/remove implementations, which may not honor order at all. Maybe different components are loaded in a different order depending on who-knows-what? Maybe that isn't the case now, but it will be in 2 years when some poor intern has to fix your code? Never rely on the order of event handlers. That might sound easy enough, but it isn't hard in a complex system to accidentally create a dependency on the order of things. Such a dependency should be obvious through the design of the system.

Using the override approach gives you better control over that, if you know what you are doing. It turns out, the base implementation of OnLoad is what raises the Load event. OnInit raises the Init event, etc. Consider this:

protected override void OnLoad(EventArgs e) {
    // do something here before the load event is raised
    base.OnLoad(e); // the Load event is raised
    // definitely comes after all listeners have been notified.
}

Now you have control over the order of things, at least with respect to the logic you are adding -- whether it comes before or after the event listeners. Furthermore, if anyone derives from this class, they can also control whether their logic comes before or after yours (or both) by deciding when to call base. And the behavior is consistent every time.

Mistakes?
Ok -- so should I put my logic before or after calling base??? And what if I don't call base??? What will blow up? Will the control fail to load?

This is an argument for not using the override method. If you forget to call base, the corresponding event will not be raised. Depending on lots of things, that may or may not cause a problem. It could cause a very subtle problem that you won't catch until much later. But thankfully tools like Visual Studio exist, and they insert the call to base for us automatically. In this OO age, it should be rare for someone to forget this.

Whether you put your logic before or after calling base really depends on the scenario. Personally I always call base last, at the bottom of the method, just because in general I think it makes sense for my component/control to do its own 'X' before raising the 'X' event for external listeners to respond to. If I want to know about anything those external listeners have done to me, then I could have more code after calling base. But let me just say I can't really even think of a time where this should matter. If you end up with code that needs to worry about this, then just pause and consider your design, it's a CodeSmell. You should be able to design it in a manner that doesn't depend on such subtlety.

Purity?
Trying to think like a purest -- I can't decide from that point of view what is right. If the purpose of OnX is to raise the X event, then you shouldn't override it if you're only purpose is to do something when the X event is raised. You should override it if you need to modify to ammend the strict and narrow task of raising the event, right? But listening to the event just smells worse to me. Perhaps OnX should be called RaiseX, and there should be protected OnX methods whose base implementations do nothing at all. That seems more pure... but that's not the way it is :) Purity and reality must collide in the real world to create... pureality.

And to me, that's within the OnLoad method, not the Load event.

So -- should you go around and convert all your apps one way or another? No way. Just stick with what you're used to. You're probably more likely to make mistakes and introduce bugs if you try to change your ways. Not that you would just because you read this :)

UPDATE 3/25 - clarified delegate ordering section.

A long time ago I published one of my first blog entries, TRULY Understanding ViewState. And what an experience it has been. It was pretty popular with commenters, so much so I decided to spin off a whole series of articles, TRULY Understanding Dynamic Controls based on some of the issues people were asking me about.

In the meantime, TRULY Understanding ViewState has accumulated over 250 comments! Most are questions from developers facing problems they cannot solve or architects seeking advice on how to approach a project. I've tried hard to answer each and every commenter with a meaningful answer. I have missed some, but I haven't forgotten about them -- they are still in my outlook inbox with that little red flag on them.

I do enjoy helping people, and I don't expect anything in return -- but here's a reader who really gave back. Trevor Morrison painstakingly combed through each and every comment in TRULY Understanding ViewState, categorized and indexed them, and compiled them into a 69 page word and pdf document! I cannot even imagine how much work that was, thank you Trevor!! He even took the time to highlight key statements throughout. I remember college, and how great used books were, because usually some overachiever had already highlighted all the important parts for me.

Trevor has also been gracious enough to let me publish the index here, for all of you to benefit.

Behold, just one page of the table of contents.

TRULY Understanding ViewState Comments Index - Table of Contents

 

And a random page within... notice the category.

 

TRULY Understanding ViewState Comments Index - Example Page

 

Download the TRULY Understanding ViewState Comment Index [word]. Also in PDF.

If for any reason the above links do not work for you, try the mirror site below, courtesy of Colin Bowern:
http://rockstarguys.com/blogs/colin/archive/2008/02/22/truly-understanding-viewstate-mirrored.aspx

Still relatively unknown, ASP.NET Futures is a nice little add-on to ASP.NET and ASP.NET AJAX that contains some features we want public feedback on. It's a playground in which technology gets to frolic in front of the public's (your) eyes. So why not seize the opportunity to play with the bits and submit your thumbs up, thumbs down?

I thought I'd give an introduction to two of the controls in ASP.NET Futures that I'm most fond of (I've worked on them, so I'm a little bit partial). If you already know about them, excellent, please log in some feedback.

<asp:Xaml runat="server" />

The Xaml control is an integration story between Silverlight and ASP.NET. If you are writing ASP.NET pages that contain Silverlight content, especially if you are also using AJAX features, it's definitely worth a look. Because it's not only an integration of Silverlight and ASP.NET, but between Silverlight and ASP.NET AJAX. It defines a new client-side ajax type, Sys.Preview.UI.Xaml.Control. So, if you are familiar with ASP.NET and with ASP.NET AJAX, this control gives you a logical extension. Just point the control at a XAML resource, and it wraps an ajax type around Silverlight, giving you a familiar and object-oriented asp.net ajax programming model to work with the surface area between the HTML page and the Silverlight plugin instance.

Take a look at a Calculator implemented using the Xaml control.

<asp:Media runat="server" />

I said it is object oriented, and it is. The media control defines another client-side ajax type which derives from the first: Sys.Preview.UI.Xaml.Media.Player. When this type wraps a Silverlight plug-in, it does a lot of work to it, searching within the Xaml document for elements of certain predetermined names like "PlayButton", and makes them more than just a pretty Canvas by adding behavior to them implied by their name. It may seem trivial, but there are a lot of subtle things that must happen to make what is essentially static markup (the xaml) behave like a full-blown media player. Silverlight makes it look pretty. The Media control brings it to life.

Not just a black box

When you watch video on a web page, you probably don't expect much in the way of interaction between the video and the page. The video is like a rich island in the middle of boring HTML, and never the twain shall meet. Even the orientation of the video is pretty much fixed -- ever seen a movie playing on a webpage at at 15 degree angle? I haven't. I'm not sure I want to, but I sure haven't!

But it doesn't have to be that way... The media control exposes some pretty cool client-side APIs in the form of properties and events that allow for some really interesting interaction between the media and the rest of the page. asp:Media... Tearing down walls!

Take a look at some of the cool things you can do with it.

Not just for fun, either

The Media control can work with any Xaml. It's very forgiving with which Xaml elements it requires, too. What? Your Xaml doesn't have a MuteButton? Ok, no problem. But it does have a WizzyWigDoSomethingButton -- well, it doesn't know what that is, but a client-side type you create that derives from the media player's client side type knows what to do with it.

The only element required is the MediaElement. Yeah you kind of need that one...

You get the picture. But what most people don't know, even those who use it, is that the client-side code that drives the Media control has already appeared in many places. So many, in fact, that if you've seen video playing in Silverlight, you've probably executed the code. The code was joint developed and is shared by the Expression Encoder product, which allows you to export videos to html for execution in Silverlight. It too creates nice media player functionality in Silverlight... and it does it using the exact same code the Media control uses. Well, the namespace is different. But that's it.

Here are some examples of sites using the Media control's client-side ajax type. Note how vastly different they look and behave -- a testament to Silverlight and this control.

So there you have it. If you want to play video or audio on your site using Silverlight, and you don't want to implement an entire media player UI from scratch, have a look-see.

EDIT: Hey, my first post tagged "Silverlight". Expect more in the future.

I've struggled with pretty bad headaches probably ever since high school. They come and go with intensity and frequency. Sometimes I think I have them figured out. Eat right, and before I get starving, get enough sleep, and they usually leave me alone. But stressful times, like long business trips or big presentations, or other matters, can easily prompt one. I've grown so used to them that I always make sure I have a supply of Excedrin nearby. There's a bottle at home, up and down stairs, at work, even in the car for those unexpected times. I even have family members be sure to have a stock if I know I'll be visiting for an extended period of time.

For whatever reason, Excedrin seems to be the only thing that helps. Nothing else even touches my headaches. But sometimes, on rare occasions, even Excedrin fails. Today was one of those times.

Bad enough that I finally went to a doctor about it (I was lucky to get a walk-in appointment). After describing all my symptoms, sure enough, these Excedrin-immune headaches are the migraine variety.

If you've had a migraine, I need not explain how terrible they are. If you're one of the lucky ones who don't get them, well, for me they on par with a really bad hangover.

There are lots of options these days for dealing with them. The key is preventing them by understanding what triggers them for you. I've lived with them all my life so far because they crept up on me. I never thought they were migraines because descriptions I read of them seem much more severe than what I have. Indeed I do seem to be luckier than most migraine sufferers -- they are bad, but not so bad that I must lock myself in a dark room for two days. Just thought I'd share my experience -- I'm sure lots of you can relate!

Perhaps this is one sub-conscious reason why I prefer The Dark Side of Visual Studio. The bright light of the normal color scheme is just too overpowering.

 

More Posts « Previous page - Next page »