Page Validation, Browser Capabilities, and Alternative Content

Page Validation, Browser Capabilities, and Alternative Content

It is very easy to build your Web site in ASP.NET, perhaps using an IDE like Visual Studio, and test it only in your favorite browser. In fact, the built-in ASP.NET Web server and automatic launching of the pages in the default browser (Internet Explorer) does little to influence a change in this approach. However, this is a recipe for building browser-specific Web sites. It may even result in sites that are inaccessible to visitors using other browsers or specialist user agents.

It is true that there are only a few types of Web browsers in general use; at the time of writing this book, the bulk of hits on your pages are likely to be from Internet Explorer; Mozilla Firefox; any of a variety of Netscape browsers; and others such as Avant and Opera. All of these support the features required by ASP.NET, such as cookies (to provide support for ASP.NET sessions), client-side script (for link buttons, auto-postback, validation, etc.), and the standard set of HTML elements and CSS styles.

The best solution is to install as many of these browsers on your test system as you can (or run virtual machines) and test your pages in all of them. Doing this quickly reveals any issues that you must solve if you want to provide full support for all browser types. Also bear in mind that most browsers are available for different operating systems. The user may be running the browser on Unix or Linux, or on an Apple computer running a version of MAC-OS. While the browser manufacturers aim to provide the same appearance and enable the same behavior on different operating systems, this goal is not always achieved. The appearance of rendered output certainly varies considerably, so you should test your pages in these circumstances as well, if you can. If not, you may be able to solicit feedback and even screenshots from other users who have access to non-Microsoft environments.

You can obtain the latest browsers from these locations:

Validating Page Content

Visual Studio, by default, will check the content of your pages and show any issues by underlining the elements and attributes in Source view. This makes it easy to validate the content against a range of HTML and XHTML schemas. You can choose which level of conformance you require using the drop-down list in the Formatting toolbar. Figure shows how, when you select a legacy format such as HTML 3.2 for Internet Explorer and Netscape Navigator 3, content that is not valid against the current HTML 4.0 and XHTML schemas is acceptablethere are no warning underlines in the source code.

1. Validating HTML content against a legacy schema

However, with the default schema, XHTML 1.0 Transitional, warning underlines appear in your HTML source (see Figure). This schema forces stricter element and attribute structure that more closely conforms to XHTML standards, but it still permits the use of certain HTML 4 attributes.

2. Validating HTML content against the default XHTML Transitional schema

If you hover over the underlined elements and attributes, Visual Studio shows details of the validation failure and useful tips for fixing the problem. For example, in XHTML, a <form> element should not have the name attributeas you can see in Figure. However, (not visible in this monochrome screenshot), this error is flagged as a warning rather than an error (the underline is purple not red). In the XHTML 1.1 Strict schema, Visual Studio would flag it as an error.

3. A warning that the <form> element should not have the name attribute

Visual Studio flags other problems in the example as errors (with a red underline), and these must be fixed to make your page compatible with the selected schema. In Figure, you can see that the single-tag element for a horizontal rule must use the correct empty-element syntax of including a space and a closing backslash, as <hr /> to be considered valid. The same applies to the <input> element above it and to other elements such as <br />.

4. An error indicating a missing closing slash in an empty element

Other Validation Services

The Visual Studio editor does a good job of helping you write valid HTML; for example, it automatically adds the closing slashes for empty elements and forces you to use them on all ASP.NET Web Control declarations. It also performs some validation of other documents such as CSS stylesheets by providing pop-up lists of valid selector names and by checking the overall structure. However, if you prefer, you can use one of the many external validation services to check your pages and stylesheets.

The W3C provides both CSS and HTML validation services, and a Web search will locate plenty of others. The W3C CSS stylesheet validation service is at, while the W3C HTML validation service is at

XHTML Compliance

ASP.NET allows you to create pages that are compatible with the XHTML specification. While this book does not cover the XHTML standards, some of the effects of specifying the XHTML-compliant format for your pages affect not only the output rendered to the browser, but also the output from page templates. The major issues involved are the following:

  • Client script tags render without the language attribute and with the type attribute.

  • Hidden fields, such as those used by viewstate, render within a div element whose display attribute is set to none.

  • Input elements render within a block element, and therefore there is a div element immediately inside the form element.

  • The form name attribute only renders when the W3CDomVersion.MajorVersion property of the BrowserCapabilities class is greater than zero.

  • Special characters (such as ampersands, apostrophes, and angle brackets) are encoded in both the attributes and the query strings rendered by controls.

