ASP.NET 2.0执行 Web 标准以便更加易于访问


本文示例源代码或素材下载

  本文讨论:

  采用 Web 标准

  CSS 控件适配器

  ASP.NET 2.0 主题和母版页

  本文使用了以下技术:

  ASP.NET 2.0

目录

  采用 Web 标准

  XHTML 的风格

  ASP.NET 2.0 作为 Web 标准平台

  CSS 控件适配器

  母版页和主题

  请求

  我不得不承认我一开始并不觉得 Web 标准很重要。和大多数人一样,我也是在 Web 浏览器刚出现时就开始编写网页了。那时,我认为闭合每个 HTML 段落标记会降低我的工作效率,而且会不必要地占用用户那宝贵的 28K 的部分带宽。所以,我不闭合它。只要浏览器能通过,我也不在乎。

  但是,自那时起我开始认识到 Web 标准对未来 Web 和基于 Web 的软件的普遍重要性。当然,Web 标准远不只是闭合 HTML 标记这么简单。它们关系着软件组件是否能很好地应用于未来的内容。

  此外,为了遵循 W3C 标准的 XHTML、级联样式表 (CSS)、XML 等标准,Web 应用程序应友好地支持搜索引擎、可访问性好、具有易懂的 URL 并采用其他公认的做法,从而更便于查找和使用。Web 标准还要求特别注意站点的代码结构,以便将来更容易维护。在本文中,我将解释为什么所有人,特别是编写服务器控件的编程人员都应遵循 Web 标准。

  采用 Web 标准

  Web 标准的影响可分为四大类:代码的合法性、站点导航、可访问性以及内容与设计的分离,如图 1 所示。如果您解决了这些类别中的重大问题,那么就生成了基本上符合标准的代码。让我们逐个了解每个类别。

Figure1Web 标准的分类

标准 说明
代码合法性 根据 W3C 标准,网站必须使用合法的 XHTML 和 CSS,并且格式正确。这将确保获得浏览器尽可能的支持、呈现速度更快并使代码更容易理解。
站点导航 网站应有具有站点地图和 URL 友好的分层结构。用户应能够根据 URL 确定他们在站点中的位置。
可访问性 网站必须便于残障用户使用,并应可以通过各种浏览器和设备进行访问。
内容与设计的分离 网站必须使用样式表来定义布局和表示形式(用 XHTML 表示内容)。

  XHTML)和 jigsaw.w3.org/css-validator (用于 CSS)。可以将这些服务作为您的构建过程的一部分自动运行,也可以在部署代码之前手动执行。

  大多数浏览器都逐渐地遵循 Web 标准。对于在 2006 年底发布的 Internet Explorer? 7.0 和 Mozilla Firefox 2.0 而言正是如此。所以,在遵守它们强制的 Web 标准时,您可以更加自信您的代码将正确地呈现在当前浏览器中。

  站点导航 很多内容管理系统将内容内部化并提供页面 URL,而这些页面 URL 不会为用户提供有关页面与站点其余部分之间关系的任何线索。此外,动态创建的内容通常会生成不友好的 URL,因为诸如唯一标识符之类的信息通常会包含在 URL 中通过查询字符串传递。为了弥补这些不足,应根据主题组织 URL 并向用户显示其位置。通过 URL 重写,您可以获得动态生成内容的友好 URL,在处理 HTTP 请求时,HTTP 模块将不友好的 URL 映射到友好 URL。Microsoft? .NET Framework 支持 URL 重写。友好的 URL 还使您的内容更容易被搜索到,某些搜索引擎实际上会将具有友好 URL 的页面的排名提前。

  可访问性 对于一个企业而言,生成或呈现残障人士可以方便使用的代码就如同建造轮椅通道一样重要。您不无法预知所有可能访问您的网站的用户中是否有残障人士。例如,男性中有百分之五到百分之十是色盲。幸运的是,有一些方便的做法可以使对网站的访问更加容易。避免使用表格,原因是为视力受损用户用于读取屏幕内容的屏幕读取器会混淆表格布局。可访问性强的窗体也很重要。我很后悔曾经创建了一个两列表格,一列是标签,另一列是 HTML 窗体元素。正确的方法是定义一个具有“for”属性的标签,该属性指明了标签描述的窗体元素的 ID(请参见图 2)。

