Colin Cochrane

Software Developer based in Victoria, BC specializing in C#, PowerShell, Web Development and DevOps.

Internet Explorer 7 Did Not Kill XHTML

Professionally I make sure that I devote a certain amount of time every week to reading articles, whitepapers and blogs related to every aspect of web development. The subjects range from web design, to programming, SEO, and those that I spend a considerable amount of time reading about: web standards, accessibility, and pretty much anything related to the W3C. The communities based around those "W3C"-centric subjects are host to some extrordinarily well-research articles, posts and comments which is largely in part to the time afforded from the relatively slow pace in which major changes occur in respect to the major areas of HTML, XHTML and CSS.

Lack Of Support

One topic of controversy in this area has been Internet Explorer 7 not supporting the application/xhtml+xml MIME type, which essentially means not supporting true XHTML as specified by the W3C. Of course with this being related to Microsoft there is the expected amount of flak coming from the anti-Microsoft camp. That said, even once you've filtered out the extremes from the discourse, there are still a lot of people who think Internet Explorer 7 killed/is killing XHTML.

The support of Internet Explorer is certainly an important factor in the mainstream adoption of a web specification, considering that all versions of IE account for over 50% of web browsers used on the net. It seems reasonable that people would think that not supporting true XHTML would be a devastating blow to a specification that has been continually rising in popularity. In a time when IE is still recovering from the frustration of web developers everywhere about IE6's poor handling of CSS it's not hard to see why a lot of people think that the IE development team has a grudge against the W3C.

Tough But Fair

The IE development team is not stupid. They are also faced with the task of creating the browser that is used by millions of people every day. It is important to remember this because the decisions made regarding the development of IE are hardly made lightly. In a post on the IE Blog Chris Wilson, the lead program manager for the Internet Explorer platform and incendently a member of the XHTML 1.0 W3C working group, explained why IE7 does not support XHTML served as application/xhtml+xml.

The reasoning was that implementing support would involve hacking in XML constructs to the existing HTML parser in IE7. The existing parser is based on compatibility, and even if the support for properly served XHTML was implemented it would still have to accommodate invalid documents, which is exactly what shouldn't happen with an XHTML document (example of what happens when attempting to view an invalid XHTML document served as application/xhtml+xml). If support involves the same silent support for invalid documents, there is really no point.

In fact, had IE7 implemented support in this fashion it would have been worse for XHTML. Take a look at how many HTML documents on the web even come close to validating against their DOCTYPE. Now think about how many of those documents use XHTML (usually as a matter of the developer trying to look like they are on the cutting edge of the internet!. )If all of these non-valid XHTML documents stopped working in Internet Explorer the average IE user, discovering that a significant portion of the websites they visit don't display in their browser, would have reverted to IE6 (shudder), which would certainly have been counter-productive to the goal of increasing the adoption of XHTML.

All in all, it is natural to get impatient waiting for proper widespread support of XHTML. Just don't let the impatience make you lose sight of the big picture.

Three CSS Roll Over Techniques You Might Not Know About

When it comes to rollover effects in web design the most common way to accomplish the effect has traditionally been with JavaScript:


JavaScript in the HEAD section

[code:html]

<script language="JavaScript">
<!--
// preload images
if (document.images) {
img_on =new Image(); img_on.src ="../images/1.gif";
img_off=new Image(); img_off.src="../images/2.gif";
}
function handleOver() {
if (document.images) document.imgName.src=img_on.src;
}
function handleOut() {
if (document.images) document.imgName.src=img_off.src;
}
//-->
</script>

[/code]


And in the element with the rollover effect

[code:html]


<a href="http://www.domain.com" onMouseOver="handleOver();return true;" onMouseOut="handleOut();return true;"><img name="imgName" alt="Rollover!" src="/images/1.gif"/></a>

[/code]

The reason this method is used so commonly is because it is simple to implement and, more importantly, avoids the "lag" on the first mouseover that comes when using a CSS background-image switch on an selector:hover rule due to the delay required to download the rollover image. One thing that a lot of people don't realize is that there are methods to accomplish this effect in CSS without the initial rollover lag.

Method One - CSS Preloading

This is the quick and dirty way to force browsers to download rollover images when they initially load the page. Let's say you have the following document:

[code:html]


<html>
<head>
<title>My Rollover Page</title>
<style type="text/css">
#rollover{background:url(/images/1.gif);}
#rollover:hover{background:url(/images/2.gif);}
</style>
</head>
<body>
<div>
<a id="rollover" href="http://www.domain.com">My Rollover Link</a>
</div>
</body>
</html>

