Austin and Kaizenconf Part 1 - workshops

It's finally there, Jan and I departed from Belgium to Austin, Texas to attend Kaizenconf. I have been looking forward to this for quite a while. It didn't start out good when I spilled my first drink on the plane, but it only got better from then on. After a long flight with a stopover in Atlanta we arrived at the Austin airport. A lot smaller then I expected but that didn't really matter.

Advanced NHibernate

On the first 2 days of Kaizenconf some promising workshops where scheduled, we decided to go listen to the great ayende talking about Advanced NHibernate. The talk started off with a blast when ayende gave a demo of the NHibernate Profiler that is being developed. Although beta it looks like this will be a real hit and it will help developers to get to know and control NHibernate better. I don't see myself as an advanced NHibernate user but it was nice to follow a workshop that isn't the usual introduction on how to create a Northwind CRUD application.

Below is a screenshot of the NHibernate Profiler, although it's not the best of quality you can see the query that NHibernate has generated, the different queries that were fired onto the database and much more. Very, very promising!

 

Another topic that was explained is the use of Lucene with NHibernate. By using a couple of attributes on your domain models to indicate which parts should be indexed, you get a very easy way to make your data searchable. Because the original is always better, here is a short video where the advantages of using Lucene with NHibernate are explained:

We went on to NHibernate caching and again I discovered something that will change the way I use NHibernate on a daily basis. Seems like caching is actually very intelligent but, as with everything, you have to watch out not to shoot in your own foot. Oren showed us an example that called the database 4 times without using any caching and called the database 42, yes forty-two, times with badly configured caching.

Here are some random notes I took that I'd like to keep in mind for future use of NHibernate:

- When loading an object via session.Load the query gets fired when the object is being accessed, not when the Load() function is called

- NHibernate solves threading issues with caching by returning different instances of the same object to different users

- Queries can also be cached, call the SetCacheable(true) function on every occurrence of the given query you want to cache

After this excellent session we were looking for something to eat. Luckily some of the attendees (thank you Chris and Tim) were kind enough to give us a ride to Rudy's BBQ where we learned that 'Real people eat meat'. I don't think they have a lot of veggies under their customers.

Functional programming - Is it a game changer?

For the second workshop a difficult choice had to be made. It was choosing between the DDD chalk talk of David Laribee or the workshop about Functional programming of Matt Podwysocki. You probably already guessed the one I chose. This was something completely different then the NHibernate talk and Matt asked several times if our brain hadn't exploded yet, and if I'm honest I had to answer yes every time he asked it. There was a lo-hot of information to take in.

The first part of the presentation was about making C# more functional. By heavily using the new features in C# 3.0, a lot of for-each loops could be eliminated with the help of stuff like LINQ and lambda expressions. Matt told us that F# is very good at math stuff, the software that determines the best player in Halo 3 is written in F#. Because F# has a specific purpose, there will never be a designer to create GUI's or web pages using F#. I think I heard a little cheering in the room after those words. I still have to take a closer look to the abundance of examples Matt provided us to be able to give a deeper insight into F# so I'll leave it at that for now.

Although I'd like to show a piece of code that Matt shared to point out the dangers that come with lazy evaluation of code:

Func<String> GetContent;

 

using(StreamReader fileStream)

{

   GetContent = fileStream.ReadToEnd();

}

 

String content = GetContent();

Because the fileStream is out of scope when calling the GetContent function reference, this will give unexpected behavior which is very hard to debug if you ask me. Another good session for which I'd like to thank Matt.

The conclusion of the first day of kaizenconf is very good. As I already said the sessions were of high quality. I'm already looking forward to day 2 which has an ASP.Net MVC session given by Jeremy Miller and Chad Myers. Very exciting!


Creating a menu for your ASP.NET MVC website using HTML helpers

I've been working with ASP.NET MVC for a few months and it has been quite a ride. I'm working on a website where the menu is loaded from the database. It should be rendered as an unsorted list and a CSS class should be added to the active item. Here is an example of the menu:

<ul id="navigation">

    <li class="active"><a href="about-us.aspx">About us</a></li>

    <li><a href="location.aspx">Location</a></li>

    <li><a href="what-can-we-do-for-you.aspx">What can we do for you?</a></li>

    <li><a href="works-on-my-machine.aspx">Works on my machine</a></li>

</ul>

