Today I decided to set myself a little challenge, I wanted to see if I could use the Control Adapter framework which shipped with ASP.NET 2.0 that allows the developer to override and uniquely control the rendering of all the ASP.NET controls, to render and ASP.NET page in normal HTML for IE and in XAML for Firefox.
This little project took me three hours to put together and get to the stage where I can write about my experience, so it’s a bit rough and ready!
SOURCE CODE CAN BE FOUND HERE
http://www.myservicescentral.com/CodeSamples/CssAdapters1.zip
A little background before we move on, I’ve not really used XAML yet, but understand it will be the markup for future Windows Forms style applications and will force all those Windows Developer to learn how to use <spikey brackets />. A friend of mine has been ranting on for years about how ASP.NET will be the platform of the future and how it will render out content as it see’s fit, with that in mind, I thought I’d take a stab at producing XAML from ASP.NET controls.
The first thing I did was checked out this post from Scott Guthrie on the ASP.NET 2.0 Control Adapter Architecture. Then I grabbed a copy of the CSS Adapter Toolkit, which details how to create CSS friendly controls and gives some really cool examples of some of the ASP.NET controls which have already been CSSified (is that a word? Well it is now!).
After reading through the source code which is all provided with the CSS Adapter Toolkit I was SCARED at how EASY it all was!
The fist thing I did was create a page which I could use to test my XAML Adapters.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="XamlPage.aspx.cs" Inherits="XamlPage" %>
<form runat="server">
<p>Here is some content</p>
<asp:Label id="EmailLabel" runat="server" Text="What is your e-mail address?"></asp:Label>
<asp:TextBox id="EmailTextBox" runat="server" Text="Type your e-mail address here." />
<asp:RequiredFieldValidator id="EmailRequired" runat="server" ControlToValidate="EmailTextBox" ErrorMessage="Email Address is Required" />
<asp:Button id="EmailButton" runat="server" Text="Register your e-mail address!" />
</form>
Once I had my page it was time to build my first Adapter so I set to it at the top level and decided to create my own System.Web.UI.Page implementation which instead of squirting out something like <html><head /><body></body></html> needed to produce the XAML equivalent which is <application></application>. The code was amazingly simple: -
using System;
using System.Web;
using System.Web.UI;
namespace Plipster.XamlAdapters
{
public class PageXamlAdapter : System.Web.UI.Adapters.PageAdapter
{
protected override void Render(HtmlTextWriter writer)
{
writer.WriteLine();
writer.WriteBeginTag("Application");
writer.Write(">");
writer.WriteLine();
base.Render(writer);
writer.WriteLine();
writer.WriteEndTag("Application");
}
public PageXamlAdapter()
{
}
}
}
Once the control had been created I needed to tell ASP.NET to use my new control in place of the standard System.Web.UI.Page control under the circumstances that I wanted it to. In the Real World those circumstances would be “The client is running WinFX and can support XAML”, in the world of test environments it was “The client is running Firefox so we’ll pretend that’s WinFX”.
I created this browser file: -
<browsers>
<browser refID="MozillaFirefox">
<controlAdapters>
<adapter controlType="System.Web.UI.Page" adapterType="Plipster.XamlAdapters.PageXamlAdapter" />
</controlAdapters>
</browser>
</browsers>
So once this is all set up, requesting any ASP.NET page through firefox just returns the following content: -
<Application>
</Application>
Extend it a little bit and create all the Controls that I listed in the page with their XAML equivalents and you get something like this: -
<Application>
<Canvas Background="LightCyan">
<Text>
<p>Here is some content</p>
</Text>
<Text>What is your e-mail address?</Text>
<TextBox>Type your e-mail address here.</TextBox>
<Text Color="Red">Email Address is Required</Text>
<Button>Register your e-mail address!</Button>
</Canvas>
</Application>


So what’s so cool about this? Well it shows the true power of control adapters, it also shows how easy they are to manipulate and bend to your own will.
Next steps: -
- How do you get code (C#/VB.NET) to work with this XAML?
- Do we go about rendering and compiling on the server and then stream down a binary with all the code pulled together on the server and compiled?
- Perhaps some form of Ajax style abstraction layer such as Atlas will communicate from the client to the server – maybe even use Atlas and XMLScript to do this?
- What else can we produce, not just XAML and HTML, surely there are other markups or text based languages we can produce with the adapters.
- What about a Java Adapter, one which produces client runnable applications that can be created to run on non Windows Machines?
- Mobile devices – what a huge topic, and exercise for the reader I think!
- How cool would a Windows Forms Adapter be – how about a bit of code generation, server side compilation and then binary stream of an executable down to a client – it’s just text after all! Here’s the Windows Forms code for a similar UI to the one ASP.NET produced.
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.EmailLabel = new System.Windows.Forms.Label();
this.EmailTextBox = new System.Windows.Forms.TextBox();
this.EmailButton = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(16, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(120, 23);
this.label1.TabIndex = 0;
this.label1.Text = "Here is some content";
//
// EmailLabel
//
this.EmailLabel.Location = new System.Drawing.Point(24, 96);
this.EmailLabel.Name = "EmailLabel";
this.EmailLabel.Size = new System.Drawing.Size(160, 23);
this.EmailLabel.TabIndex = 1;
this.EmailLabel.Text = "What is your e-mail address?";
//
// EmailTextBox
//
this.EmailTextBox.Location = new System.Drawing.Point(208, 96);
this.EmailTextBox.Name = "EmailTextBox";
this.EmailTextBox.Size = new System.Drawing.Size(136, 20);
this.EmailTextBox.TabIndex = 2;
this.EmailTextBox.Text = "Type your e-mail address";
//
// EmailButton
//
this.EmailButton.Location = new System.Drawing.Point(24, 144);
this.EmailButton.Name = "EmailButton";
this.EmailButton.Size = new System.Drawing.Size(176, 23);
this.EmailButton.TabIndex = 3;
this.EmailButton.Text = "Register Your e-mail address";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(400, 238);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.EmailButton,
this.EmailTextBox,
this.EmailLabel,
this.label1});
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
Okay I think that’s enough food for thought – play nicely now children J
Tonight I went for dinner with several people I know in and around the Manchester area whom are all involved in the .NET community, the attendees were Mike Taulty, Dave Verwer, Andrew Stopford and Tony Whitter.
We went to a particular favorite of mine - Shimla Pinks in Manchester, it's an Indian pleace but is very tendy, lots of neon and black marble ;-)
A most interesting night, some highlights: -
Andrew Stopford appears to know what "getting maced" is like, I stopped short of asking if he knew what personal attack alarms sounded like.
Tony Whitter proved to us all that over many years of abuse the taste buds along his tongue have been rendered completly and utterly useless by eating the hottest and most deadly curry he could find and then asking for some raw chilies to give it that extra kick. Nutter! Also Tony was right, the car park did punish me for parking there for a few hours - £12.80 !
Dave Verwer is a DIRTY MAC USER AND SHOULD DIE FOR HIS SINS. Apparently he has already heard all of the jokes I tried to come up with about Macs.
All in all I think a good night was had by all - and we didn't even talk about Tony's hedgehogs.