[/code]

In this page there would be a noticible delay when a user first mouses over the "rollover" anchor. The CSS Preloading method uses an invisible dummy element set to visibility:hidden, and has the "active" version of the rollover image set as its background.

[code:html]

<html>
<head>
<title>My Rollover Page</title>
<style type="text/css">
#preload{position:absolute;visibility:hidden;}
#image2{background:url(/images/2.gif);}
#rollover{background:url(/images/1.gif);}
#rollover:hover{background:url(/images/2.gif);}
</style>
</head>
<body>
<div id="preload">
<div id="image2"></div>
</div>
<div>
<a id="rollover" href="http://www.domain.com">My Rollover Link</a>
</div>
</body> 
</html>
 

[/code]

Method Two - Image Visibility Swap

This method accomplishes the same goal of forcing the browser to load both of the rollover images, but attacks it in a different way. Using the same example as above, we basically set the background of the containing anchor element to the "active" state of the rollover, and set the contained image to be the "inactive" state. Then it's just a matter of hiding the image element on hover.

[code:html]

<html>
<head>
<title>My Rollover Page</title>
<style type="text/css">
#rollover{background:url(/images/2.gif");display:block;height:50px;width:50px;}
#rollover:hover img{visibility:hidden;}
</style>
</head>
<body>
<div>
<a id="rollover" href="http://www.domain.com"><img src="/images/1.gif" alt="My Rollover's Inactive Image" /></a>
</div>
</body> 
</html>  

[/code]

This is the method that this site uses for the ColinCochrane.com logo in the header.

Method Three - Multistate Image

This method avoids the preloading problem altogether by using only one image that contains the inactive and active states. This is accomplished by creating an image that has the inactive and active versions stacked on top of eachother, like so:



Then all you do is set the element's height to half of that of the image and use the background-position property to shift the states on hover:

[code:html]

<html>
<head>
<title>My Rollover Page</title>
<style type="text/css">
#rollover{background:url(/images/multi.gif") bottom;display:block;height:20px;width:100px;}
#rollover:hover{background-position:top;}
</style>
</head>
<body>
<div>
<a id="rollover" href="http://www.domain.com"></a>
</div>
</body> 
</html>

[/code]


Now you have some different techniques to consider when implementing rollover effects on your website.

What A Doctype Really Says About Your Markup

I have combed through thousands upon thousands of client's HTML documents since I began working in web development, and even more in my career as an SEO.  Much of this time is spent fixing invalid markup, shaving off unneeded code, and generally doing what the original developer should have done in the first place.  One thing that I quickly realized was that a disturbingly large majority of the sites I came across that were created by "professional" developers and firms seem to have absolutely no idea what a Doctype really is.  This is especially true when I see these developers slapping an XHTML Doctype on their pages, somehow thinking that since it is newer it will make them (the developers) look better.  As a developer who has actually taken the time to pore through the W3C specifications for the different revisions of HTML and XHTML, I find that practice rather irritating. 

That being said, as a developer who actually knows the difference between the various doctypes it is easy to spot markup from lazy and/or ignorant developers.  I should clarify that I don't expect all markup out there to pass the W3C validator 100%, nor do I expect perfect seperation of markup and structure.  However, when you place that doctype declaration at the top of your document, you are essentially saying "these are the rules that this document is going to abide by", and when those rules are obviously ignored I believe that says a lot about the developer who created the page.

Those tell-tale signs are easy to spot.  Self-closing ("/>") elements under an HTML doctype, or lack thereof in an XHTML document.  Capitalized elements and attributes in an XHTML document (xml is case-sensitive remember!).  Undefined elements such as <font> which has a cockroach-like ability of staying around, or attributes that aren't defined for the element they are declared on.  All indicators that the developer doesn't really understand the language they are working with.

HTML really isn't that complicated.  Someone who had never seen a piece of code in their life could pick it up within a week and have a working knowledge of the language.  Unfortunately that seems to be the average professional understanding of it as well, because it is apparantly too much to expect someone who makes a living using a markup language to take a few hours and actually learn how to use it properly.

Using the ASP.NET Web.Sitemap to Manage Meta Data

kick it on DotNetKicks.com

In an ASP.NET application the web.sitemap is very convenient tool for managing the site's structure, especially when used with an asp:Menu control.  One aspect of the web.sitemap that is often overlooked is the ability to add custom attributes to the <siteMapNode> elements, which provides very useful leverage for managing a site's meta-data.  I think the best way to explain would be through a simple example.