This is certainly no rocket science, a normal website navigation build with XHTML and CSS. Because ASP.NET MVC has no things as viewstate, server controls or postbacks we need another approach then what we're used to. In ASP.NET Web forms the unsorted list would probably be a server control which we then would manipulate in the code behind. But we're not using ASP.NET Web forms, we're using ASP.NET MVC and that's a good thing!

The first solution I found was adding a property to my Navigation model class called Active. So the Navigation class looked like this:

public class Navigation

{

    public virtual Int32 Id

    {

        get; set;

    }

 

    public virtual String Label

    {

        get; set;

    }

   

    public virtual String Link

    {

        get; set;

    }

 

    public virtual Boolean Active

    {

        get; set;

    }

}

Notice that the Link property maps to the action we want to perform.

In the controller I would first fetch the navigation items from the database and copy them to the ViewData property, then iterate through the collection of navigation items and compared the action of the current page to the navigation items in the collection. If the actions matched then the active item was found and the property was set. There were a few moral problems I had with this approach. First it was quite some code to do something simple as setting the active item of a menu. Second, and this was the worst problem, you had to add logic to your view in order to output the correct HTML for the active item. In the view something like this had to be done:

<% foreach(var navigationItem in (ViewData["navigation"] as TwotoContent.Domain.Models.Navigation[]))

   {

        if(navigationItem.Active)

        {

            %><li class="active"><%

        }

        else

        {

            %><li><%

        }

%>   

            <a href="<%= navigationItem.Link + ".aspx" %>">

                <%= navigationItem.Label %>

            </a>

        </li>

<% }%>

Oh crap! This resulted in logic in the view which could not be tested, on top of that it polluted the view. I started searching Google for better solutions and found this thread. The last post is actually the most valuable one. Ben Scheirman, who has a most excellent blog by the way, posted the tip to use HTML helpers for this purpose. I had read about HTML helpers, but unfortunately none of the helper methods that existed actually did what I needed. So I decided to create my own. Drew Miller wrote a nice post about writing your own HTML helper.

Here are a few advantages about creating your own HTML helper:

  • Your view doesn't get cluttered
  • The code in the HTML helper is testable
  • Less code in your controller, this means less code to maintain which is always a good thing

So I created the following extension on the HTML helper class:

public static String NavigationItem(this HtmlHelper htmlHelper,

                                    String actionLink,

                                    String controller,

                                    String itemTitle)

{

    var htmlTemplate = htmlHelper.ActionLink(itemTitle, actionLink, controller) + "</li>";

    var action = htmlHelper.ViewContext.RouteData.Values["action"];

 

    if(String.Compare(actionLink, action.ToString(), true, CultureInfo.InvariantCulture) == 0)

    {

        htmlTemplate = "<li class=\"active\">" + htmlTemplate;

    }

    else

    {

        htmlTemplate = "<li>" + htmlTemplate;

    }

 

    return String.Format(htmlTemplate, actionLink, itemTitle);

}

 

As you can see I do use one helper method, the ActionLink method, in order to create a link for the given action for the given controller. The advantage of using ActionLink is that it takes the defined routes into account so you don't have to worry about that. Then we compare the given action to the current action if those two are equal we generate a list item with the correct class, otherwise we just generate a list item. Now we can write something like this in our view:

<% foreach(var navigationItem in (ViewData["navigation"] as TwotoContent.Domain.Models.Navigation[]))

   {

       Html.NavigationItem(navigationItem.Link, "mycontroller", navigationItem.Label);

   }

%>   

This will generate the menu just as we want it to be. I'm sure this solution still has drawbacks but I hope you agree this is a big improvement compared to the first solution. If you have any suggestions to improvement, questions or remarks I'll be glad to listen to them.


Descriptive names versus abbreviations for UI elements

I have been using abbreviations for UI elements for a long time. I think most developers have and still do. When you declare a button which will give the user the possibility to log on, it will be called: btnLogOn (or something similar). At first I wasn't really thinking this through and automatically started the name of a dropdownlist with ddl, of a label with lbl etc... One day I was programming in Visual Studio, I was creating a trivial user interface, and I typed something like this:

<label for="txtEmailAddress">

  <asp:Literal runat="server" Text="<%$ Resources: CommonResources, EmailLabel %>"></asp:Literal>

</label>

<input type="text" runat="server" id="txtEmailAddress" /><br />

<label for="txtPassword">

  <asp:Literal runat="server" Text="<%$ Resources: CommonResources, PasswordLabel %>"></asp:Literal>

</label>

<input type="password" runat="server" id="txtPassword" /><br />

Then I went to the code behind file and started adding functionality:

