Developers often ask me what they can do to improve web standards on their ASP.NET website. There are a number of tricks available and I thought I'd share them with you.
Web.Config magic
First thing to do, is to make sure you've got your Web.Config ready for web standards. This is really simple, as there's only some copy and paste needed. What you want to do is setting xhtmlConformance mode to Strict and make use of browserCaps, both in the system.web section, like this:
<system.web>
<xhtmlConformance mode="Strict" />
<browserCaps>
<case match="W3C_Validator*">
TagWriter = System.Web.UI.HtmlTextWriter
W3CDomVersion = 1.0
</case>
</browserCaps>
....
</system.web>
Use the best .NET controls at your disposal
Countless of times you see .NET controls such as Label and Panel used. Not good, since both render extra HTML output. A label renders an extra span and a Panel renders an extra div, thus affecting the markup of the website - and at worst even breaking the layout.
To the rescue, comes the Literal and PlaceHolder controls. The Literal and PlaceHolder don't render extra markup, and I've never ran into a single problem using them instead.
Also, I like to use the Repeater as often as I can, since I don't always trust third party controls.
Set CSS class on the first listing item
You might have seen class="first" set on the first item in a listing, a number of times. For some, this is a pain to address. However, nothing could be easier than setting a specific CSS class on the first item in a listing. You just have to use the onItemDataBound event on your control. Here's how it might look:
<asp:Repeater ID="rptListing" OnItemDataBound="cssAddons" runat="server">
<ItemTemplate>
<li<asp:Literal ID="cssClass" Visible="false" runat="server"> class="first"</asp:Literal>>
<%#Eval("Item") %>
</li>
</ItemTemplate>
</asp:Repeater>
And the codebehind:
protected void cssAddons(object sender, RepeaterItemEventArgs e)
{
ListItemType type = e.Item.ItemType;
if (type == ListItemType.Item)
{
if (e.Item.ItemIndex == 0)
{
Literal litCssClass = (Literal)e.Item.FindControl("cssClass");
if (litCssClass != null) litCssClass.Visible = true;
}
}
}
You should never be forced to rebuild a project when doing layout changes - that's why one would prefer to use a hidden Literal with the CSS class in the ItemTemplate, and toggling the visibility if it's the first item in a listing.
Customized web controls and CompositeControl
A lot of you are perhaps writing your own web controls. Take note though, inheriting from CompositeControl will make your web controls render an extra span. There's a simple solution to this - just override the Render method in your control, like this, and you're set:
protected override void Render(HtmlTextWriter writer)
{
RenderContents(writer);
}
Some reminders - naming conventions and id's
When it comes to ASP.NET and naming web controls, things can get messy. You want to name your controls as short as possible, without making the name totally meaningless. You particularly want to name your ContentPlaceHolders in a smart way, to avoid id's like this:
ctl00_ContentPlaceHolderContent_ContentPlaceHolderMain_ContentPlaceHolderWidePageWithoutTopImage_ContentPlaceHolderWidePage_ContentPlaceHolderPageContent_ButtonSend
I regularly prefix my web controls, rpt for Repeater, cph for ContentPlaceHolders and so on.
Another problem in ASP.NET Web Forms is id's. If you use runat="server" with a HTML element, the id might look like in the example above. You must avoid this as much as you can, since the altered id's might break the layout. Some might say you should use CSS classes instead, but that's not the way to go. CSS classes aren't meant to be used instead of id's.
In ASP.NET 4, you can actually choose how your id's are rendered, through the ClientIdMode property. A welcome change!
More reading
Remember this is aimed at ASP.NET Web Forms websites, even though part of the tricks can be used in an MVC environment too!
Today there's a lot of talk about duplicate content and SEO. What happens to your blog when a search engine crawls it and discovers the same blog post exists in a specific category archive, and on an own page? What happens to your e-commerce website when you've got products tagged with more than one tag? Duplicate content.
This creates problems for search engines - but there's a simple solution - canonical urls.
Canonical urls to the rescue
Canonical urls, or canonicalization as it also is called, helps you decide what address should be the standard address for specific content on your website. What you want to do is to start using a new link rel attribute: canonical.
Put the new link rel attribute in <head> and provide the default url for the specific content, like this:
<link rel="canonical" href="http://blog.dileno.com/archive/200907/going-english/" />
Read more about canonical urls in Google's webmaster blog.
Ever e-mailed code? Ever wanted to share code in an easy way, online? Look no further - here's 10 online tools for code hosting, making it easier than ever before to share code.
- Used particularly for .NET code
- Code formatting
- Tagging
- Member area

- Online source code editor
- Code formatting

- Code formatting
- Version control
- Admin possibilities

- Code formatting
- Version control
- Member area

- Code formatting
- Version control
- Admin possibilities


- Code formatting
- Tagging
- Version control
- Member area

- Code formatting
- Tagging
- Member area

- Code formatting
- Member area

- Code formatting
- Member area

Very often you add a namespace or register an assembly on top of an ASP.NET page, like this:
<%@ Page Language="C#"
AutoEventWireup="True"
CodeBehind="Default.aspx.cs"
Inherits="ProjectName._Default" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="ProjectName.Classes" %>
<%@ Register Assembly="ProjectName" Namespace="ProjectName.Controls" TagPrefix="cc" %>
It works to do once or twice, but when you need to add these namespaces and controls on several different pages, it quickly becomes maintenance hell.
What to do? Use Web.Config instead.
You just have to declare your namespaces and controls in the system.web section, like this:
<system.web>
<pages>
<namespaces>
<add namespace="System.IO" />
<add namespace="ProjectName.Classes" />
</namespaces>
<controls>
<add assembly="ProjectName" namespace="ProjectName.Controls" TagPrefix="PN" />
</controls>
</pages>
</system.web>
Then you will be able to write code like
<%=Toolbox.FormatHtml("....") %>
instead of code like
<%=ProjectName.Classes.Toolbox.FormatHtml("....") %>
A clear improvement. You also won't need to register your controls everywhere to use them.
If you haven't been using this feature (it already came in ASP.NET 2.0!) it's time now!