Consider a small site with three pages: /default.aspx, /products.aspx, and /services.aspx. The web.sitemap for this site would look like this:

<?xml version="1.0" encoding="utf-8" ?>

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

<siteMapNode url="~/" title="Home">

     <siteMapNode url="~/products.aspx" title="Products" />
     <siteMapNode url="~/services.aspx" title="Services" />

</siteMapNode>

 

Now let's add some custom attributes where we can set the Page Title (because the title attribute is where the asp:Menu control looks for the name of a menu item and it's probably best to leave that as is), the Meta Description, and the Meta Keywords elements. 

 

<?xml version="1.0" encoding="utf-8" ?>

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

<siteMapNode url="~/" title="Home" pageTitle="Homepage" metaDescription="This is my homepage!" metaKeywords="homepage, keywords, etc">

     <siteMapNode url="~/products.aspx" title="Products" pageTitle="Our Products" metaDescription="These are our fine products" metaKeywords="products, widgets"/>
     <siteMapNode url="~/services.aspx" title="Services" pageTitle="Our Services" metaDescription="Services we offer" metaKeywords="services, widget cleaning"/>

</siteMapNode>

 

Now with that in place all we need is a way to access these new attributes and use them to set the elements on the pages.  This can be accomplished by adding a module to your project, we'll call it "MetaDataFunctions" for this example.  In this module you add the following procedure.

 

Public Sub GenerateMetaTags(ByVal TargetPage As Page)
    Dim head As HtmlHead = TargetPage.Master.Page.Header
    Dim meta As
New HtmlMeta

    If SiteMap.CurrentNode IsNot Nothing Then
      meta.Name = "keywords"
      meta.Content = SiteMap.CurrentNode("metaKeywords")

      head.Controls.Add(meta)

      meta =
New HtmlMeta
      meta.Name = "description"
      meta.Content = SiteMap.CurrentNode("metaDescription")
      head.Controls.Add(meta)

      TargetPage.Title = SiteMap.CurrentNode.Description
   
Else

      meta.Name = "keywords"
      meta.Content = "default keywords"

      head.Controls.Add(meta)

      meta =
New HtmlMeta
      meta.Name = "description"
      meta.Content = "default description"

      head.Controls.Add(meta)

      TargetPage.Title = "default page title"
    End If
  End Sub

 

Then all you have to do is call this procedure on the Page_Load event like so...

 

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

    GenerateMetaTags(Me)    

End Sub

 

..and you'll be up and running.  Now you have a convenient, central location where you can see and manage your site's meta-data.

SEO Best Practices - Dynamic Pages in ASP.NET

kick it on DotNetKicks.com

One of the greatest time-savers in web development is the use of dynamic pages to serve up database driven content.  The most common examples of which are content management systems and product information pages.  More times than not these pages hinge on a querystring parameter such as /page.aspx?id=12345 to determine which record needs to be retrieved from the database and output to the page.  What is surprising is how many sites don't adequatly validate that crucial parameter.

Any parameter that can be tampered with by a user, such as a querystring, must be validated as a matter of basic security.  That being said, this validation must also adequately deal with a situation when that parameter is not valid.  Whether the parameter is for a non-existant record, or whether the parameter contains letters where it should only be numbers, the end-result is the same: the expected page does not exist.  As simple as this sounds there are countless applications out there that seem to completely ignore any sort of error handling, and are content to have Server Error in "/" Application be the extent of their error handling.  Somewhere in the development cycle the developers of these application decided that the default ASP.NET error page would be the best thing to show to the site's visitors, and that a 500 SERVER ERROR was the ideal response to send to any search engine spiders that might have the misfortune of coming across a link with a bad parameter in it.

With a dynamic page that depends on querystring parameters to generate its content, the following basic measures should be taken:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load    
'Ensure that the requested URI actually has any querystring keys
If Request.Querystring.HasKeys() Then

'Ensure that the requested URI has the expected parameter, and that the parameter isn't empty
If Request.Querystring("id") IsNot Nothing Then

'Perform any additional type validation to ensure that the string value can be cast to the required type.

Else

Response.StatusCode = 404

Response.Redirect("/404.aspx",True)

End If

Else

Response.StatusCode = 404

Response.Redirect("/404.aspx",True)

End Sub


This is a basic example, but demonstrates how to perform simple validation against the querystring that will properly redirect anyone that reaches the page with a bad querystring in the request URL.  A similar approach should be taken when attempting to retrieve the data in the case that the record is not found.