string logOnResult = CustomerServiceBusinessObject.LogOn(txtEmailAddress.Value, txtPassword.Value);

When suddenly it hit me: why was I using these ugly names for UI elements (txtPassword, txtEmailAddress) which mess up my code? Why can't I just name them like every other variable I use? So the code above became:

string logOnResult = CustomerServiceBusinessObject.LogOn(emailAddressTextBox.Value, passwordTextBox.Value);

Of course when you are working on a project with fellow programmers, you have to try to follow the same guidelines and naming conventions in order to get consistent source code. If one programmer uses abbreviations and the other isn't, the result is even worse then when using abbreviations. So I started up the discussion at work. Because I couldn't convince all my colleague's we decided to put it on the Development Guidelines. This is a monthly get together with the team where we discuss interesting tools, new development techniques and other geeky stuff that could help us in your daily job.

While discussing the matter the following advantages/disadvantages of using abbreviations were mentioned:

Advantages Disadvantages
  • You can see in an instant what the type of the class member is
  • If you use intellisense and press Control+Enter, al buttons are alphabetically grouped
  • It's a Microsoft coding guideline
  • For UI elements like a button the abbreviation is obvious, btn, but for other elements (DataList, DataGrid, ...) there are variations of abbreviations that are being used. This makes it very hard to keep code consistent and readable
  • Because variables of other types for example Strings or Integers are normal typed, the code gets polluted by UI elements

Eventually we decided to leave abbreviations behind and use descriptive names for UI elements. One small step for men, when giant leap for code readability.

To take it to the next step, you could argue that all UI elements are actually class members. And because I prefix all my class members with an underscore, you could do the same with UI elements. So logOnButton would become _logOnButton. I don't do it like that - yet - because I'm not convinced that it is the way to go. This could be taking it too far.

What do you think? Do you still use abbreviations for UI elements?


Aggiorno, the Italian colleague you've always wanted

logo Ever had someone come to your desk and saying: I have a little project for you, you should change something in our state of the art web application. After agreeing you would do the changes, you open up the solution and you see that the state of the art application is built using HTML spaghetti. At that moment you wished you had a) a gun or b) some guy on your team that loves monkey work and cleans all the code for you. Someone who gets a kick out refactoring FONT-tags to CSS an making the indentation perfect. Let's be honest, if the guy exists he's probably playing chess with Yoda in a galaxy far, far away.

The problem is that most of the time the spaghetti wasn't made by a fellow programmer. Visual Studio 2003 had the nasty habit to mess up your beautiful hand coded HTML with perfect indentation to an unseen spaghetti mess. Luckily Visual Studio 2005 keeps his hands off your work of art. But what to do with projects that are ported from .Net 1.1 (and Visual Studio 2003) to .Net 2.0 (and thus Visual Studio 2005)? The HTML doesn't get cleaned and it's very time consuming and plain sucks to do it by hand, certainly for large pages. Now there is a solution to do all the grunt work for you: Aggiorno.

Aggiorno is a plug-in for Visual Studio 2005 or 2008. Once installed, you get an extra option in your menu bar (and in your context menu).

Picture 1 

The most important menu item is the Aggiorno... item. If you click it you will get a popup with a few options. Let's go through some them.

Picture 2

Add Alternate Text to Images

Adding alternate text to all of your images by using the alt-attribute is very important in web accessibility. If the browser can't render the images, it will show the alternate text instead. Screen readers will read the text out loud so visually impaired web surfers will have an idea of what the purpose of the image was. For example, if the image of an arrow is used to go to the next item, the alt text of the arrow image would be "Go to next item". A screen reader that can't show the image to his (blind) user, will read the alternate text instead. Keep in mind that not all images need an alt text, images that are only used for the design of the web site don't need an alternate text because they give no added value to the textual version of the web site. You still have to add the alt attribute but you leave it blank in such cases.

When performing "Add Alternate Text to Images", Aggiorno gives you an overview of all the images on your ASPX page that don't have an alt attribute and gives you the choice to add an alternate text.

Assign Tab Index

Picture 4

This is also a very nice feature. For people that don't know tab index, if you use the tab-key to browse through the different input elements (that includes text boxes, checkboxes, radio buttons and all other UI elements) tab index will be used to determine the order in which the elements will be browsed. Aggiorno will go through your page and list all the input elements you have on that page. It will also highlight all the elements it has found, you get a popup in which you can specify the tab index for all the elements on the page.

The only thing I'm missing in this list is the name of the input element we're about to change. But keeping in mind that this is only RC0, this could be added in future releases. If you click on a row in the file column you will go to the corresponding line in your code file. I can live with that.