Figure2一个可访问性强的窗体

<form id="FormAccessible" runat="server">
  <fieldset>
    <legend>Personal Information</legend>
    <p>
      <label for="TextFirstName">First Name</label>
      <asp:TextBox ID="TextFirstName" runat="server"
        AccessKey="f" TabIndex="0" />
    </p>
    <p>
      <label for="TextLastName">Last Name</label>
      <asp:TextBox ID="TextLastName" runat="server"
        AccessKey="l" TabIndex="1" />
    </p>
  </fieldset>
  <fieldset>
    <legend>Contact Information</legend>
    <p>
      <label for="TextEmail">Email</label>
      <asp:TextBox ID="TextEmail" runat="server"
        AccessKey="e" TabIndex="2"/>
    </p>
  </fieldset>
</form>

  其他提高可访问性的方法包括为重要内容(例如,链接和按钮)选择易于区分的颜色、确保在放大字体(允许放大)时页面的可读性以及使用 alt 属性描述图像。使用 alt 的同时还有一个好处,就是搜索引擎可以为描述建立索引。

  最后,将站点设计为具有更大的设备无关性,这就意味着更多人可以访问该站点。毕竟,用户的手机、PDA、Smartphone 和其他设备现在都可以访问网站。由于无法在移动设备上访问站点而不能访问需要的数据,这会让他们非常失望。

  内容与设计的分离 早在 XML 成为如今的通行标准之前,网页就已经存在了。出现 XML 之后,内容和设计之间就有了严格的区分,因为 XML 不像 HTML 那样轻易允许样式信息与内容纠缠在一起。

  这种分离的好处有很多。将所有布局和样式信息保存在 CSS 样式表中,这样可以支持多种设备。并使得发出的 XHTML 更小。XHTML 更简洁、组织性更好,有助于进行编辑和调试。XHTML 的简洁性还使屏幕读取器更容易读取网页内容,并允许搜索引擎更准确地为页面建立索引。

  XHTML 的风格

  在强调了 Web 标准的重要性之后,现在我们来创建一些页面来实现这些标准。第一步是选择正确的文档类型。文档类型定义 (DOCTYPE) 会告诉浏览器的验证程序您使用的是哪种类型的 XHTML。XHTML 1.0 有三种风格:Strict、Transitional 和 Frameset。XHTML 1.1 只提供了一种风格,这限制了被认为直观的 HTML 元素的使用。图 3 列出了这些类型。

Figure3XHTML 文档类型

版本 语法 说明
XHTML 1.0 Strict <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 仅支持在 HTML 4.01 中定义的元素和属性,并遵循 XML 语法规则。
XHTML 1.0 Transitional <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 支持某些不推荐使用的元素和属性,这些元素和属性(例如 <center> 和 <u>)被认为是用于演示的。
XHTML 1.0 Frameset <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> 支持使用 <object> 或 <iframe> 元素的框架。一般而言,不建议使用 iframe。
XHTML 1.1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 //EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 最新的 W3C 建议删除所有被认为是用于演示的元素。

  最好使用 XHTML 1.1 或 HTML 1.0 Strict DocType,因为它们有助于确保所有直观元素从 XHTML 中迁移到样式表中。但是,请注意符合这些类型并不确保页面完全符合 Web 标准,因为仍然允许使用 XHTML 表格来定位内容;所以,您不能完全依赖合法性,因为合法性不会仅仅由于使用了表格而出现故障。

  应在您无法从代码中完全清除所有直观元素时,使用 Transitional DocType。它应该用来表示页面不是完全符合标准,需要以后进行重构。

  XHTML 1.0 规范支持框架,但 XHTML 1.1 不支持。将来,对 iframe 和对象的使用可能被 XFrame 规范取代。由于可用性方面的原因,现在普遍禁止包含框架。如果您曾经单击过具有框架的网页上的“返回”按钮,您会明白我的意思。

  ASP.NET 2.0 作为 Web 标准平台

  ASP.NET 1.1 中有一些人所共知的不足。可以直接使用的控件生成的代码不会传递合法性。这主要是由于 ASP.NET 1.1 中处理 ViewState 的方式造成的 – 使用块显示中未包含的隐藏输入标记,如下所示:

<input type="hidden" name="__VIEWSTATE"
value="dDwtMTU1NzQzNDgy..." />

  此问题和其他一些语法问题使 ASP.NET 1.1 有了一个兼容性不够好的坏名声。

  ASP.NET 2.0 解决了很多 Web 标准问题。例如,如果看一下由 ASP.NET 2.0 生成的页面的源代码,您会发现 ViewState 现在包装在 div 标记中(使其兼容):

<div>
  <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
      value dDwtMTU1NzQzNDgy..." />
</div>

  Microsoft 公开表示 ASP.NET 2.0 的目标之一是更好地与 Web 标准一致,实际上,您可以用 ASP.NET 2.0 创建兼容的网站和控件。创建兼容网站的一个好资源是 Stephen Walther 的 MSDN? 文章“使用 Web 标准创建 ASP.NET 2.0 网站”。这篇 78 页的文章详细介绍了依照 Web 标准创建站点的方法。

  CSS 控件适配器

  尽管 ASP.NET 2.0 在兼容性方面有了很大进步,但是仍有一些问题需要解决。例如,某些 ASP.NET 2.0 控件在不该呈现为 HTML 表格时,却呈现为 HTML 表格。在某些情况下,由于控件本身是表格数据,所以诸如 GridView 或 DataList 之类的控件应在表格中呈现输出。其他控件(例如,菜单控件)则不应呈现为表格。图 4 显示了呈现为菜单控件的菜单项的 HTML 表格的一部分。该表格及其多个样式属性使该代码并非最佳代码。

Figure4默认菜单 HTML 输出

<table id="ctl00_menuTop" class="ctl00_menuTop_2"
    cellpadding="0" cellspacing="0" border="0">
 <tr onmouseover="Menu_HoverStatic(this)"
   onmouseout="Menu_Unhover(this)"
   onkeyup="Menu_Key(this)" id="ctl00_menuTopn0">
  <td>
   <table cellpadding="0" cellspacing="0" border="0" width="100%">
    <tr>
     <td style="white-space:nowrap;width:100%;">
      <a class="ctl00_menuTop_1"
        href="http://Msdn.WebStandards/Default.aspx">Main Page</a>
     </td>
     <td style="width:0;">
      <img src="/Msdn.WebStandards/WebResource.axd?d=hnH9bjBrxucw46WA5Xha0Kh9gZ-YF67wSyd4b51QsEc1&amp;t=632962190992968750"
         alt="Expand Main Page"
         style="border-style:none;vertical-align:middle;" />
     </td>
    </tr>
   </table>
  </td>
 </tr>
