ASP.NET has never exactly enjoyed a warm relationship with the web standards crowd. Mention “Web Controls” in certain company and you can practically hear the knives being sharpened.
To be fair, much of the criticism is deserved. ASP.NET has spent years enthusiastically generating markup that no sane human being would write by hand. But things aren’t entirely hopeless. With a little effort, some configuration and the willingness to occasionally fight the framework, you can make the output slightly less offensive.
ASP.NET 1.1
Let’s get the unpleasant business out of the way first. ASP.NET 1.1 is pretty much beyond salvation. Hopefully most people have abandoned it by now. It was released in 2000, when Internet Explorer ruled the earth, table layouts were considered perfectly reasonable and web standards were apparently something that happened to other people.
The Web Controls mostly generate invalid XHTML. There are ways around this (more on this later), but none of them are particularly elegant. Stay away from Design mode as well. It has an alarming tendency to rearrange your markup without asking, like an overenthusiastic hotel maid who decides your passport would look better in another room.
Turn off adaptive rendering to avoid generating different code for different browsers (which is always a bad idea) and reduce ViewState if you don’t actually need it. There is little reason to ship a small novel back and forth between browser and server simply because ASP.NET thinks you might need it later.
ASP.NET 2.0
ASP.NET 2.0 is better. This is admittedly a low bar. One improvement is that Design mode no longer spontaneously rewrites your markup. You should probably still stay away from it, but at least it has stopped actively vandalising the premises.
Most Web Controls now produce markup that validates, although “valid” should not necessarily be confused with “good”. Custom Web Controls, for example, automatically wrap themselves in <span> elements, occasionally producing charming little constructions where block elements end up inside inline elements (which is invalid).
Then there’s JavaScript. Some controls generate obtrusive JavaScript, and plenty of .NET machinery relies on the generated “javascript:__doPostBack” event. In plain English, this can cause the page to fail checkpoint 6.3 of WCAG 1.0, which is a Level A requirement. Not ideal.
And then we come to the classic tables. Controls such as MenuView, TreeView and DetailsView happily generate layout tables by default, violating checkpoint 5.3 of WCAG 1.0, a Level AA requirement. Somewhere, a standards advocate quietly pours another stiff drink.
If you’re wondering why empty alt attributes mysteriously disappear, you need to activate GenerateEmptyAlternateText. And if you’ve ever looked at the source and wondered who named your perfectly respectable control “ctl00_MainContent_Something”, congratulations: you’ve met ASP.NET’s talent for turning simple IDs into something resembling evidence from a criminal investigation.
Fortunately, there are ways out. You can write your own controls. You can use HTML Controls instead of Web Controls. You can intercept the markup before it reaches the browser and clean up the wreckage yourself. Or, if writing your own controls sounds like an unnecessarily intimate way to spend an evening, there are CSS Adapters (more on this below).
XHTML conformancy
ASP.NET 2.0 emits XHTML 1.0 Transitional by default. You can’t select a Strict DOCTYPE directly from the IDE, because apparently that would have been too convenient. You can however configure ASP.NET’s rendering through the xhtmlConformance element in web.config:
The available modes are Legacy, Transitional and Strict. And yes, it has to be Strict, with a capital S. At least some MSDN documentation says “strict”. Follow that advice and ASP.NET rewards your obedience with a ConfigurationErrorsException. It’s the sort of tiny detail that makes software development such a relaxing profession.
Also note that migrating an ASP.NET 1.1 site to ASP.NET 2.0 may enable Legacy mode. This disables partial-page updates when using ASP.NET AJAX UpdatePanel controls, giving you another small archaeological mystery to solve.
App_Browsers
Another weapon in the fight against unwanted markup is the App_Browsers folder. It contains browser definition files that ASP.NET uses to identify browsers and determine their capabilities, replacing the old browserCaps element. These .browser files use the Browser Definition File Schema.
There’s a particularly entertaining problem here: ASP.NET doesn’t recognize the W3C Validator properly and may therefore serve it legacy markup. So the validator arrives to check whether your page contains valid markup, and ASP.NET responds by deliberately giving it worse markup. You couldn’t make this stuff up.
One solution is to add a w3cvalidator.browser file to App_Browsers, allowing ASP.NET to recognize the validator and behave itself while the inspector is in the building.
CSS Adapters
The CSS Friendly Control Adapters provide another approach. They change how ASP.NET controls render, producing output that’s considerably friendlier to CSS and standards-based layouts. Rather than intercepting and rewriting the final markup, they participate directly in the rendering phase, which keeps the process relatively efficient. They also use the .browser files mentioned above.
They’re not without problems. The adapters rely on JavaScript postbacks, and there have been reports of double postbacks with certain controls. The first postback changes the control state. The second arrives immediately afterwards, discovers that reality has shifted beneath its feet and throws an error. Good times.
Still, something like CSS Friendly Control Adapters really ought to have been the default behavior of Web Controls in the first place. Very few .NET developers are going to write custom adapters merely to stop the framework from producing terrible markup. They have deadlines, families and presumably other things they’d like to do before death.
CSS Adapters aren’t perfect. Nothing involving ASP.NET Web Controls ever seems to be. But they’re considerably better than accepting the vanilla output and pretending not to look at the source. For more details, have a look at Creating CSS Control Adapters.
Related posts
4 comments
Leave a reply