Fix Deprecated Elements for XHTML Compliancess2

This menu item searches your page for deprecated HTML tags like <FONT> or <CENTER>. It will replace those tags with inline CSS.

Fix Syntax Errors for XHTML Compliance

Using this option, Aggiorno will look for a variety of errors in your document: attributes that are not quoted and html tags that are still uppercase. If you want certain things to be retained, you can tweak the plug-in. It's certainly no all or nothing action. This one is extremely useful and has literally saved me hours.

Oh yeah, it will also add the necessary and correct DOCTYPE to your document.

Preview

If you run one of Aggiorno's options, you will get a preview window which will show you all the modifications it will make on your source code. It will highlight all changes and you can navigate through them. If you don't like what it has done to your HTML code, you can back out. So nothing becomes final until you press the OK button on the preview window.I've added some screen shots to give you an idea about how powerful this tool really is.

ss1

Conclusion

I'm very enthusiastic about this plug-in, but some caution must be taken while using it. Some options will change the structure of your HTML, a possible consequence is that the rendering of your page could be different in some (or all) browsers. Test your pages before putting them out in the open!

There is no more excuse that your web pages aren't built with mint HTML code. Aggiorno does all the dirty work for you and is a real time saver. It is extremely useful if you use it in a project that has been ported from .Net 1.1 to .Net 2.0 or that has badly written HTML code. But even when you're starting a new project, it's a handy tool to get your HTML code as perfect as possible. This tool is in my top 5 of best visual studio plug-ins and it doesn't even have a full release yet! If you work in Visual Studio and care about valid and accessible web pages (and you should), this is a must install. And there is no reason why you wouldn't because the RC0 is available for free.

This is only a brief touch of the possibilities of Aggiorno, there are many more options but you better see for yourself how powerful this plug-in is. There are some introduction videos on the Aggiorno web site as well.

What are you waiting for? Go get it!


Brazilian waxing, choosing a JavaScript framework and why I don't like ASP.NET AJAX

Let me first clarify something. As Jan pointed out I am into Brazilian waxing but please, all you pervert guys stop sending me emails with questions about the subject!

Now that's taken care of, we can get to the matter at hand. A couple of days ago, somebody asked me what the best JavaScript / AJAX framework is to start a new web application project. Because we work mostly with Microsoft technologies the answer should be obvious: ASP.NET AJAX. But I have been working with ASP.NET AJAX for the past few months now and I really don't like it. The first problem with ASP.NET AJAX is rather well known throughout the community: the UpdatePanel. I have found a good article which explains why the UpdatePanel is evil. I would recommend not to use it. It plain sucks. The second fact that I hate about ASP.NET AJAX, including the control toolkit, is the fact that you are cluttering your HTML code with all sorts of custom server controls. I don't want clutter in my ASPX page, I want it to be as clean as possible (thank you ASP.NET MVC). I want my JavaScript in a separate file so I have a clear distinction between presentation (CSS), markup (xHTML) and behavior (JavaScript). I know you don't have to use the drag-and-drop method and that you can use the same ASP.NET AJAX classes in JavaScript, but doing this is painful because documentation is lacking.

These things don't stimulate you in becoming a better (web) programmer. In order to be able to solve the problems you encounter with your software, you have to know how stuff works. It doesn't pay off to be able to open a designer, drag and drop some server controls on it and then wrap them in an UpdatePanel to create a web page using AJAX. You are missing out on a lot of exciting stuff that you encounter when doing client side web programming. You are missing out on JavaScript, a whole new and exciting language. When learning a new programming language you once again have a way of doing things differently, you can see how the new language tries to solve the same problems in comparison to other programming languages and learn from it.

I know it is possible to reference the MicrosoftAjax.js file directly, and write out object oriented JavaScript. Most of the literature mentions that this is possible but very few really go into the matter.

If you compare them to the other JavaScript frameworks out there, jQuery, prototype (with scriptaculous), YUI, ... Documentation is abundant and these frameworks don't try to give you the drag-and-drop experience. They just give you a decent framework, which is necessary with JavaScript, to start enriching your web pages. On wikipedia there is a comparison of the different JavaScript frameworks and ASP.NET AJAX isn't even included! I think that says a lot about the popularity and usage of ASP.NET AJAX.
So before choosing a JavaScript / AJAX framework, don't go blindly for the Microsoft solution. It's not the best around, try out the different frameworks and take the one you like. I have been using AjaxPro with prototype for my personal projects but development of AjaxPro has stopped. For new projects I am going to use ASP.NET MVC, which is great by the way, in combination with jQuery. Chad Myers has a very good how to on the matter.