</table>

  由于在表格中的数据通常不是表格时 HTML 呈现为表格,所以认为此代码不符合 Web 标准。使用 HTML 表格呈现一列菜单项,就像使用 DataSet(而不是通常使用的字符串阵列或集合)来处理一个作业一样。呈现此类分层数据的可行方法是使用 HTML 无序列表,如果您把菜单当作一系列嵌套列表就容易理解了。

  幸运的是,Microsoft 发布了 ASP.NET 2.0 CSS 友好控件适配器 1.0 工具包,使您可以覆盖控件的默认输出以便在控件呈现时删除、替换或注入 HTML。经过几次反复测试之后,Microsoft 发布了该工具包,您可以从 asp.net/CSSAdapters/Default.aspx 下载。

  CSS 控件适配器使您可以在不修改控件源代码的情况下,重写任何控件输出的功能,而不管控件是随 ASP.NET 2.0 提供的、由第三方提供的还是自定义的。作为开发人员,您不会拥有全部所用控件的源代码;即使有,修改源代码并不总是重写功能的最佳方法。如果您需要修改的只是呈现的 HTML,那更是如此。

  驱动控件适配器的体系结构是基于适配器或包装设计模式构建的。抽象类 ControlAdapter 定义了所有适配器的基本功能。WebControlAdapter 类在添加用于呈现各个 HTML 标记的方法的同时,继承了 ControlAdapter 功能。菜单适配器等类从 WebControlAdapter 继承而来,以便提供针控件专用的功能。图 5 显示了控件适配器的类关系图。

  图 5ASP.NET 2.0 控件适配器类

  此体系结构的实现非常简单,对于已经开发了适配器的控件而言尤为如此。幸运的是,几乎所有 ASP.NET 控件都有适配器。在所示的示例中,MenuAdapter 类用于替代具有无序列表的默认 HTML 表格布局。

  完成此操作的第一步是创建或自定义一个浏览器定义文件,该文件用于检测访问 ASP.NET 2.0 站点的浏览器并为该浏览器提供特定的功能。这是一个为通过移动设备访问站点的用户提供自定义体验的好方法。但是,如果使用 CSS 控件适配器,浏览器定义文件用于表示兼容的浏览器应使用一个或多个适配器。

  图 6 所示的 XML 显示了一个完整的浏览器定义文件,该文件告诉 ASP.NET 将所有 MenuControl 类路由到任何符合所述条件的浏览器的 MenuAdapter。该条件描述了支持 JavaScript 和 CSS 的所有符合 W3C 的浏览器。这与如今使用的大多数浏览器一致。浏览器定义文件还为您提供了可用于各类其他自定义用户体验的信息。

Figure6ASP.NET 2.0 浏览器定义文件

<browsers>
 <browser refID="Default">
  <controlAdapters>
   <adapter controlType="System.Web.UI.WebControls.Menu"
        adapterType="CSSFriendly.MenuAdapter" />
  </controlAdapters>
 </browser>
 <browser id="W3C_Validator" parentID="default">
  <identification>
   <userAgent match="^W3C_Validator" />
  </identification>
  <capabilities>
   <capability name="browser"       value="W3C Validator" />
   <capability name="ecmaScriptVersion"  value="1.2" />
   <capability name="javascript"      value="true" />
   <capability name="supportsCss"     value="true" />
   <capability name="supportsCallback"   value="true" />
   <capability name="tables"        value="true" />
   <capability name="tagWriter"      
    value="System.Web.UI.HtmlTextWriter" />
   <capability name="w3cdomversion"    value="1.0" />
  </capabilities>
 </browser>
</browsers>

  实现 CSS 控件适配器的最后一步是创建一个由适配器类派生的类。图 7 显示了随 ASP.NET 2.0 控件适配器附带的示例菜单适配器。该类由 MenuAdapter 类派生而来,它可以枚举构成控件的所有项目并使用适当的标记重写 HTML。此处所示的内容是该类的一部分,该类以 BuildItems 方法呈现无序列表的开始部分。

Figure7菜单控件适配器 HTML 输出

Public Class MenuAdapter
    Inherits System.Web.UI.WebControls.Adapters.MenuAdapter
  ...
    
  Protected Overrides Sub RenderContents(ByVal writer As HtmlTextWriter)
    If (Extender.AdapterEnabled) Then
      writer.Indent = writer.Indent + 1
      BuildItems(Control.Items, True, writer)
      writer.Indent = writer.Indent—1
      writer.WriteLine()
    Else
      MyBase.RenderContents(writer)
    End If
  End Sub
  Private Sub BuildItems(ByVal items As MenuItemCollection, _
      ByVal isRoot As Boolean, ByVal writer As HtmlTextWriter)
    If (items.Count > 0) Then
      writer.WriteLine()
      writer.WriteBeginTag("ul")
      If isRoot Then
        writer.WriteAttribute("class", "AspNet-Menu")
      End If
      writer.Write(HtmlTextWriter.TagRightChar)
      writer.Indent = writer.Indent + 1
      For Each item As MenuItem In items
        BuildItem(item, writer)
      Next
      writer.Indent = writer.Indent—1
      writer.WriteLine()
      writer.WriteEndTag("ul")
    End If
  End Sub