Another useful trick is to define the default error redirect in the web.config file (<customErrors mode="RemoteOnly" defaultRedirect="/error.aspx">), and use that page to respond to the error appropriately by using the Server.GetLastError() method to get the most recent server exception and handling that exception as required.

There are many other ways to manage server responses when there is an error in your ASP.NET application.  What is most important is knowing that you need to handle these errors properly, up to and including an appropriate response to the request.   

Missing Link Data in Google Webmaster Tools

Late last night I noticed that the link data for my sites was missing in Google Webmaster Tools.  I assumed this was the result of some routine maintenance on Google's end and thought nothing of it.  Apparantly this may not be the case, as I came in to work this morning and discovered the the link data was still missing, and was also missing for every single one of our client's sites (both external links and internal links).

I'm not going to throw out wild theories about what Google is up to, but it will certainly be interesting to see if anything comes of this latest development.  If I had to hazard a guess, I would say the most likely explanation is an update of the link database.  However, when it comes to Google, as we all know, the only people that really know what's happening are the people at Google.

 

 

Windows Vista Disappearing System Tray Icons Fix

Yesterday I got out my laptop (which is running Vista Ultimate) to do some work on one of my websites.  When it loaded itself out of sleep mode I noticed that the battery, volume, and network icons in the system tray were missing:

 Naturally I was puzzled by this, and a little annoyed because I could no longer tell how much battery life was left (important because I like to get up and go sit on the deck while I work every so often).  First thing I did was check the Taskbar properties, and found something odd:

 

 

 As you can see in the above image, the checkboxes for the volume, network, and power icons are grayed out and not-selectable.  From my Windows development experience, I knew that Vista keeps a cache of recently used system tray icons in the registry, so on a hunch I popped open RegEdit and found where this cache is stored:

 

and the values

To make a long story short, I backed up the registry, deleted the "IconStreams" and "PastIconsStream" values, opened up the Task Manager, ended the "explorer.exe" process, restarted "explorer.exe" and just like that the missing icons had returned:



An odd problem, but thankfully one that is easily fixed. 

Edit (Added 01/28/2008):  It's worth trying to restart explorer.exe (see Step 4) before trying the registry modifications, because that may fix the problem on its own.


  1. Go to Start > Run (or Windows-key + "R"), type in "regedit" and hit "OK".



  2. Navigate to the key "HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion \TrayNotify"



  3. Delete the values "IconStreams" and "PastIconsStream"




  4. Now open up the Task Manager (Ctrl + Shift + Esc), go to the "Processes" tab, select "explorer.exe" and click "End Process"



  5. Now open the "Applications" tab and click "New Task..." at the bottom-right of the window.



  6. In the message box that pops up type in "explorer.exe" and hit "OK"



  7. Explorer.exe will reload, and that's it! The missing icons should now be back in the system-tray where they belong.





ASP.NET's Answer to WordPress

It's an exciting time to be an ASP.NET developer.  As the ASP.NET community continues to grow we find ourselves with an ever-increasing aresenal of tools, controls and frameworks at our disposal.  Unfortunately this can make the decision on a component a little more difficult, as very few of the components out there have reached that point where they are largely considered the "standard".  ASP.NET blogging engines certainly fall in to this category, as many of you have probably noticed.

 When I decided to create this blog I had some definite requirements in mind when it came to choosing a blog engine.  First and foremost it had to render completely valid XHTML because I practice what I preach in respect to W3C compliance.  Control over SEO-important aspects such as canonical URLs and meta descrition elements were a necessity.  It also had to have a URL strategy that didn't rely on a "/page.aspx?id=123456789"-style mess of a querystring. Finally, the underlying code had to be well-organized and lean.  Without a de-facto "standard" for ASP.NET blog engines I started hunting around and researching the options that were out there.

I tried some different ASP.NET blog engines such as dasBlog and subText, but found the markup that was rendered was not acceptable.  Then I came across BlogEngine.NET, which, I was thrilled to discover, met all of my requirements.  It's light weight, very easy to set up, and is very well-designed and organized under the hood.  A nice feature is that, by default, it doesn't require a SQL  database to run, instead storing all posts, comments and settings in local XML files.  Of course SQL database integration is available, and is also easy to get up and running.  Aesthetically it comes with a nice collection of themes, which are quite easy to modify, and creating your own themes is a straightforward process. 

The above factors have led me to believe that BlogEngine.NET is in a position to become to ASP.NET what WordPress is for PHP.  If any of you are currently trying to decide on a solid ASP.NET blog system you should definitely try BlogEngine.NET.  You won't be disappointed.