To conclude I would like to share the different books I have been using/reading about the matter:

51XWseT1BbL._SL160_PIsitb-dp-arrow,TopRight,21,-23_SH30_OU01_AA115_51OY5KP5ydL._SL160_AA115_  416ConPucQL._SL160_AA115_ 512OlKc-kUL._SL160_AA115_ 

I'll probably be writing a review on one or more of these books, although I'll first have to write about the pussy way of development like I promised Patrick.


Building accessible web forms with ASP.NET

First of all, let me welcome you to my brand new blog. It will serve as a personal reference and a way to (hopefully) become a better software developer by researching and writing about technology. And don't forget if you liked the article, subscribe to the RSS. It's free and saves you time!

Now let's get our hands dirty...

When designing a web form with ASP.NET you usually fire up the web forms designer that comes with Visual Studio and start dragging and dropping server controls on the page. This is the normal way of designing a web form, the way Microsoft promotes. They have provided us with a Label server control which we all use to put a text near a certain TextBox, DropDownList or something similar. A common web form might look something like this:

 default_form

The markup for this form is:

<form id="form1" runat="server">

    <fieldset>

        <legend>Default ASP.Net form</legend>

        <asp:label runat="server" id="userNameLabel">username:</asp:label>

        <asp:textbox runat="server" id="userName"></asp:textbox>

        <asp:label runat="server" id="passwordLabel">password:</asp:label>

        <asp:textbox runat="server" id="password"></asp:textbox>

        <hr />

        <asp:label runat="server" id="streetLabel">street:</asp:label>

        <asp:textbox runat="server" id="street"></asp:textbox>

        <asp:label runat="server" id="numberLabel">number:</asp:label>

        <asp:textbox runat="server" id="number"></asp:textbox>

        <asp:label runat="server" id="zipCodeLabel">zipCode:</asp:label>

        <asp:textbox runat="server" id="zipCode"></asp:textbox>

        <asp:label runat="server" id="cityLabel">city:</asp:label>

        <asp:textbox runat="server" id="city"></asp:textbox>

        <hr />

        <asp:button runat="server" id="submit" text="Submit" cssclass="button" />

    </fieldset>

</form>

Let's not get carried away with the look and feel of this form, it could be better, but that's not what what we care about in this article. Let's have a look at what happens under the surface, if we look at the source of this page we see the following piece of generated HTML :

<form name="form1" method="post" action="Default.aspx" id="form1">

<div>

    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/..." />

</div>

<fieldset>

    <legend>Default ASP.Net form</legend>

    <span id="userNameLabel">username:</span>

    <input name="userName" type="text" id="userName" />

    <span id="passwordLabel">password:</span>

    <input name="password" type="text" id="password" />

    <hr />

    <span id="streetLabel">street:</span>

    <input name="street" type="text" id="street" />

    <span id="numberLabel">number:</span>

    <input name="number" type="text" id="number" />

    <span id="zipCodeLabel">zipCode:</span>

    <input name="zipCode" type="text" id="zipCode" />

    <span id="cityLabel">city:</span>

    <input name="city" type="text" id="city" />

    <hr />

    <input type="submit" name="submit" value="Submit" id="submit" class="button" />

</fieldset>

<div>

    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/.../U0=" />

</div>

</form>

The problem with the Label server control is that it generates a <span>-tag. The browser has no clue that a given label applies on a given input field. And the <span> doesn't describe its content, from a semantic point of view it's not right. Why is this necessary? Don't you see which label applies on which input field? That's right, for us it's most of the time easy to link a certain label to an input field. But visually impaired users have a harder time trying to figure out what they have to fill into the input field. If the input field and the label aren't close to each other, it's impossible for a screen reader to make the link between the label and the input field.

Instead of using the Label server control, we could use the <label>-tag. The html <label>-tag describes its content, in this case it describes that the text in front of the textbox, dropdownlist, ... is actually the label for that input field. This is a much better practice and not only from a semantic point of view. Another benefit of using the html tag is that we can style it very easily via CSS. In order to couple the <label> to a certain input field we use the for attribute. The value of the for attribute should be the ID of the input field which the label describes.

If we change our form and use the newly learned <label>-tag, we get the following code:

<form name="form1" method="post" action="Default.aspx" id="form1">

<div>

    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/..." />

</div>

<fieldset>

    <legend>Default ASP.Net form</legend>

    <span id="userNameLabel">username:</span>

    <input name="userName" type="text" id="userName" />

    <span id="passwordLabel">password:</span>

    <input name="password" type="text" id="password" />

    <hr />

    <span id="streetLabel">street:</span>

    <input name="street" type="text" id="street" />

    <span id="numberLabel">number:</span>

    <input name="number" type="text" id="number" />

    <span id="zipCodeLabel">zipCode:</span>

    <input name="zipCode" type="text" id="zipCode" />

    <span id="cityLabel">city:</span>

    <input name="city" type="text" id="city" />

    <hr />

    <input type="submit" name="submit" value="Submit" id="submit" class="button" />

</fieldset>

<div>

    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/.../U0=" />

</div>

</form>

Because the different <label>-tags are html elements and not server controls, ASP.NET won't mess with the markup and just leave it as it is. The HTML code that is generated is much cleaner, much more accessible specially for visually impaired visitors and on top we save on viewstate (if viewstate is not turned off, which you should whenever possible)!

A careful reader is asking himself right now: but what if I'm using master pages or a user control? When using master pages or user controls, ASP.NET changes the ID of the server controls in order to make them unique (certainly the case with user controls). To solve this we use some inline coding tags to get the ClientID of the server control into the for attribute of the corresponding <label>-tag. Did I lost you? Let's alter our example to make a bit more clear:

<form id="form1" runat="server">

    <fieldset>

        <legend>Accessible, without master</legend>

        <label for="<%= userName.ClientID %>">username:</label>

        <asp:TextBox runat="server" ID="userName"></asp:TextBox>

        <label for="<%= password.ClientID %>">password:</label>

        <asp:TextBox runat="server" ID="password"></asp:TextBox>

        <hr />

        <label for="<%= street.ClientID %>">street:</label>

        <asp:TextBox runat="server" ID="street"></asp:TextBox>

        <label for="<%= number.ClientID %>">number:</label>

        <asp:TextBox runat="server" ID="number"></asp:TextBox>

        <label for="<%= zipCode.ClientID %>">zipcode:</label>

        <asp:TextBox runat="server" ID="zipCode"></asp:TextBox>

        <label for="<%= city.ClientID %>">city:</label>

        <asp:TextBox runat="server" ID="city"></asp:TextBox>

        <hr />

        <asp:Button runat="server" ID="submit" Text="Submit" CssClass="button" />

    </fieldset>

</form>

 

As you can see we use inline coding tags to fetch the clientID of the server control and fill it into the for attribute of the <label>-tag. If we look at the output of this page (it is wrapped in a master page) then we get the following html code (the input field ids have been truncated for your reading pleasure):

<fieldset>

    <legend>Accessible</legend>

    <label for="ctl00_..._userName">username:</label>

    <input name="ctl00$...$userName" type="text" id="ctl00_..._userName" />

    <label for="ctl00_..._password">password:</label>

    <input name="ctl00$...$password" type="text" id="ctl00_..._password" />

    <hr />

    <label for="ctl00_..._street">street:</label>

    <input name="ctl00$...$street" type="text" id="ctl00_..._street" />

    <label for="ctl00_..._number">number:</label>

    <input name="ctl00$...$number" type="text" id="ctl00_..._number" />

    <label for="ctl00_..._zipCode">zipcode:</label>

    <input name="ctl00$...$zipCode" type="text" id="ctl00_..._zipCode" />

    <label for="ctl00_..._city">city:</label>

    <input name="ctl00$...$city" type="text" id="ctl00_..._city" />

    <hr />

    <input type="submit" name="..." value="Submit" id="..." class="button" />

</fieldset>

The for-attribute of each label matches the id of the input fields. And even if the page gets moved to a user control, we don't have to change anything. The ClientID is automatically filled out for us. Another nice side effect of using this technique: When clicking on a <label>-tag, the corresponding input field gets focus. This kind of behavior is implemented in every modern browser (and Internet Explorer 6).

I use this technique to create all my forms. If you have any remarks on this topic or post please feel free to leave a comment.

Download the examples of this article: AccessibleWebForms.zip (19.60 kb)

Useful reading:

Update: Chris pointed out in the comments that there is also an AssociatedControlID property on a <asp:label>. If you set this property to the ID of your server control, then a <label> is outputted which will automatically insert the correct for-attribute. I did a Google search on the property and found out that the famous Phil Haack has written an excellent blog post about the subject a while ago, go check it out.