End Class

  查看图 8 中的 HTML 源时,您会发现菜单控件中的表格被无序列表取代。但是,无序列表并不是 HTML 输出中唯一值得关注的主题。由于输出不与样式和脚本代码混在一起,所以输出也十分整洁。现在,所有的定位和样式都驻留在菜单的 CSS 文件中,现在可以认为菜单符合 Web 标准。

Figure8菜单控件适配器 HTML 输出

<div class="AspNet-Menu-Horizontal">
 <ul class="AspNet-Menu">
  <li class="AspNet-Menu-WithChildren">
  <a href="http://Default.aspx" class="AspNet-Menu-Link">Web Standards</a>
   <ul>
    <li class="AspNet-Menu-Leaf">
     <a href="http://ControlAdapters.aspx">Control Adapters Sample</a>
    </li>
    <li class="AspNet-Menu-Leaf">
     <a href="http://AccessibleForm.aspx">Accessible Form</a>
          </li>
        </ul>
      </li>
    </ul>
</div>

  CSS 控件适配器随附在很多控件(包括 Tree view、Login 和 CreateUserWizard)的适配器中,用于表示众所周知的那些不应在呈现表格时却呈现表格的控件。只需花费几分钟的时间,就可以将示例集成到现有项目中,并按照您的喜好进行自定义。

  母版页和主题

  拥有呈现符合 Web 标准的工具之后,您可以使整个站点都符合 Web 标准。母版页和主题的结合使用为网站提供了强大而灵活的体系结构。

  母版页使 Web 开发人员可以为网页创建灵活的模版。母版页是用于创建可供多个网页重用的组件的强大工具,还是一种确保整个站点符合标准的方法。创建使用 XHTML 1.1 DocType 的母版页是确保站点内所有页面都符合标准的一个好方法。当您需要在一个位置(例如,从 XHTML 1.0 Transitional 迁移到 XHTML 1.0 Strict 的站点)对 DocType 进行全面更改时,母版页也很有用。

  ASP.NET 2.0 主题使您可以为相同的内容创建多种设计,从而提高可访问性。例如,通过允许用户增大字体和图像尺寸,主题可以改善视力受损用户对网站的访问。借助可以在母版页中切换主题的功能,用户可以按照最适合自身需求的方式查看站点。

  我发现一种方法可以帮助用户切换主题,那就是定义一个由 Page 类派生而来的类。切换主题功能仅在 ASP.NET 页面生命周期的早期才可以使用(以 OnPreInit 方法)。图 9 中的类说明了如何捕获用户选定的主题并在重写的方法中应用该主题。

Figure9ThemeSelectablePage 类

''' <summary>
''' Override Page with PreInit method to allow for theme switching
''' </summary>
''' <remarks>"__Theme" represents the RadioButton list of theme</remarks>
Public Class ThemeSelectablePage
    Inherits System.Web.UI.Page
  Protected Overloads Overrides Sub OnPreInit(ByVal e As EventArgs)
    For Each key As String In Me.Request.Form.AllKeys
      If key.IndexOf("__Theme") > -1 Then
        Page.Theme = Me.Request.Form(key).Trim
        Exit For
      End If
    Next
    MyBase.OnPreInit(e)
  End Sub
End Class

  此类可以查找具有预定义名称的请求窗体变量并将值传递给主题类。部署此类的所有网页都将提供支持多个主题所需的体系结构。这是向一个站点中的所有页面添加主题的一个非常简单的方法。

  请求

  本文讨论了 Web 标准如此重要的原因,并给出了一些可用于创建符合标准的网站的技术。采用这些标准可能会有一定的难度,因为采用标准通常不是最简单的操作方法,但这是确保将来各类用户可以通过更多设备访问您今天创建的控件和 HTML 的最佳方法。各种浏览器都在逐渐地满足这些标准,而这一趋势仍将继续;现在,编写符合 Web 标准的代码的责任就落在了所有开发人员的肩上。

  Ben Waldron 是 Pop Art, Inc. 的首席技术官,Pop Art, Inc. 是一家为客户提供一系列基于 Web 的解决方案的互动广告经纪公司。Ben 在俄勒冈州波特兰市,您可以通过下面的电子邮件向他询问问题或寻求合作机会:Ben.Waldron@PopArt.com


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3