- Web Apps Stuck in the Past
- Guidelines, Rules, and Web Standards
- Microsoft ASP.NET Framework
- Content Management
- How To Approach Web Apps
Microsoft ASP.NET Framework
One framework that has gained massive adoption, particularly in large commercial enterprises, is Microsoft's critically acclaimed ASP.NET framework (the successor to "Classic" ASP). The .NET foundation classes, objects, and APIs are powerful.
ASP.NET enforces, by its model, layers of code that abstract database and program logic to a degree from "front end" files with the ASPX extension. These files are HTML and custom ASP.NET tags, which will be discussed later. In theory, UI coders learn these tags to control the front end with hooks for the programmers to use. This is certainly a possibility, but in reality is rarely done. The Web team would need to make a conscious decision to educate the UI team and collaborate on these efforts, and the UI team would have to be willing to learn. It could happen.
Typically, ASP.NET Web applications are created in an IDE called Microsoft Visual Studio.NET. This IDE has a WYSIWYG window that complements the programming view and allows programmers to rapidly drag form objects onto pages and set properties, including presentation attributes, without writing a line of code. These settings generate HTML.
From a Web standards standpoint, there are several issues that can be of concern with Visual Studio.NET, particularly versions earlier than 2005, and ASP.NET's server-generated code:
- Most ASP.NET examples, which everyone learns from, feature bad code.
- Visual Studio.NET 2003 and earlier was notorious for (when a programmer entered this design mode) rewriting and reformatting the HTML of the page in question, even if it was created and carefully crafted in another application or plain text editor by a UI coder.
- Form inputs and data controls can be ASP.NET "tags," which frequently have presentation attributes applied to them. The code output is often not valid XHTML or HTML code, although in version 2005 this situation improved greatly. These tag attributes output a massive amount of inline presentational attributes if the author does not make the extra effort to control the output.
- In versions 2003 and earlier, when an author uses the built-in tools to create a page, it creates HTML pages in quirks mode, because the DOCTYPE declaration applied to the document does not include a URI.
- ASP.NET features "adaptive rendering," which means the server makes decisions about what type of UI layer code to send to the Web browser based on server-side settings that "guess" the level of support a browser has for certain technologies.
- ASP.NET's server-side code makes great use of ID attributes on the controls embedded in the page code. Frequently, depending on the context, these IDs are dynamically renamed based on their location in the document, so CSS and JavaScript authors may have difficulty referencing page objects by their IDs even though that is the open, internationally recognized, standards-based way of doing things. In some cases a CSS class might be more appropriate, or trying to apply the required ID to a parent element and referencing the object by context. Ideally, front-end designers and backend programmers will collaborate on setting UI IDs in the best way to leverage the strengths of both front-end code and backend code—but this is not always the case.
It is interesting to note, however, that even these concerns can be mitigated with some extra effort, time, and attention to the front-end aspects of the code.
ASP.NET Data Output
Like other languages, ASP.NET features database output; however, one way Microsoft implements this is through its server-side tags. These tags all have presentation-related attributes that allow the programmer to control the XHTML presentation aspects of the output. Here is a typical sample of controls using an ASP.NET feature called a DataGrid control to output a table of items from a database. This code is embedded in an ASPX file surrounded by the rest of the document's (X)HTML (FIGURE 4.3).
Figure 4.3 An ASP.NET DataGrid control displaying data.
<asp:DataGrid ID="catalog" runat="server" AutoGenerateColumns="false" CellPadding="2" Width="600" BorderColor="black"> <ItemStyle Font-Names="Arial" Font-Size="12px" ForeColor="#800000" VerticalAlign="top" /> <AlternatingItemStyle Font-Names="Arial" Font-Size="12px" ForeColor="#400000" BackColor="#cccccc" /> <HeaderStyle Font-Bold="true" Font-Names="Arial" Font-Size="15px" ForeColor="white" BackColor="black" VerticalAlign="top" /> <Columns> <asp:BoundColumn DataField="Name" HeaderText="Name" /> <asp:BoundColumn DataField="abbr" HeaderText="Common Name" /> <asp:BoundColumn DataField="typeof" HeaderText="Tech Type" /> <asp:BoundColumn DataField="notes" HeaderText="Notes" /> </Columns> </asp:DataGrid>
This describes a data output table including alternating row colors. The attributes that describe the look and feel of the table are just some of the options that are available; the options are in fact extensive. The source of the data coming back is in another layer of code, an ASP.NET feature for separating data and presentation, which is, in theory a great idea. Here is the code the above sample generates:
<table cellspacing="0" cellpadding="2" rules="all" border="1" id="catalog" style="border-color:Black;width:600px;border-collapse: collapse"> <tr valign="top" style="color:White;background-color:Black; font-family:Arial;font-size:15px;font-weight:bold"> <td>Name</td><td>Common Name</td><td>Tech Type</td><td>Notes </td> </tr><tr valign="top" style="color:Maroon;font-family:Arial; font-size:12px"> <td>HyperText Markup Language</td><td>HTML</td><td>Markup </td><td>Used to markup documents. Loose syntax.</td> </tr><tr valign="top" style="color:#400000;background- color:#CCCCCC;font-family:Arial;font-size:12px"> <td>eXtensible HyperText Markup Language</td><td>XHTML </td><td>Markup</td><td>HTML as an XML syntax, XML-like strict rules.</td> </tr><tr valign="top" style="color:Maroon;font-family:Arial; font-size:12px"> <td>Cascading Style Sheets</td><td>CSS</td><td>Presentation </td><td>Separates design, look and feel information into separate documents from the markup.</td> </tr><tr valign="top" style="color:#400000;background- color:#CCCCCC;font-family:Arial;font-size:12px"> <td>JavaScript</td><td>JS</td><td>Behavior, Interaction, Events </td><td>Sometimes called the behavior layer, this controls user interaction, events, and behavior of Web pages.</td> </tr> </table>
The table is simple, with alternating colors and font family settings, and nicely uses CSS as opposed to <font> tags. However, this is a common sample of the code used in tutorials in describing DataGrid use. The CSS gets repeated inline within the generated code due to the use of the ASP.NET tagging attributes such as ForeColor, BackColor, and others. Additionally, the top row of content, which is intended to be a header row, is simply contained in <td> elements and is set as bold.
It is a shame, because ASP.NET does in fact feature the ability to assign CSS classes for most of these values, and in ASP.NET 2.0 there are features to generate <th> elements for headers. The CssClass attribute is available for most tags and there are others that allow classes to be assigned to tags in many scenarios. Note the UseAccessibleHeader attribute of the <DataGrid> element used below. It's too bad that programmers have to go out of their way to intentionally make the code accessible, but that is the nature of the beast—and it's fortunate the features are there in ASP.NET 2.0.
Here are the small adjustments that can be made to the ASP.NET code to improve the quality of the output:
<asp:DataGrid ID="catalog" runat="server" AutoGenerateColumns="false" CssClass="grid-class" UseAccessibleHeader="true"> <ItemStyle CssClass="item" /> <AlternatingItemStyle CssClass="item-alt" /> <HeaderStyle CssClass="item-header" /> <Columns> <asp:BoundColumn DataField="Name" HeaderText="Name" /> <asp:BoundColumn DataField="abbr" HeaderText="Common Name" /> <asp:BoundColumn DataField="typeof" HeaderText="Tech Type" /> <asp:BoundColumn DataField="notes" HeaderText="Notes" /> </Columns> </asp:DataGrid>
Pair the above code with CSS such as
.grid-class { border: 1px solid black; width: 600px; border-collapse:collapse; } .grid-class td { vertical-align: top; padding: 2px; border: 1px solid black; } .item { font: 12px arial, sans-serif; color: #800; } th { font: bold 15px arial, sans-serif; background-color: black; color: white; vertical-align: top; text-align: left; padding: 2px; } .item-alt { font: normal 12px arial, sans-serif; background-color: #ccc; }
In this case, the HTML table looks identical with a better, more Web standards approach to the same code. Here is the new XHTML output (FIGURE 4.4):
<table class="grid-class" cellspacing="0" rules="all" border="1" id="catalog" style="border-collapse:collapse"> <tr class="item-header"> <th scope="col">Name</th><th scope="col">Common Name</th> <th scope="col">Tech Type</th><th scope="col">Notes</th> </tr><tr class="item"> <td>HyperText Markup Language</td><td>HTML</td><td>Markup </td><td>Used to markup documents. Loose syntax.</td> </tr><tr class="item-alt"> <td>eXtensible HyperText Markup Language</td><td>XHTML </td><td>Markup</td><td>HTML as an XML syntax, XML-like strict rules.</td> </tr><tr class="item"> <td>Cascading Style Sheets</td><td>CSS</td><td>Presentation </td><td>Separates design, look and feel information into separate documents from the markup.</td> </tr><tr class="item-alt"> <td>JavaScript</td><td>JS</td><td>Behavior, Interaction, Events</td><td>Sometimes called the behavior layer, this controls user interaction, events, and behavior of Web pages.</td> </tr> </table>
Figure 4.4 The same ASP.NET <DataGrid>, with standards-based enhancements, looks the same.
Note the addition of the <th> tags (complete with a scope attribute), CSS classes on most elements including the alternating rows of color, and lack of (most) inline presentation. While the code is not perfect, it is a great improvement, with a small technique to improve the output. This sort of improvement requires front-end coders with knowledge of the backend, or backend programmers who know the front end.
There are a dozen or more options for tags to output ASP.NET database code. Sometimes, another tag altogether might be a better option because there is more control over what UI code is being produced. For instance, a Repeater control is a great choice for simple data output, as it defines an output loop with small templates of code an author can specifically set as she or he sees fit:
<asp:Repeater id="catalog" runat="server"> <HeaderTemplate> <table class="grid-class"> <tr> <th>Name</th> <th>Common Name</th> <th>Tech Type</th> <th>Notes</th> </tr> </HeaderTemplate> <ItemTemplate> <tr class="item"> <td><%#Container.DataItem("name")%> </td> <td><%#Container.DataItem("abbr")%> </td> <td><%#Container.DataItem("typeof")%> </td> <td><%#Container.DataItem("notes")%> </td> </tr> </ItemTemplate> <AlternatingItemTemplate> <tr class="item-alt"> <td><%#Container.DataItem("name")%> </td> <td><%#Container.DataItem("abbr")%> </td> <td><%#Container.DataItem("typeof")%> </td> <td><%#Container.DataItem("notes")%> </td> </tr> </AlternatingItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater>
The above code generates an HTML table as follows, and, paired with the same CSS as in the first example, is fairly clean, and free of even more unnecessary inline presentation attributes. While it is a little more code in terms of the Repeater tags, it does give more control of the output (FIGURE 4.5).
Figure 4.5 Using an ASP.NET Repeater control to render the same table with leaner code, while still looking the same.
<table class="grid-class"> <tr> <th>Name</th> <th>Common Name</th> <th>Tech Type</th> <th>Notes</th> </tr> <tr class="item"> <td>HyperText Markup Language </td> <td>HTML </td> <td>Markup </td> <td>Used to markup documents. Loose syntax. </td> </tr> <tr class="item-alt"> <td>eXtensible HyperText Markup Language </td> <td>XHTML </td> <td>Markup </td> <td>HTML as an XML syntax, XML-like strict rules. </td> </tr> <tr class="item"> <td>Cascading Style Sheets </td> <td>CSS </td> <td>Presentation </td> <td>Separates design, look and feel information into separate documents from the markup. </td> </tr> <tr class="item-alt"> <td>JavaScript </td> <td>JS </td> <td>Behavior, Interaction, Events </td> <td>Sometimes called the behavior layer, this controls user interaction, events, and behavior of Web pages. </td> </tr> </table>
This is a clean example of HTML code generated from ASP.NET server-side logic, showing that reasoned application of the features does provide some control of the output.
Looking over the tag-based code, it is obvious why Microsoft's pulling the application logic into other files and using these front-end ASPX files with tags is not a bad concept. Some front-end teams could certainly manipulate and modify this code without having to learn C# or Visual Basic.NET.
ASP.NET HTML Controls, Web Controls, and More
There are some other areas where ASP.NET commonly generates UI code for the programmers. Instead of sticking to simple HTML tags, ASP.NET has features that output HTML tags and provide server-side access to the document in ways quite similar to the DOM, although with their own proprietary syntax. Examine the following screen and code (FIGURE 4.6):
<script runat="server"> void Clicker(Object sender, EventArgs e) { Response.Redirect("http://www.cherny.com"); } void Page_Load() { if (!IsPostBack) { // Web Controls myLink.Text = "Pro Web Book Dot Com"; myLink.NavigateUrl = "http://www.prowebbook.com"; myLink.CssClass = "webControl"; // HTML Anchor Controls myOtherLink.InnerText = "NavigationArts"; myOtherLink.HRef = "http://www.navigationarts.com"; myOtherLink.Attributes.Add("class","htmlControl"); // Label Control myLabel.Text = "Hey Look! This span is meaningless!"; // Literal Control myLiteral.Text = " (A Bad Link!)"; // Paragraph HTML Control myPara.InnerHtml = "Pro Web Book " + "Links <strong>Rock!</strong>"; // Paragraph HTML Control 2 myPara2.Visible = false; } } </script> <form id="form1" runat="server"> <ul> <li><asp:HyperLink runat="server" id="myLink" /></li> <li><a runat="server" id="myOtherLink" /></li> <li><asp:LinkButton Text="Click This" OnClick="Clicker" runat="server" /></li> </ul> <p><asp:Label id="myLabel" runat="server" /></p> <p id="myPara" runat="server" /> <p id="myPara2" runat="server">This will be hidden.</p> </form>
Figure 4.6 Various ASP.NET server controls for outputting dynamic content.
There is a lot to look at here, to illustrate a number of different points:
- The whole thing must be a <form> element with runat=server in order to use the <asp:LinkButton /> control. This control should be avoided if possible, as will be seen in a moment when the resulting XHTML is examined.
- Note the first ASP.NET server tag in the unordered list is in the form of <asp:HyperLink />. This is a Web Server Control that generates an HTML link and provides program access to all the attributes and text of the tag, as demonstrated in the <script> block above where the myLink references are located.
- Note the second link has no href attribute and is also programmatically controlled from the <script> block above. This is a server-side HTML control (note the runat=server attribute) that also allows programmatic access to the item's attributes. This grants more control over the output but fewer server-side features.
Adding an ID and the code runat=server to just about any HTML tag provides access to the tags, which is exceptionally powerful because programmers can control the tag's visibility, content, and attributes with a few lines of code, located at the programming layer.
Both link controls do virtually the same thing, and while the Web controls provide added features over and above the HTML controls, the Web control is less predictable and features presentation attributes frequently used by programmers after the quick fix. When using Web controls, programmers should try to stick to the CssClass attributes, avoid presentation attributes, and use HTML controls for greater predictability in the code output, unless it is necessary for the specific case.
Keep watching the paragraphs at the end of the document:
<p><asp:Label id="myLabel" runat="server" /></p> <p id="myPara" runat="server" /> <p id="myPara2" runat="server">This will be hidden.</p>
These are all executed server-side as well.
The <script> is the server-side code that is not sent to the browser, and frequently this code is in a separate file altogether. It programmatically generates the following XHTML (aside from some other .NET code that is meaningless to this discussion):
<script type="text/javascript"> <!-- var theForm = document.forms['form1']; if (!theForm) { theForm = document.form1; } function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } // --> </script> <ul> <li><a id="myLink" class="webControl" href="http://www.prowebbook. com">Pro Web Book Dot Com</a></li> <li><a href="http://www.navigationarts.com" id="myOtherLink" class="htmlControl">NavigationArts</a></li> <li><a href="javascript:__doPostBack('ctl00','')">Click This</a> </li> </ul> <p><span id="myLabel">Hey Look! This span is meaningless!</span> </p> <p id="myPara">Pro Web Book Links <strong>Rock!</strong></p>
Some more observations about the code output:
- Note that there are several ways to output a simple link in ASP.NET: the first two as described above with Server and HTML controls and another that creates the third link, the <asp:LinkButton /> control.
- The third link code generated above demonstrates why it is best to avoid using the <asp:LinkButton /> control under most circumstances, as it produces an href attribute with a JavaScript link, which breaks every rule in this book.
- The <asp:Label /> control used in the first paragraph above outputs a <span> for no reason. The label control is considered nice because programmers can assign presentation aspects to it, but it is possible to use the <asp:Literal /> control instead, which outputs the lovely message "(A Bad Link!)" above. It is often claimed that one downside to using this control is that there are no presentation aspects for it—which is exactly why using it is a great idea.
- Programmers can also control the text of tags with HTML controls for paragraphs, as demonstrated by the paragraph above with the ID of myPara.
- Note that programmers can also hide and show HTML controls: The last paragraph in the server-side code is set to visible = false and not sent to the browser.
HTML controls offer ASP.NET code a lot of power, but for various reasons ASP.NET tutorials downplay their use. From a Web standards perspective, however, these are very powerful tools and often preferable to Web server controls.
Server-Side Collaboration with UI Designers
The bottom line is that programmers, developers, and designers should collaborate as closely as possible when programming server-side applications, to make sure the UI markup follows Web standards-based best practices. This often means picking the right tool on the server. Keep the UI out of the application and use classes and clean code; this keeps the design in the hands of the UI team, reducing risk and the potential need to involve a programmer just for a UI change. When applications are complex or based on older code bases, compromises may be necessary, but ultimate goals, standards, and guidelines should be set toward the goal of bringing consistency in the long run.