ASP.NET Whidbey
I'm not talkin' about tennis...
Today I received a *very* cool gift (signed by Soma) consisting of a transparent (and heavy...) cube with the Visual Studio 2005 logo and a few paragraphs floating inside of it (ok, its hard to explain). Very, very cool:

It is the "Visual Studio 2005 ACE award", which recognizes the contributions done to make VS a better product, like a lot of bug reporting, suggestions, etc.
I just downloaded the Community Server beta 2 with the intention of having a quick look at it. Unzipped the download and found no source code… L (there is a “no source code will be available for beta 2” legend in one of the readme files too).
So I fired up Reflector and started looking at the available classes to get an idea of how the integration of .Text, ASP.NET Forums, ect looked like. While doing this I stumped at an assembly whose naming was not following the standard “CommunityServer.blah.dll”, instead it was named “MemberRole.dll”…
“Oh, an implementation of membership & roles coming from the guys at Telligent and/or the community” was what I thought. But then, why in the world is it named with no “CommunityServer” or “Telligent” prefix?
I’m curious you know… so I had to feed this little “MemberRole.dll” through Reflector and… big surprise!
The namespaces used start with “Microsoft” and by quickly looking at the implemented classes one can easily tell that it looks like a backport of the Membership, Roles, Profile and Provider pattern found in the Whidbey bits.
I haven’t heard anything about this yet, maybe this is because I’m like 1.5 weeks behind weblogs…
Quick Catchup: you may have heard about the new upcoming Cross Page Posting feature in ASP.NET Whidbey, in a nutshell: you will be able to post from page A to page B and while executing in Page B do some cool things like accessing the control tree for page A.
I was having dinner the other night with my gf and we where talking about *I don’t remember exactly what* when one sleeping thread in my head popped up and suddenly told me: “What about if the posting page uses Response.Write, that will be cause a mess!”.
Not having paid much attention to this feature before (read: not having run Reflector through it) I was pretty sure that if both pages were sharing the same HttpContext (which sounded logical to me) and the posting page called Response.Write to write its UI for example, then, when posted to another page, the target page UI will get all messed up with the posting page UI. Best of all this didn’t look like a bug at all, this was only good news, another excellent reason for people to finally start cleaning up calls to Response.Write in their code.
So, I quickly wrote the 3 lines of code required to test this scenario and hit Ctrl-F5.
I first browsed to –lets call it– Page “A” which included some garbage written out by calls to Response.Write. Then I clicked a button on Page “A” to cross post to Page “B” and expected Page “B” output to include the previous garbage… so far… no luck… Page “B” output was not including this… disappointing… :-(
At this point I started thinking that someone (read: the ASP.NET team) may have considered this before (just a year or two maybe? :-)) and included some workaround to make the life of developers using Response.Write much easier.
It was time for “the tool” to enter scene. It didn’t took me more than a minute or two to find out what was really happening, and yes, someone had thought about this before…
What is happening here is that before executing the posted page (Page “A”) from the target page (Page “B”), ASP.NET is cleverly switching the writer used by the HttpResponse instance with a dummy one, using a new internal (yes internal, sorry) method whose signature is:
internal TextWriter SwitchWriter(TextWriter writer);
After the posted page (Page “A”) has finished executing (and their controls are ready to be accessed by the target Page “B”) ASP.NET will switch again HttpResponse’s writer to the *real* writer this time thus allowing Page “B” to properly output whatever it needs to.
This is just an example of Whidbey helping the reputation of some ASP.NET developers :-)
A few days ago I stumped at the following sample (Whidbey docs required):
ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/cpref/html/T_System_Web_Handlers_AssemblyResourceLoader.htm
In the code for that sample a custom control is built; you will find that a constructor taking two arguments is provided but not used; why is it provided at all is beyond me.
public TextWithImage(string text, string imageName) {
ViewState["Text"] = text;
ViewState["ImageName"] = imageName;
}
But what is really bad about the previous constructor? It’s the lack of sense of storing values into viewstate in a constructor when viewstate tracking has not been started yet; anything you put in there will not be persisted into viewstate.
As these samples are and will be followed by thousands and thousands of people I believed it was really necessary to not show such a thing. People actually learn from samples and this one will not help any in that matter.
So I filed this bug using LadyBug and telling:
Description: Opened by vga on 2004-10-31 at 00:27:49
In the sample used here:
ms-help://MS.VSCC.v80/MS.MSDNQTR.v80.en/MS.MSDN.v80/MS.VisualStudio.v80.en/cpref/html/T_System_Web_Handlers_AssemblyResourceLoader.htm#codeExampleToggle
A ctor taking two arguments is provided although not used by the sample. This ctor actually stores into viewstate the two arguments passed.
Storing values into viewstate in a ctor is nonsense as viewstate tracking hasn't started yet thus these values won't be persisted.
Please consider deleting the mentioned ctor from the sample as:
1) its not used at all
2) its showing a nonsense usage of viewstate
And less than two days later I got the following (the highlighting is mine):
Resolution: Fixed
Closed by Microsoft on 2004-11-02 at 11:15:43
Thanks for your comments,
you are right that manipulating view state in the constructor in that way is silly. I've changed the sample to have a default constructor; the control is still usable in this way and still demonstrates the important thing, which is how to use the AssemblyResourceLoader to get at some type of resource compiled with the assembly.
Regards, Alex
Don’t you just love that much sincerity? :-) I know I do!
BTW, Alex if you happen to read this, please while you’re at it modifying the sample make sure to also change the referenced filename map6.gif to something like… map.gif? Or if you really want to get funny with filenames then you could try map872-b-northEast.gif… :-)
No, I’m not talking about the 2004 Olympics here.
Like two years ago in a meeting for MVPs ScottGu was presenting an overview of ASP.NET Whidbey. I do remember he told us that ASP.NET support for mobile devices would be a gold key in Whidbey.
The alpha bits were a step further in that direction: the control architecture was revamped in order to allow “adaptation” natively. The days (and problems) of having two separate control architectures were counted.
So with adaptation being supported natively and with every control adaptable out-of-the-box against any of the supported markups they were going straight for the gold.
But then, one drop before beta1 eventually missed all the code for the adapters and the infamous System.Web.Mobile.dll had its comeback into scene. A few weeks after noticing it I innocently posted this. A week later I heard (just don’t ask where) that they were being cut off. A month later SusanC (blog?) confirmed it in the same thread. Then it got pretty much “official” with ShankuN announcement.
All this doesn’t lead to gold for sure. Why not silver then? Because I’m still not buying that the current adaptation architecture is here to last. Don’t take me wrong: it is way better than having no adaptation at all like the v1.x bits but it has it owns drawbacks too.
Bronze would be a better fit for now.
As you may already know ASP.NET 2.0 will include a new control, HtmlHead, to serve all your <head> handling needs thus making all previous v1.x hacks unnecessary by providing programmatic access to that tag. So far so good. Let’s hear the bad now.
First thumb down: I received a response in LadyBug stating that viewstate support will not be added to HtmlHead. This was after I chimed about it. Sadly, they didn’t include an explanation backing up their decision (not that they have to but it would have been nice). While I agree that the most common scenario may not require viewstate handling there may be cases where it could be useful, so why not adding support for it and just set EnableViewState to false if you don’t want it?; with this approach you’re giving developers a choice at least…
Second thumb down: HtmlHead handling of meta tags is incomplete, or better said, *very* incomplete. Its RenderControl method is hardcoded to output only name and content attributes. What about support for other valid attributes like http-equiv and scheme? It’s just not there. Please, please… make this control more ‘standard-aware’, look at section 7.4.4 of the HTML401 spec and add support for it. It should be a piece of cake. I’ve filled a new bug in LadyBug (#FDBK11439), let’s see how this one turns up.
Considering the bits are in beta 1 now and that there are –for sure- more important bugs/issues/whatever to be fixed, my guess is that this poor little control will not get much more attention and will hit gold in its current status…
In the following post I’m going to focus on the new viewstate serializer exclusively; keep in mind that there are other strategies being introduced in order to reduce viewstate size, like separation between viewstate as we know it today and a new control state.
Also, when using the term “serializer” I’m referring to the viewstate serializer unless otherwise noted.
New added support for common types
As I mentioned in a previous post, the serializer in ASP.NET v1.x was designed to handle only a few different types and it is not really a good idea to feed it with anything else.
In Whidbey, the serializer is being extended to support 10 additional types: IndexString, byte, char, DateTime, double, short, float, HybridDictionary, Enum and Color meaning that all these types now generate smaller footprints.
Aside from supporting new types, current serialization is being optimized. Let’s see some of the introduced changes.
Clever Gets Clever: type code = type + state
How is a Boolean handled? In v1.x they decided this was a very common type and added support for it into the viewstate serializer. This support means having a dedicated type code that represents a Boolean type thus avoiding the need to persist any additional extra information in order to properly identify it and de-serialize it later on.
This is how a serialized Boolean looks like in v1.x:
111 – code representing a Boolean type
60 – token representing the beginning of the stored state
116 or 102 – only one is used, depending on the instance value being true or false respectively.
62 – token representing the end of the stored state
Thanks to this type code optimization the footprint ends up being of 4 bytes which –believe it or not- is not that bad when compared for example to the footprint that would have been generated by the BinaryFormatter itself (~27 bytes).
First thing to notice in Whidbey is the reduction of token usage (char 60 and 62). In my opinion this “tokenized” approach of v1.x was largely useless so it’s a good thing to know it changed. Ok… so that’s two bytes shorter for a start.
Second thing we can see in Whidbey is that now the Boolean type code represents type plus state. Having two possible states bring us two different type codes: 104 for a Boolean with a value of false and 103 for a Boolean with a value of true. This means one less byte, which including the previous reduction, totals three less bytes, a 75% reduction, not bad. This is how a Boolean with a value of true looks like when serialized by Whidbey’s viewstate serializer:
103 – code representing a Boolean set to true
We miss you, Unit
There is a notoriously lack of support for the System.Web.UI.WebControls.Unit type in Whidbey.
In v1.x this type was assigned its own type code (49) which saved the serializer from having to store an –often large– string representing its assembly-qualified name.
In Whidbey, Unit is not backed up with a type code meaning that its full type name (yes, its full name and not its assembly-qualified one, wait till next title to learn why!) needs to be stored into viewstate, which means storing once the following additional string:
System.Web.UI.WebControls.Unit
None of the two serializers, the v1.x and the Whidbey one, do support any special serialization for this type; it’s being handled by a UnitConverter.
How this absence of a type code for Unit in Whidbey ends up reflecting in the final footprint?
Let’s take for example the following Unit instance:
Unit u = new Unit (“100px”);
In v1.x this instance will end up serialized into 8 bytes while in Whidbey final footprint will be of 39 bytes. Ugly… I know.
Types from System.Web.dll assembly are loved (and around 82 bytes cheaper now!)
In v1.x, non-optimized types were handled down to a type converter when available. When this happens the assembly-qualified name of the type needs to be stored into viewstate which is not fun at all as it usually tends to be a quite large strings, i.e.:
System.Web.UI.WebControls.Unit, System.Web, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
In Whidbey, the serializer performs an additional check and if its dealing with a type that lives in the System.Web.dll assembly then it uses a special code (42) to signal it so only the full name of the type needs to be saved, i.e.:
System.Web.UI.WebControls.Unit
This avoids the need for having to store assembly-qualified names for any non-optimized types living in System.Web.dll assembly which will usually result in saving ~82 bytes of storage caused by the following string:
System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
There are other interesting things going on about the new serializer, like the special treatment some types as Color are given in order to produce the smaller possible footprint. I guess I will save them for a later post…
Very simple questions as “How can I programmatically set my Page’s title from codebehind?” or “How can I handle my Page’s <head> element from codebehind?” were, are and will be asked about every single day in the public newsgroups, forums, etc.
This is because v1.x doesn’t include any built-in support for handling the <head> element or any of its children elements.
This leads to the common approach of adding the runat=’server’ attribute to the <head> element and then handling it as a HtmlGenericControl. Pretty simple and pretty unfriendly stuff at the same time. In addition, having VS.NET removing the attribute at will just make things more annoying.
After looking at all the feedback from newsgroups, forums, etc, it was pretty obvious that something was needed. Because of this, the HtmlHead control was born in the PDC03 bits (and others like HtmlTitle and HtmlLink did appear in the March04 bits). The Page type itself was modified to include these additions and new properties were added: Header (in the PDC03 bits) returns an instance of a type that implements IPageHeader (HtmlHead in this case) and Title (in the March04 bits) just wraps a Header.Title call.
So now, this is how you handle this very common need in the Whidbey bits:
void Page_Load (object sender, EventArgs e) {
this.Header.Title = “This is a title”;
this.Header.LinkedStyleSheets.Add (“classicblue.css”);
this.Header.Metadata.Add (“author”,”clarius”);
}
Pretty simple, ugh? No doubt, this is a good addition. Hopefully all the confusion and how-to questions that plagued the newsgroups about how to deal with this in v1.x won’t be there for v2.0 (now that’s a wish).
While playing with this new supported I discovered a few “issues” that I describe in these posts (warning: the following info may be more than you ever wanted to know about <head> and its child elements):
Whidbey Support For HtmlHead, Part I – What title will be rendered?
Whidbey support for HtmlHead, Part II – Not only VS.NET messes up your markup
Whidbey support for HtmlHead, Part III – The missing ViewState
The third interesting observation worth noticing from HtmlHead and co. (that is, HtmlLink, HtmlHead, etc) is that they know nothing about state management… viewstate? what’s that??
The PDC03 bits didn’t include any state management code and the March04 bits still haven’t changed this. Bottom line: if you’re planning to dynamically alter the page title, the links or metadata elements you’re definitively out of luck (well… you can always implemented the code yourself…).
Let’s take for instance the HtmlTitle control: it’s a very simple (really, very simple) control that derives from HtmlControl overriding only two methods (AddParsedSubObject and Render) and adding a property named Text.
The get and set accesors for the HtmlTitle.Text property read and write a private member variable instead of using viewstate as its storage; any changes made will be lost on postback.
The same holds true for metadata and links elements, any modifications made at runtime are lost on postback.
All this new support for the head and its child elements is really a very welcomed one, but won’t be of much use without state management implemented. Let’s just hope that state management for these controls is already planned but not there only because March04 is not a feature complete build.
Now its turn to peek at how <meta> child elements are being supported. Let’s take for example the following markup:
<head runat=”server”>
<title>Foo</title>
<meta name=”one” content=”uno” />
</head>
As the <head> element has a proper runat=”server” attribute, it will be parsed as an instance of HtmlHead and you will be able to programmatically play with it at runtime like this:
this.Header.Metadata.Add (“two”,”dos”);
What output would you expect from the previous code?
This one:
<head runat=”server”>
<title>Foo</title>
<meta name=”one” content=”uno” />
<meta name=”two” content=”dos” />
</head>
Or this other real funny one:
<head runat=”server”>
<meta name=”one” content=”uno” />
<title>Foo</title>
<meta name=”two” content=”dos” />
</head>
Of course you should expect the first one, but with the March04 preview bits you’ll get the second one.
What causes this strange reordering of the tags? Uff... I mean… once we finally got VS.NET to *never* touch our markup now it’s the HtmlHead control that decides to rearrange them in the previously shown “clever” way of meta-title-meta…
Let’s try to shed some light on what’s happening here…
HtmlHead has associated a control builder, HtmlHeadBuilder. By looking at HtmlHeadBuilder.GetChildControlType we can tell that it only recognizes two different child types: HtmlTitle and HtmlLink. There is no recognition here for the <meta> element, moreover, there is not even a HtmlMeta control (as there are HtmlTitle and HtmlLink ones).
This means any <meta> elements that you may specify at design-time will be parsed as a single LiteralControl.
When it is time to render, HtmlHead rendering basically does the following (warning: very-simplistic-pseudo-code-follows):
- Render HtmlHead’s child controls (this will render the LiteralControl containing the <metadata> specified at design-time)
- Render HtmlTitle (or a blank <title></title> if none is found)
- Render Metadata items that were added programmatically
Remember our <meta> elements specified at design-time were parsed as a single LiteralControl and added to HtmlHead’s control collection. So they will be rendered before any other output of the HtmlHead control.
I’m hoping for this funny reordering to go away soon. I believe that modifying HtmlHeadBuilder to recognize childs of type HtmlMetadata (and adding such a control in the meantime) will make everyone (or at least me!) happy.