Note, however, that some controls you use in ASP.NET do not always create output that is strictly in conformance with XHTML 1.1. This is because the target attribute used in hyperlinks is not valid in XHTML 1.1. The controls where you can set the target attribute, such as the Hyperlink, BulletedList, ImageMap, and treeView, will produce XHTML 1.1 conforming output as long as you do not set properties such as Target that cause this attribute to appear.

Detecting Browser Capabilities

If you want to build pages that vary their content in some custom way depending on the type of browser each visitor is using, you must be able to detect the browser type or its capabilities within your code. ASP.NET automatically detects the browser type and provides output tailored to the current browser where possible. For example, a Panel control renders as a <div> for modern browsers, but as a single row, single column table for older browsers that may not support the <div> element.

You can hook into this browser detection mechanism, or influence the behavior of ASP.NET, in your pages. In Chapter 9, in the Specifying the Client Target section, you saw how you use the ClientTarget property of the Page class to specify behavior that overrides the default automatic browser detection process.

Browser Definitions

To detect the browser type, ASP.NET matches the USER-AGENT value sent to the server in the HTTP headers of a client request to a set of browser definition files stored in the Browsers subfolder of the main ASP.NET configuration folder. By default, this is:


The browser definition files follow the general format shown in Listing 14.1.

The General Format of a Browser Definition File

  <browser id="device-name" parentID="family-type-to-inherit-from">
      <!-- Specifies how to identify this browser -->
      <!-- Specifies additional HTTP header values to match -->
      <!-- Specifies capabilities values to set, for Figure>
      <capability name="cookies" value="true" />
      <!-- Specifies control adapters to use for this browser -->

There is a file named Default.browser that defines the default values and capabilities for the base browser type, and there are files for the more common manufacturer-specific values (such as Internet Explorer and Mozilla). The id and parentId attributes in each definition link them to each other, creating a hierarchy of inherited and version-specific settings relevant to each browser.

ASP.NET compiles all these files into a single compact representation when you install the Framework. If you update a definition, you can recompile them manually by running the aspnet_regbrowsers.exe utility installed along with the Framework. An interesting possibility arising from this is that automated updates to browser definitions will be much easier to implement and might even become part of the Framework update process in time.

You can also place browser definition files in the special folder named App_Browsers within your application root folder. Also, any browser definitions within a <browserCaps> element in a web.config file are recognized and merged into the final set of definitions used by the Framework. However, ASP.NET ignores any definitions in the machine.config file.

The BrowserCapabilities Class

Although the implementation and operation of the device detection system in ASP.NET is automatic, you can use it in your code to find out about the current browser and change the behavior of your pages, if required. The current Request instance (an HttpRequest) exposes an instance of the HttpBrowserCapabilities class through its Browser property. This means that you can write code that interrogates the browser capabilities properties; for example, this code returns the browser name and major version number of the current browser:

String details = Request.Browser("Browser")
               + Request.Browser("MajorVersion");

There are over a hundred properties for the HttpBrowserCapabilities class. Some are not relevant for common tasks, but the majority are useful for detecting all kinds of capabilities. For example, you can detect if a browser supports cookies, frames, color, sound, scripting, and more. For a full list of the properties of the HttpBrowserCapabilities class, see

Browser-Specific Pages and Sites, and Client-Side Code Support

One point to bear in mind is that the HttpBrowserCapabilities class simply provides information based on the contents of the browser definition files. This means that, for features that the user can turn on and off in their browser, you may not always get accurate results.

For example, the user may have disabled client-side scripting in VBScript and/or JavaScript, turned off display of images, or disabled cookies. If you rely on these features in your pages, you must implement more intrusive detection methods yourself, or use an alternative browser detection scheme. Third-party tools are available to perform browser detection. A good example is BrowserHawk, which automatically updates its own browser definition files to provide accurate detection of new browser types and new versions. It also detects if the user has disabled a range of common browser features. You can find BrowserHawk at

You can also create your own code to detect currently enabled capabilities such as cookies and client-side script. Code like this often relies on an initial page sent to the client (usually Default.aspx) that contains both a <meta> redirection directive and a client-side script redirection statement. Listing 14.2 shows the <head> section of a page containing a <meta> redirection directive to a page named no-script.aspx that causes the browser to load that page after three seconds. Below this is a client-side script section that contains a function to redirect the browser to the main page in your site. Finally, the opening <body> tag contains an onload attribute that causes the JavaScript function to execute and open the main site page when the Default.aspx page has finished loading:

<body onload="jumpScriptEnabled()">

If the user has disabled client-side scripting, the browser will load the no-script.aspx page, which can display a message indicating that clientside script is required for your site to work correctly. Alternatively, if you have a version of the site that works without client-side script, you could place this URL in the <meta> directive to redirect the user to that site. Another approach is to store a value in the user's session indicating that client-side script support is not available and then use this in your site pages to provide alternative features that do not rely on it.

Detecting if Client-Side JavaScript Is Enabled

<meta http-equiv="refresh" content="3;url=no-script.aspx" />
<script language="JavaScript">
function jumpScriptEnabled() {
// jump to page using client-side JavaScript - if jump not executed
// then client does not have scripting available or it is disabled
window.location.href = 'mainmenu.aspx';

It is also a good idea to include a <noscript> section in your page. Most browsers allow users to disable <meta> redirection, and some proxy servers can also prevent this. In these cases, when client-side script is disabled or unavailable, the browser automatically displays the contents of the <noscript> section, and you can use this to provide information and links to other sites.

Detecting Cookie Support

Most server-side programming environments depend on cookies to maintain a session for each user. Without this, some features of the ASP.NET framework and some server controls will fail to work correctly. In addition, if you store data in the user's session in your server-side code, you rely on cookie support in client browsers unless you take advantage of the cookieless session support feature in ASP.NET. Fortunately, in modern browsers, there are features that allow users to disable cookie support where it is undesirable (third-party cookies that originate in another site) but retain it for the current site.

However, you can quite easily detect if the current browser supports cookies by adding some simple code to your Default.aspx page. All this code has to do is set the value of a session variable, which you can then look for in subsequent pages. If it is not available, you know either that the user entered the site through another page or that the user does not have cookies enabled in his or her browser. Listing 14.3 shows a simple example that redirects the user to a page that requests enabling of cookies and that contains a link to the main site menu page. Alternatively, you could just redirect them to a version of your site that uses cookie-less sessions.

Detecting if Cookies Are Enabled

In Default.aspx:
<script runat="server">
Sub Page_Load()
  ' put value in session to check for cookie/session
  ' support by looking for it again in the next page
  Session("SessionCheck") = "OK"
End Sub

In your main site menu page:
<script runat="server">
Sub Page_Load()
  ' look for "sessions-enabled" cookie
  If CType(Session("SessionCheck"), String) > "OK" Then
  End If
End Sub

The cookie-less session feature in ASP.NET uses URL-munging (inserting the session ID into the URL automatically on each page request) to keep track of individual users and maintain their sessions. To enable cookie-less session support, you use the <sessionState> element in the <system.web> section of web.config to specify that ASP.NET should use cookie-less sessions:

<sessionState cookieless="true" />

For more details, see the section Cookie-less Sessions and Cookie-less Forms Authentication in Chapter 11.

CSS Support Quirks

While, in general, the later versions of all the mainline browsers support all the features required by ASP.NET, there are cases where support for CSS varies between browsers. For example, Internet Explorer and Mozilla vary from the W3C recommendations for CSS support in a few small areas, while Opera does not behave the same way as these two browsers for issues such as dynamic element positioning.

The differences between the behavior of a browser and the standards or recommendations are often referred to as "quirks." You can change the way that Internet Explorer 6.0 and later, Opera 7.0 and later, and Mozilla behave using an appropriate DOCTYPE declaration at the start of your pages. These browsers take into account the MIME type (such as "text/html" or "text/xml") that the server sends to the browser in the HTTP headers, and the document type declaration (DTD) and URL present in the DOCTYPE element.

If your page design or layout depends upon behavior caused by one or more of the quirks exposed by older browsers, you can specify this fact by omitting the DOCTYPE declaration or by using a DOCTYPE element and specifying a version of HTML prior to 4.0 or the transitional version of HTML 4.0 (a better solution):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

To trigger standards-compliant mode in modern browsers, you can use any of the following DOCTYPE elements:


If your pages are XHTML compliant, you can indicate this by using the appropriate DOCTYPE. This triggers standards-compliant mode in all modern browsers:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"

By default, Visual Studio automatically adds a DOCTYPE element to your pages that specifies partial XHTML compliance, using:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

For more information on the different modes, their effects in each browser, and the alternative ways that you can trigger each mode, see:

There is also a useful site called QuirksMode that provides side-by-side feature lists that show the differences between the modes in the mainstream browsers at:

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows