About Links Archives Search Feed Albums of Note


ASP.NET, Part 9: Rendering Cleaner HTML

Welcome to part 9 of my tour through ASP.NET 4.0 [http://blog.hmobius.com/post/2010/02/09/ASPNET-40-Cometh.aspx]. In this episode, we’ll conclude our look at the ways that ASP.NET has been tweaked in v4.0 to produce cleaner, leaner HTML that we can turn to our purpose without having to deal with some of the inconveniences of previous versions – control IDs and injected HTML we can’t control being two. More control over viewstate being a third.

ASP.NET 2.0: Only Technically Standards Compliant… Even in 2005, the idea of producing pure HTMLwebsites had gained quite a foothold. XHTML had been a W3C Recommendation since 2001 and CSS was evolving and being used more prevalently. Sites like CSS Zen Garden [http://www.csszengarden.com] had been championing cross-browser sites and advanced layouts with this approach for a couple of years. All it required was control over the HTML generated by your site and some reasoned application of CSS.

Regrettably, ASP.NET 1.1 didn’t produce standards-compliant HTML at all, so ASP.NET 2.0 created a new setting in web.config called xhtmlConformance [http://msdn.microsoft.com/en-gb/library/ms228268(loband).aspx] that would determine how its server controls were to be rendered as HTML. By default, controls would render markup compatible with the XHTML 1.0 Transitional standard (Transitional). Alternatively, the setting could be changed to have ASP.NET render markup compatible with XHTML 1.0 Strict (Strict) or as v1.1 (Legacy) has rendered it before. Websites upgraded from v1.1 to v2.0 were set to this Legacy mode.

Unfortunately, sites running in Legacy mode didn’t work with ASP.NET AJAX [http://weblogs.asp.net/scottgu/archive/2006/12/10/gotcha-don-t-use-xhtmlconformance-mode-legacy-with-asp-net-ajax.aspx] and while Transitional and Strict modes were technically compliant with the XHTML 1.0 standard, they could equally have been described as CSS-intolerant.

Technically correct, but not a good foundation to build standards compliant sites upon. The introduction of the ListView [http://msdn.microsoft.com/en-gb/library/system.web.ui.webcontrols.listview.aspx] & DataPager [http://msdn.microsoft.com/en-gb/library/system.web.ui.webcontrols.datapager.aspx] controls in ASP.NET 3.5 and the out of band CSS Control Adapters [http://www.codeplex.com/cssfriendly] release helped somewhat but it’s only because they’ve been able to go into System.Web for .NET 4.0 that Microsoft have been able to make ASP.NET (mostly) CSS-friendly. Indeed, emitting cleaner markup was one of the main goals for ASP.NET 4.0

ControlRenderingCompatibilityVersion Like xhtmlConformance in ASP.NET 2.0, a new setting is now available in web.config to control how controls render HTML. It is called ControlRenderingCompatibilityVersion.

<system.web> <pages controlRenderingCompatibilityVersion=“3.5” />

</system.web>

CRCV, as we’ll call it, takes one of two values. Set it to 3.5 (the default for sites upgraded from ASP.NET 3.5) and all server controls will render as they did in ASP.NET 3.5. Set it to 4.0 (the default for new web site and web application projects) and the following happens

Let’s look at these changes in detail.

Menus Let’s consider a very simple menu control with three items.

With CRCV set to 3.5, we get three CSS styles for the menu added to the HTML

, 53KB of script files added in by two calls to WebResource.axd (21KB for the standard script to handle postbacks, 32KB for a menu-specific script file), and the following HTML for the menu itself.

Skip Navigation Links
       </tr>         </table>       </td>     </tr>     <tr onmouseover="Menu_HoverStatic(this)" onmouseout="Menu_Unhover(this)"        onkeyup="Menu_Key(this)" id="testMenun0">       <td>         <table cellpadding="0" cellspacing="0" border="0" width="100%">           <tr>             <td style="white-space:nowrap;width:100%;">               <a class="testMenu_1" href="#">Menu Item 2</a>             </td>           </tr>         </table>       </td>     </tr>     <tr onmouseover="Menu_HoverStatic(this)" onmouseout="Menu_Unhover(this)"        onkeyup="Menu_Key(this)" id="testMenun0">       <td>         <table cellpadding="0" cellspacing="0" border="0" width="100%">           <tr>             <td style="white-space:nowrap;width:100%;">               <a class="testMenu_1" href="#">Menu Item 3</a>             </td>           </tr>         </table>       </td>     </tr>   </table>   <a id="testMenu_SkipLink"></a>   </div>    <script type="text/javascript">      //<![CDATA[     var testMenu_Data = new Object();     testMenu_Data.disappearAfter = 500;     testMenu_Data.horizontalOffset = 0;     testMenu_Data.verticalOffset = 0;     //]]>   </script> </body>
With CRCV set to 4.0, we get six CSS styles added to the

element, a single 27KB script file downloaded to the browser (a completely refactored version of the menu script) and the following HTML for the menu.

 <a href="#testMenu_SkipLink">     <img alt="Skip Navigation Links" width="0" height="0" style="border-width:0px;"        src="/CleanHtml/WebResource.axd?d=y4UEb5xFzNnwyKsjxERYdw2&t=634013486901596851" />     </a>     <div id="testMenu">     <ul class="level1">       <li><a class="level1" href="#">Menu Item 1</a></li>       <li><a class="level1" href="#">Menu Item 2</a></li>       <li><a class="level1" href="#">Menu Item 3</a></li>     </ul>     </div>     <a id="testMenu_SkipLink"></a>   </div>   <script type='text/javascript'>     new Sys.WebForms.Menu({        element: 'testMenu',        disappearAfter: 500,        orientation: 'vertical',        tabIndex: 0,        disabled: false });   </script> </body>
As you can see, not only is the rendered HTML semantically correct, the overall payload is smaller as well. Indeed you can reduce it further by setting the Menu control’s IncludeStyleBlock property to false. This will remove the six styles added to the

element for you to include in your own CSS files. Finally, note that you can set the Menu control’s RenderingMode property to either List, Table or Default. This will override the CRCV setting and render the menu as either List or Table as you’ve set it.

Extraneous HTML The Image control is a good example of a control that in ASP.NET 3.5 added a property to the emitted HTML that wasn’t asked for and couldn’t be overridden. Take a very simple declaration

With CRCV set to 3.5, ASP.NET sets the image’s border-width to 0px.

With CRCV set to 4.0, there’s no sign of the style property at all.

Other controls, such as Table and GridView are similarly shed of their extraneous properties.

Removing The Outer Table From Some Composite Controls For the most part, ASP.NET controls will render the HTML you want them to, but it looks like some of the more complex, composite controls haven’t been ‘sanitized’ in the same way as more commonly used controls such as the Image or DropDownList. However, it is worth noting that some of these controls now have a new property called RenderOuterTable which does address one particular markup issue. These are

  • FormView * Login * ChangePassword * PasswordRecovery

Take for example the Login control.

Whether CRCV is set to 3.5 or 4.0, the default markup is the same.

Menu Item 1
     </tr>         <tr>           <td align="right">             <label for="loginTest_UserName">User Name:</label>           </td>           <td>             <input name="loginTest$UserName" type="text" id="loginTest_UserName" />             <span id="loginTest_UserNameRequired" title="User Name is required."                style="color:Red;visibility:hidden;">*</span>           </td>         </tr>         <tr>           <td align="right">             <label for="loginTest_Password">Password:</label>           </td>           <td>             <input name="loginTest$Password" type="password" id="loginTest_Password" />             <span id="loginTest_PasswordRequired" title="Password is required."                style="color:Red;visibility:hidden;">*</span>           </td>         </tr>         <tr>           <td colspan="2">             <input id="loginTest_RememberMe" type="checkbox" name="loginTest$RememberMe" />             <label for="loginTest_RememberMe">Remember me next time.</label>           </td>         </tr>         <tr>           <td align="right" colspan="2">             <input type="submit" name="loginTest$LoginButton" value="Log In"                onclick="…" id="loginTest_LoginButton" />           </td>         </tr>       </table>     </td>   </tr> </table>

A CSS-related issue with this in earlier versions of ASP.NET is the outer table which you haven’t previously been able to remove (but which ironically was added as a wrapper in to give you better control over your styles). Set the Login control’s RenderOuterTable property to false and this will lose that table no matter what CVCR is set to.

Log In
 <td>       <input name="loginTest$UserName" type="text" id="loginTest_UserName" />       <span id="loginTest_UserNameRequired" title="User Name is required."          style="color:Red;visibility:hidden;">*</span>     </td>   </tr>   <tr>     <td align="right">       <label for="loginTest_Password">Password:</label>     </td>     <td>       <input name="loginTest$Password" type="password" id="loginTest_Password" />       <span id="loginTest_PasswordRequired" title="Password is required."          style="color:Red;visibility:hidden;">*</span>     </td>   </tr>   <tr>     <td colspan="2">       <input id="loginTest_RememberMe" type="checkbox" name="loginTest$RememberMe" />       <label for="loginTest_RememberMe">Remember me next time.</label>     </td>   </tr>   <tr>     <td align="right" colspan="2">       <input type="submit" name="loginTest$LoginButton" value="Log In"          onclick="…" id="loginTest_LoginButton" />     </td>   </tr> </table>

Not ground-shattering certainly, but definitely handy.

What We’ve Learnt In today’s episode, we’ve learnt that Microsoft has taken the opportunity in ASP.NET 4.0 to clean up a great deal of the HTML emitted by its server controls, thus making it CSS-friendlier. A new setting in web.config called ControlRenderingCompatibilityVersion indicates whether controls should render as cleaner HTML or as they did in 3.5. We saw two example of the cleaner HTML in effect in the Menu and Image control and noted that while some of the more complex controls have not had their markup cleaned up, a subset of those now have a RenderOuterTable property which allows you to remove some of it manually.

Incidentally, for those of you with sites that you can’t upgrade to .NET 4.0, a group of enterprising souls are continuing to work on the CSS Friendly Adapters mentioned earlier. You’ll find this revitalization here on Google Code [http://code.google.com/p/aspnetcontroladapters/]. Happy coding!

Log In
Posted on March 3, 2010   #ASP.NET     #Geek Stuff  






← Next post    ·    Previous post →