ITKeyword,专注技术干货聚合推荐

注册 | 登录

ASP.NET 4 和 Visual Studio 2010 Web 开发概述

netatomy 分享于

2021腾讯云限时秒杀,爆款1核2G云服务器298元/3年!(领取2860元代金券),
地址https://cloud.tencent.com/act/cps/redirect?redirect=1062

2021阿里云最低价产品入口+领取代金券(老用户3折起),
入口地址https://www.aliyun.com/minisite/goods

推荐:ASP.NET Visual Studio2010 发布Web网站问题详解

今天研究了一下如何发布web网站,之前总是没耐心,遇到点问题就没心情搞了,今天总算有点耐心搞明白了。其实遇到的问题还是挺多的,网上也没有太全的解释,所以

声明:本文是ASP.NET 白皮书 ASP.NET 4 and Visual Studio 2010 Web Development Overview 的阅读摘要,只是本人的学习记录,并非完整翻译,仅供参考,由于水平有限,有些翻译未必准确。点击下载PDF文档

本文档提供了 ASP.NET 的许多新特性的概述,它们包含在 .NET Framework 4 和 Visual Studio 2010 中。

1. 核心服务

ASP.NET 4 引入了大量特性来增强核心 ASP.NET 服务,例如输出缓存和会话状态存储。

1) Web.config 文件重构

随着新特性的增加,如 Ajax、路由以及与 IIS 7 的交互,Web.config 文件包含的配置越来越多。在 .NET Framework 4 中,主要的配置元素已经移到 machine.config 文件中。这样 ASP.NET 4 应用程序中的 Web.config 文件可以是空的或只包含几行,即指定要针对哪个版本的框架的内容:

<?xml version="1.0"?>
 <configuration>
 <system.web>
 <compilation targetFramework="4.0" /> 
 </system.web>
 </configuration>

2) 可扩展的输出缓存

以前版本的 ASP.NET 要求输出缓存必须要存储在内存中。

ASP.NET 4 提供了输出缓存的可扩展能力,可以创建自定义的输出缓存提供程序。输出缓存提供程序能够使用任何存储机制来持久化 HTML 内容。这样就为多种持久化机制创建自定义输出缓存成为可能,这些机制包括本地或远程磁盘,云存储,以及分布式缓存引擎。

定义继承自 System.Web.Caching.OutputCacheProvider 类型的类即可创建自定义输出缓存提供程序。然后配置 Web.config 文件中的 outputCache 元素,例如:

<caching>
 <outputCache defaultProvider="AspNetInternalProvider">
 <providers>
 <add name="DiskCache"
 type="Test.OutputCacheEx.DiskOutputCacheProvider, DiskCacheProvider"/>
 </providers>
 </outputCache>

</caching>

ASP.NET 4 默认使用内存中输出缓存,即 defaultProvider 属性设置的 AspNetInternalProvider。

另外,可以为每个控件和每个请求选择不同的输出缓存提供程序。例如:

<%@ OutputCache Duration="60" VaryByParam="None" providerName="DiskCache" %>

为 HTTP 请求指定不同的输出缓存需要在 Global.asax 文件中重写 GetOutputCacheProviderName 方法。例如:

public override string GetOutputCacheProviderName(HttpContext context)
{
 if (context.Request.Path.EndsWith("Advanced.aspx"))
 return "DiskCache";
 else
 return base.GetOutputCacheProviderName(context);
}

使用这种扩展能力,可以追求更积极更智能的输出缓存策略,比如现在可以在内存中缓存最常访问的前10个页面,而更低流量的页面缓存在磁盘中。此外,还可以为呈现的页面缓存每个 vary-by 组合,但使用分布式缓存会导致内存消耗从前端 Web 服务器中卸载。

3) 自动启动的Web应用程序

一些 Web 应用程序需要在第一次请求时加载大量的数据或执行昂贵的初始化处理。之前要自己想办法。现在增加了一个新的具有可伸缩能力的特性,叫做自动启动(auto-start),当 ASP.NET 4 运行在 Windows Server 2008 R2 的 IIS 7.5 上时,它能直接解决这样的场景。自动启动为启动应用程序池、初始化 ASP.NET 应用程序以及接受 HTTP 请求提供了可控制的方法。

要使用自动启动特性,IIS 管理员需要设置 applicationHost.config 文件中的应用程序池:

<applicationpools>
 <add name="MyApplicationPool" startMode="AlwaysRunning" />
</applicationpools>

因为单个的应用程序池可以包含多个应用程序,所以需要在 applicationHost.config 文件中为单独的应用程序进行设定:

<sites>
 <site name="MySite" id="1">
 <application path="/" 
 serviceAutoStartEnabled="true"
 serviceAutoStartProvider="PrewarmMyCache" >
 <!-- Additional content -->
 </application>
 </site>

</sites>

<!-- Additional content -->

<serviceautostartproviders>
 <add name="PrewarmMyCache"
 type="MyNamespace.CustomInitialization, MyLibrary" />
</serviceautostartproviders>

当 IIS 7.5 服务器是冷启动的,或当单独的应用程序池回收的时候,IIS 7.5 会使用 applicationHost.config 文件中的信息来确定哪些 Web 应用程序需要自动启动。对每个标记为自动启动的应用程序,IIS 7.5 会发送请求给 ASP.NET 4来启动应用程序。ASP.NET 会实例化定义在 serviceAutoStartProvider 属性中的类型然后调用其公共的入口方法。

创建一个托管的自动启动类型要实现 IProcessHostPreloadClient 接口,例如:

public class CustomInitialization : System.Web.Hosting.IProcessHostPreloadClient
{
 public void Preload(string[] parameters)
{
 // Perform initialization. 
}
}

运行在Preload 方法中的初始化代码返回之后,ASP.NET 应用程序就做好准备处理请求了。

4) 永久重定向

从旧的URL转向新URL的传统方法是使用 Response.Redirect 方法,这个方法发出 HTTP 302 Found(临时重定向)响应,这会导致额外的 HTTP 往返旅程(round trip)。

ASP.NET 4 添加了新的 RedirectPermanent 辅助方法,可发出 HTTP 301 Moved Permanently 响应,例如:

RedirectPermanent("/newpath/foroldcontent.aspx");

搜索引擎和其他用户代理识别出永久重定向后会存储新URL,消除了不必要的往返旅程。

5) 缩小的会话状态

ASP.NET 提供两种跨 Web 群(Web Farm)的默认选项:一个是调用进程外会话状态服务器的会话状态提供程序,另一个是将数据存储在SQL Server中的会话状态提供程序。两个选项都涉及将状态信息发送到 Web 应用程序的工作者进程外部,会话状态必须要在发送前进行序列化。依赖于开发人员保存多少信息在会话状态中,序列化的数据可能会迅速变大。

ASP.NET 4 为两种进程外会话状态提供程序引入了新的压缩选项。当设置为 true 时,ASP.NET 会使用 System.IO.Compression.GZipStream 类压缩或解压缩序列化的会话状态。

<sessionState
 mode="SqlServer"
 sqlConnectionString="data source=dbserver;Initial Catalog=aspnetstate"
 allowCustomSqlDatabase="true"
 compressionEnabled="true"
/>

6) 扩展允许的URL范围

基于 NTFS 文件路径限制,旧版本的ASP.NET 限制 URL 路径长度为 260 个字符。在 ASP.NET 4 中,有选项来增强或减少这个限制。例如:

<httpRuntime maxUrlLength="260" maxQueryStringLength="2048" />

要允许更长或更短的路径(即URL中不包括协议、服务器名和查询字符串的部分),修改 maxUrlLength 即可。要允许更长或更短的查询字符串,修改 maxQueryStringLength 的值。

ASP.NET 4 还提供了检查 URL 包含字符的配置。当发现URL的路径部分中的无效字符时,ASP.NET 会拒绝请求并发出 HTTP 400 错误。旧版本限制了一组固定的字符,ASP.NET 4 可以自定义这些字符了:

<httpRuntime requestPathInvalidChars="&lt;,&gt;,*,%,&amp;,:,\,?" />

注意 ASP.NET 4 总量会拒绝包含 ASCII 码范围在 0x00 到 0x1F 之间的字符的 URL 路径。因为这些是定义在 RFC 2396 中的无效 URL 字符。在运行 IIS 6 或更高版本的 Windows Server 各个版本中,http.sys 协议设备驱动程序会自动地拒绝带有这些字符的 URL。

7) 可扩展的请求验证

ASP.NET 请求验证会搜索进来的 HTTP 请求数据中用于跨站点脚本(XSS,cross-site scripting)攻击的字符串。如果找到,请求验证会标出可疑脚本并返回错误。内置的请求验证仅当发现了最常见的XSS攻击字符串时都会错误。

在 ASP.NET 4 中,请求验证特性可以进行扩展了,这样可以使用自定义的请求验证逻辑。要扩展请求验证逻辑,可以创建继承自新的 System.Web.Util.RequestValidator 类型的类,然后配置应用程序使用自定义类型。例如:

<httpRuntime requestValidationType="Samples.MyValidator, Samples" />

对每个请求,ASP.NET 都会调用自定义类型去处理每段进入的 HTTP 请求数据。进入的 URL,所有的 HTTP 头(cookies 和 自定义头),以及实体主体对自定义请求验证类都可拿来检查。这样的类定义如下所示:

public class CustomRequestValidation : RequestValidator
{
 protected override bool IsValidRequestString(
HttpContext context, string value, 
RequestValidationSource requestValidationSource, 
 string collectionKey, 
 out int validationFailureIndex) 
{...}
}

8) 对象缓存和对象缓存扩展

从初次发布起,ASP.NET 就包含了强大的内存中对象缓存(System.Web.Caching.Cache)。缓存实现已经变得非常以至于它也被用于非 Web 应用程序。然而对于 Windows 窗体或 WPF 来说包含对 System.Web.dll 的引用而只是想使用 ASP.NET 对象缓存很不合适。

为了让所有应用程序都能用到缓存,.NET Framework 4 引入了新的程序集,新的全名空间,一些基类型,和具体的缓存实现。新的 System.Runtime.Caching.dll 程序集包含了 System.Runtime.Caching 全名空间中的新的缓存 API。全名空间包含两个核心的类集合:

  • 抽象类型提供生成任何类型的自定义缓存实现的基础
  • 一个具体的内存中对象缓存实现(System.Runtime.Caching.MemoryCache 类)

新的 MemoryCache 类接近于 ASP.NET 缓存,它和 ASP.NET 共享了许多内部缓存逻辑。尽管 System.Runtime.Caching 中的公共缓存 API 已经更新来支持自定义缓存的开发,如果你使用过 ASP.NET Cache 对象,你会发现在 API 中的概念是相似的。

下面的示例提供了新的缓存API是如何工作的思路,这个示例是为 Windows 窗体编写的,没有依赖于 System.Web.dll。

private void btnGet_Click(object sender, EventArgs e) 
{ 
 //Obtain a reference to the default MemoryCache instance. 
 //Note that you can create multiple MemoryCache(s) inside 
 //of a single application. 
ObjectCache cache = MemoryCache.Default; 
 
 //In this example the cache is storing the contents of a file string 
fileContents = cache["filecontents"] as string;
 
 //If the file contents are not currently in the cache, then 
 //the contents are read from disk and placed in the cache. 
 if (fileContents == null) 
{
 //A CacheItemPolicy object holds all the pieces of cache 
 //dependency and cache expiration metadata related to a single 
 //cache entry. 
CacheItemPolicy policy = new CacheItemPolicy(); 
 
 //Build up the information necessary to create a file dependency. 
 //In this case we just need the file path of the file on disk. 
List filePaths = new List(); 
filePaths.Add("c:\\data.txt"); 
 
 //In the new cache API, dependencies are called "change monitors". 
 //For this example we want the cache entry to be automatically expired 
 //if the contents on disk change. A HostFileChangeMonitor provides 
 //this functionality. 
policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths)); 
 
 //Fetch the file's contents 
fileContents = File.ReadAllText("c:\\data.txt"); 
 
 //And then store the file's contents in the cache 
cache.Set("filecontents", fileContents, policy); 
 
} 
MessageBox.Show(fileContents); 
}

9) 可扩展的 HTML, URL, 和 HTTP 头编码

在 ASP.NET 4 中,可以为下列通用的文本编码任务创建自定义编码例程:

  • HTML 编码
  • URL 编码
  • HTML 属性编码
  • 编码出站(outbound)的 HTTP 头

通过从新的 System.Web.Util.HttpEncoder 类型派生,可以创建自定义编码器,然后配置 ASP.NET 使用这个自定义类型,例如:

<httpRuntime encoderType="Samples.MyCustomEncoder, Samples" /> 

配置好之后,无论何时 System.Web.HttpUtility 或 System.Web.HttpServerUtility 类的公开编码方法被调用,ASP.NET 都会自动调用自定义编码实现。

10) 对单个工作者进程中独立应用程序的性能监视

为了在一个单独的服务器上能够运行更多的 Web 站点,许多主机在单个工作者进程中运行多个 ASP.NET 应用程序。然而,如果多个应用程序使用单个共享的工作者进程,对服务器管理员来说标识出有问题的独立应用程序是很困难的。

ASP.NET 4 调节了由 CLR 引入的新的资源监视功能。要启用这个功能,可以添加下列的 XML 配置片断到 aspnet.config 配置文件中:

<?xml version="1.0" encoding="UTF-8" ?> 
<configuration> 
 <runtime> 
 <appDomainResourceMonitoring enabled="true"/> 
 </runtime> 

</configuration>

注意 aspnet.config 文件位于 .NET Framework 的安装目录,不是 Web.config 文件。

启用之后,两个新的性能计数器在“ASP.NET 应用程序”性能分类中就可用了:% Managed Processor Time 和 Managed Memory Used。这两个性能计数器使用 CLR 新的应用程序域资源管理特性来追踪估算的 CPU 时间和单独的 ASP.NET 应用程序的托管内存利用。

11) 多目标

可以创建针对特定版本 .NET Framework 的应用程序。如果你显式地针对 .NET Framework 4,如果在 Web.config 文件包含了可选的元素,如对 system.codedom 的条目,这些元素必须是正确的对 .NET Framework 4 的。(如果没有显式地针对 .NET Framework 4,目标框架会进行推断)。示例:

<compilation targetFramework="4.0"/> 

注意下列针对特定版本的 .NET Framework 的事项:

  • 在 .NET Framework 4 应用程序池中,如果 Web.config 文件中没有包含 targetFramework 属性或者缺少 Web.config 文件,ASP.NET 生成系统会假设 .NET Framework 4 是目标。(你可能必须修改代码使应用程序运行在 .NET Framework 4 中)
  • 如果你包含了 targetFramework 属性,如果 system.codeDom 元素定义在了 Web.config 文件中,这个文件必须包含针对 .NET Framework 4 的正确条目。
  • 如果你正在使用 aspnet_compiler 命令预编译你的应用程序(例如在一个生成环境),你必须使用针对目标框架的正确版本的 aspnet_compiler 命令。
  • 在运行时,编译器使用安装在计算机中的最新版本的框架程序集(当然在GAC中)。如果后来对框架做了更新(例如,假设安装了 4.1 版本),是能够使用更新版本框架中的特性的,即便 targetFramework 属性针对的是更低的版本(例如4.0)。(然而,在 VS2010 的设计时或使用 aspnet_compiler 命令时,使用框架的新特性会导致编译器错误)。

2. Ajax

1) jQuery 包含在 Web Forms 和 MVC

Visual Studio 对 Web Forms 和 MVC 的模板都包含了开源的 jQuery 库。当创建新网站或项目时,一个包含3个如下文件的 Scripts 文件夹会被创建:

  • jQuery-1.4.1.js —— 人类可读的、未最小化版本的 jQuery 库
  • jQuery-1.4.1.min.js —— 最小化版本的 jQuery 库
  • jQuery-1.4.1-vsdoc.js —— 对 jQuery 库的智能感知文档文件

开发时包含未最小化版本的 jQuery,对产品包含最小化版本的 jQuery。

例如,下面的 Web Forms 页面演示了如何使用 jQuery 更改 TextBox 控件的背景颜色,使其在获得焦点时为黄色:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ShowjQuery.aspx.cs" Inherits="ShowjQuery" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
 <head runat="server">
 <title>Show jQuery</title>
 </head>
 <body>
 <form id="form1" runat="server">
 <div>
 <asp:TextBox ID="txtFirstName" runat="server" /> 
 <br /> 
 <asp:TextBox ID="txtLastName" runat="server" /> 
 </div> 
 </form>
 <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
 1:  
 2: <script type="text/javascript">
 3: $("input").focus( function() { $(this).css("background-color", "yellow"); }); 
 4: 
</script>
</body>
</html>

2) 内容分发网络(CDN)支持

Microsoft Ajax 内容分发网络(Content Delivery Network,CDN)使香锅轻易地添加 ASP.NET Ajax 和 jQuery 脚本到 Web 应用程序中。例如:

<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.js" type="text/javascript"></script>

利用 Microsoft Ajax CDN,可以提高 Ajax 应用程序的性能。Microsoft Ajax CDN 的内容是缓存在世界各地的服务器上的。另外,Microsoft Ajax CDN 让浏览器能够为定位在不同域中的网站重用缓存的 JavaScript 文件。

Microsoft Ajax CDN 支持 SSL(HTTPS)。

要学习更多关于 Microsoft Ajax CDN的内容,访问:http://asp.net/ajaxlibrary/cdn.ashx

ASP.NET ScriptManager 支持 Microsoft Ajax CDN。只要简单地设置 EnableCdn 属性就可以了:

<asp:ScriptManager ID="sm1" EnableCdn="true" runat="server" />

ASP.NET 框架会从 CDN 获取所有的 JavaScript 文件,包括用于验证的和 UpdatePanel 的。

可以为自己的 JavaScript 文件设定 CDN 路径,使用 WebResource 特性就可以实现。例如:

[assembly: WebResource("Foo.js", "application/x-javascript", CdnPath = "http://foo.com/foo/bar/foo.js")]

3) ScriptManager 显式脚本

过去,如果你使用 ASP.NET ScriptManager 你需要加载整个庞大的 ASP.NET Ajax 库。通过利用新的 ScriptManager.AjaxFrameworkMode 属性,可以精确地控制 ASP.NET Ajax 库的哪些组件要加载,只加载需要的组件。

ScriptManager.AjaxFrameworkMode 属性可以设置为以下的值:

  • Enabled——指示 ScriptManager 控件自动地包含 MicrosoftAjax.js 脚本文件,这是各个核心框架脚本的脚本文件组合(遗留行为)。
  • Disabled——指示所有的 Microsoft Ajax 脚本特性都被禁止,ScriptManager 控件不自动引用任何脚本。
  • Explicit——指示要显式地包含页面需要的单独框架核心脚本文件的引用,以及对脚本文件需要的依赖的引用 。

例如,如果你设置 AjaxFrameworkMode 属性为 Explicit 那么可以指定需要的详细的 ASP.NET Ajax 组件脚本:

<asp:ScriptManager ID="sm1" AjaxFrameworkMode="Explicit" runat="server">

<Scripts>
 <asp:ScriptReference Name="MicrosoftAjaxCore.js" />
 <asp:ScriptReference Name="MicrosoftAjaxComponentModel.js" />
 <asp:ScriptReference Name="MicrosoftAjaxSerialization.js" />
 <asp:ScriptReference Name="MicrosoftAjaxNetwork.js" /> 
</Scripts>
</asp:ScriptManager>

3. Web Forms

Web Forms 从 ASP.NET 1.0 发布起就是核心特性。在ASP.NET 4 中有许多增强,包括:

  • 设置 meta 标签的能力
  • 对视图状态更多的控制
  • 使用浏览器兼容能力的更简单的方法
  • 支持对 Web Forms 使用路由
  • 对产生的ID的更多控制
  • 在数据控件中持久化选中行的能力
  • 在 FormView 和 ListView 控件中呈现 HTML 的更多控制
  • 对数据源控件的过滤支持

1) 使用 Page.MetaKeywords 和 Page.MetaDescription 属性设置 Meta 标记

ASP.NET 4 给 Paeg 类添加了 2 个新属性,MetaKeywords 和 MetaDescription。这两个属性的工作方式和页面的 Title 属性工作方式是一样的。下面是规则:

  • 如果 head 元素中没有匹配属性名的 meta 标签, meta 标签会在呈现时添加到页面上
  • 如果已经有 meta 标签,这些属性作为存在标签内容的 get 方法和 set 方法使用

可以在运行时设置这些属性,也可以在 @ Page 指令中设置。例如:

<%@ Page Language="C#" AutoEventWireup="true" 
CodeFile="Default.aspx.cs" 
Inherits="_Default" 
Keywords="These, are, my, keywords" 
Description="This is a description" %> 

这会覆盖页面中声明的 meta 标签内容,如果存在的话。

description meta 标签的内容用于提高 Google 的搜索列表预览。(见 Improve snippets with a meta description makeover)Google 和 Windows Live Search 都不使用 keywords 的内容做任何事情,但其他搜索引擎可能会。更多信息参见Meta Keywords Advice

2) 为单独的控件启用视图状态

默认地,视图状态是为页面启用的,这样页面上的每个控件都可以存储视图状态,即使不需要。视图状态数据是包含在页面生成的标记中,会增加发送页面到客户以及回送的时间。存储多于必须的视图状态会导致明显的性能退化。旧版本的ASP.NET中,开发人员可以禁用控件的视图状态,但不得不为每个单独的控件设置。在 ASP.NET 4 中,Web服务器控件包含了一个 ViewStateMode 属性来默认禁用页面的视图状态并只为页面中需要的控件启用它。

ViewStateMode 属性有三个值:Enabled,Disabled 和 Inherit。Enabled 为控件及其设置相同属性为 Inherit 值或不设置的子控件启用视图状态。Disabled 禁用视图状态,而 Inherit 表示控件使用父控件的 ViewStateMode 值。例如:

<form id="form1" runat="server"> 
 <script runat="server">
 1: 
 2: protected override void OnLoad(EventArgs e) { 
 3: if (!IsPostBack) { 
 4: label1.Text = label2.Text = "[DynamicValue]"; 
 5: } 
 6: base.OnLoad(e); 
 7: } 
 8: 
</script>
<asp:PlaceHolder ID="PlaceHolder1" runat="server" ViewStateMode="Disabled">
Disabled: <asp:Label ID="label1" runat="server" Text="[DeclaredValue]" /><br />
<asp:PlaceHolder ID="PlaceHolder2" runat="server" ViewStateMode="Enabled">
Enabled: <asp:Label ID="label2" runat="server" Text="[DeclaredValue]" />
</asp:PlaceHolder>
</asp:PlaceHolder>
<hr />
<asp:button ID="Button1" runat="server" Text="Postback" />
<%
 1: -- Further markup here --
%>

可以看到,PlaceHolder1 控件禁用了视图状态,子控件 label1 继承了这个属性值(Inherit 是默认值),因此不会保存视图状态。PlaceHolder2 控件 ViewStateMode 设置为 Enabled,所以 label2 继承了这个属性保存了视图状态。当页面第一次加载时,两个标签的 Text 属性都被设置为 "[DynamicValue]"。

然而在 postback 后,label1 显示 [DeclaredValue],label2 显示 [DynamicValue]。

也可以在 @ Page 指令中设置 ViewStateMode:

<%@ Page Language="C#" AutoEventWireup="true" 
CodeBehind="Default.aspx.cs" 
Inherits="WebApplication1._Default" 
ViewStateMode="Disabled" %>

Page 类只不过是另一种控件,它作为页面中所有其他控件的父控件作用。Page 实例 ViewSateMode 的默认值是 Enabled,控件的默认值是 Inherit。

仅当 EnableViewState 属性为 true 时,ViewStateMode 属性的值才会决定视图状态是否要维护。如果 EnableViewState 属性为 false,视图状态将不会被维护,即使 ViewStateMode 被设置为 Enabled。

一个良好的使用是在母版页中使用 ContentPlaceHolder 控件,可以为母版页把 ViewStateMode 设置为 Disabled 然后把需要视图状态的 ContentPlaceHolder 控件单独启用它。

3) 浏览器能力的变化

ASP.NET 通过使用一种叫做浏览器能力(browser capabilities)的特性来检测用户使用的浏览器的能力。浏览器能力是通过 HttpBrowserCapabilities 对象(由 Request.Browser 属性暴露)来表示的。可以使用 HttpBrowserCapabilities 对象检测当前浏览器是否支持特定版本JavaScript的类型和版本。或者,检测请求是否最初来自于移动设备。

HttpBrowserCapabilities 对象是由一组浏览器定义文件驱动的。这些文件包含了关于特定浏览器能力的信息。在 ASP.NET 4 中,这些浏览器定义文件已经更新为包含最近引入的浏览器和设备(如 Chrome, iPhone)的信息。

下面的列表展示了新的浏览器定义文件:

  • blackberry.browser
  • chrome.browser
  • Default.browser
  • firefox.browser
  • gateway.browser
  • generic.browser
  • ie.browser
  • iemobile.browser
  • iphone.browser
  • opera.browser
  • safari.browser

使用浏览器能力提供程序

在 ASP.NET 3.5 SP1 中,可以以下面的方法定义浏览器拥有的能力:

a. 在计算机级别,创建或更新下面文件夹中的 .browser XML文件:

\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers

定义后要从 Visual Studio 命令提示行运行下面的命令来重新生成浏览器能力程序集并将其添加到GAC:

aspnet_regbrowsers.exe -I c

b. 对于单独的应用程序,在应用程序的 App_Browsers 文件夹中创建 .browser 文件。

这些方法需要更改 XML 文件,对于计算机级别的更改,还必须在运行 aspnet_regbrowsers.exe 后重新启动应用程序。

ASP.NET 4 包含一个称为浏览器能力提供程序(browser capabilities provider)的特性。正如名称所示,这个会让你征收一个提供程序,从而能使用自己的代码检测浏览器能力。

在实践中,开发人员经常不会定义自定义的浏览器能力。浏览器文件很难更新,更新他们的过程相当复杂,而 .browser 文件的 XML 语法复杂的难以使用和定义。如果有一个通用的浏览器定义语法,或者一个包含即时更新浏览器定义的数据库,会不会让这个过程变得容易呢。新的浏览器能力提供程序特性让这些场景成为可能,对第三方开发人员也实用。

有两个使用新的 ASP.NET 4 浏览器能力提供程序特性的主要方法:扩展 ASP.NET 浏览器能力定义功能,或者干脆完全取代它。下面描述如何取代它,再介绍如何扩展它。

a. 取代 ASP.NET 浏览器能力功能

要完全取代 ASP.NET 浏览器能力,遵循这些步骤:

(1) 创建一个派生自 HttpCapabilitiesProvider 提供程序类重写 GetBrowserCapabilities 方法,例如:

public class CustomProvider : HttpCapabilitiesProvider 
{ 
 public override HttpBrowserCapabilities GetBrowserCapabilities(HttpRequest request) 
{ 
HttpBrowserCapabilities browserCaps = new HttpBrowserCapabilities(); 
Hashtable values = new Hashtable(180, StringComparer.OrdinalIgnoreCase); 
values[String.Empty] = request.UserAgent; 
values["browser"] = "MyCustomBrowser"; 
browserCaps.Capabilities = values; 
 return browserCaps;
} 
}

代码创建了一个新的 HttpBrowserCapabilities 对象,仅指定了名为 browser 的能力并设置此能力的值为 MyCustomerBrowser。

(2) 注册提供程序

为了在应用程序中使用提供程序,必须在 Web.config 或 machine.config 文件的 browserCaps 节添加 provider 属性。(也可以在 location 元素中为特定目录定义提供程序属性,例如针对特定移动设备的文件夹)。例如:

<system.web> 
<browserCaps provider="ClassLibrary2.CustomProvider, ClassLibrary2, 
Version=1.0.0.0, Culture=neutral" /> 
</system.web>

另一种注册方法是使用代码,例如:

void Application_Start(object sender, EventArgs e) 
{ 
HttpCapabilitiesBase.BrowserCapabilitiesProvider =
 new ClassLibrary2.CustomProvider();
 // ... 
}

这段代码必须运行在 Global.asax 文件的 Application_Start 事件中。

b. 缓存 HttpBrowserCapabilities 对象

可提升性能,步骤如下:

(1) 创建一个派生自 HttpCapabilitiesProvider 的类,例如:

public class CustomProvider : HttpCapabilitiesProvider 
{ 
 public override HttpBrowserCapabilities 
GetBrowserCapabilities(HttpRequest request) 
{ 
 string cacheKey = BuildCacheKey(); 
 int cacheTime = GetCacheTime(); 
HttpBrowserCapabilities browserCaps = 
HttpContext.Current.Cache[cacheKey] as 
HttpBrowserCapabilities; 
 if (browserCaps == null) 
{ 
HttpBrowserCapabilities browserCaps = new 
HttpBrowserCapabilities(); 
Hashtable values = new Hashtable(180, 
StringComparer.OrdinalIgnoreCase); 
values[String.Empty] = request.UserAgent; 
values["browser"] = "MyCustomBrowser"; 
browserCaps.Capabilities = values; 
HttpContext.Current.Cache.Insert(cacheKey, 
browserCaps, null, DateTime.MaxValue, 
TimeSpan.FromSeconds(cacheTime));
} 
 return browserCaps; 
} 
}

(2) 注册提供程序(与前面相同)

c. 扩展 ASP.NET 浏览器能力功能

(1) 创建一个派生自 HttpCapabilitiesEvaluator 的类,重写 GetBrowserCapabilities 方法,例如:

public class CustomProvider : HttpCapabilitiesEvaluator 
{ 
 public override HttpBrowserCapabilities 
GetBrowserCapabilities(HttpRequest request) 
{ 
HttpBrowserCapabilities browserCaps = 
 base.GetHttpBrowserCapabilities(request);
 if (browserCaps.Browser == "Unknown") 
{ 
browserCaps = MyBrowserCapabilitiesEvaulator(request); 
} 
 return browserCaps; 
} 
}

(2) 注册提供程序(与前面相同)

d. 通过添加新的能力给已存在能力定义来扩展浏览器能力功能

(1) 创建派生自 HttpCapabilitiesEvaluator 的类,重写 GetBrowserCapabilities 方法,例如:

public class CustomProvider : HttpCapabilitiesEvalutor
{
 public override HttpBrowserCapabilities
GetBrowserCapabilities(HttpRequest request)
{
HttpBrowserCapabilities browserCaps = 
 base.GetBrowserCapabilities(request);
browserCaps.Frames = true;
browserCaps.Capabilities["MultiTouch"] = "true";
 return browserCaps;
}
}

(2) 注册提供程序(与前面相同)

4) ASP.NET 4 中的路由

ASP.NET 4 增加了对 Web Forms 使用路由的内置支持。路由让应用程序可以配置来接受不映射到物理文件的请求URL。

路由从 ASP.NET 3.5 SP1 起就可用了,不过 ASP.NET 4 包含了一些更易于使用的特性:

  • PageRouteHandler 类,是一个简单的 HTTP 处理程序在定义路由时使用,该类传递数据到请求路由的页面。
  • 新的 HttpRequest.RequestContext 属性和 Page.RouteData 属性(这是HttpRequest.RequestContext.RouteData 对象的代理)。用于更方便的访问从路由传递的信息。
  • 新的表达式生成器:System.Web.Compilation.RouteUrlExpressionbuilder 和 System.Web.Compilation.RouteValueExpressionBuilder。
  • RouteUrl,提供了一个在服务器控件中创建路由URL的简单方法。
  • RouteValue,提供了从 RouteContext 对象提取信息的简单方法。
  • RouteParameter 类,使 RouteContext 对象中包含的数据传递到数据源控件查询变得更加容易。

a. 针对 Web Forms 页面路由

下面的例子展示了如何使用 Route 类的新 MapPageRoute 方法定义 Web Forms 路由:

public class Global : System.Web.HttpApplication 
{ 
 void Application_Start(object sender, EventArgs e) 
{ 
RouteTable.Routes.MapPageRoute("SearchRoute", 
 "search/{searchterm}", "~/search.aspx"); 
RouteTable.Routes.MapPageRoute("UserRoute", 
 "users/{username}", "~/users.aspx"); 
} 
}

ASP.NET 4 引入了 MapPageRoute 方法。下面的例子和前面的例子作用相同,但使用了 PageRouteHandler 类:

RouteTable.Routes.Add("SearchRoute", new Route("search/{searchterm}", 
 new PageRouteHandler("~/search.aspx")));

代码将路由映射到物理页面。第一个路由定义还指定了名为 searchterm 的参数,它应当从 URL 中提取并传递给页面。

MapPageRoute 方法支持下面的方法重载:

  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary contraints)

checkPhysicalUrlAccess 参数指示路由是否应当检查被路由的物理页面(search.aspx)的安全许可,和进站URL的许可(search/{searchterm})。如果值为 false,只能进站的URL许可会被检查。这些许可定义在 Web.config 文件中,例如:

<configuration> 
 <location path="search.aspx"> 
 <system.web> 
 <authorization> 
 <allow roles="admin"/> 
 <deny users="*"/> 
 </authorization> 
 </system.web> 
 </location> 
 <location path="search"> 
 <system.web> 
 <authorization> 
 <allow users="*"/> 
 </authorization> 
 </system.web> 
 </location> 

</configuration> 

在示例中,对物理文件 search.aspx 的访问对除了admin角色的其他所有用户是禁止的。当 checkPhysicalUrlAccess 参数为 true (默认值)时,只有 admin 用户允许访问 URL /search/{searchterm}。如果为 false,所有的授权用户都允许访问 URL /search/{searchterm}。

b. 在 Web Forms 页面中读取路由信息

在 Web Forms 物理页面的代码中,可以访问从 URL 提取的路由信息(或者其他对象添加到 RouteData 对象中的其他信息),这是通过两个属性做到的:HttpRequest.RequestContext 和 Page.RouteData。(Page.RouteData 包装了 HttpRequest.RequestContext.RouteData)例如:

protected void Page_Load(object sender, EventArgs e) 
{ 
string searchterm = Page.RouteData.Values["searchterm"] as string; 
label1.Text = searchterm; 
}

考虑这个请求URL:http://localhost/search/scott,单词“scott”会在 search.aspx 页面中呈现。

c. 在标记中访问路由信息

可以在标记中使用表达式访问路由数据。表达式生成器是一种和声明式代码一起工作的强大而优雅的方法。(更多信息见 Express Yourself With Custom Expression Builders)。

ASP.NET 4 为 Web Forms 路由包含两个新的表达式生成器。例如:

<asp:HyperLink ID="HyperLink1" runat="server" 
 NavigateUrl="<%$RouteUrl:SearchTerm=scott%>">Search for Scott</asp:HyperLink> 

在示例中,RouteUrl 用于定义基于路由参数的 URL。这个标记会生成这样的URL:http://localhost/search/scott。

ASP.NET 基于输入参数自动的解决正确的路由(即产生正确的 URL)。还可以在表达式中包含路由名称,这样可以指定要使用的路由。

下面的例子展示了如何使用 RouteValue 表达式,例如:

<asp:Label ID="Label1" runat="server" Text="<%$RouteValue:SearchTerm%>" />

当包含这个页面的控件运行时,“scott”会显示在标签上。

RouteValue 表达式使得在标记中使用路由数据变得简单,它避免了在标记中使用更复杂的 Page.RouteData["x"] 语法。

d. 为数据源控件参数使用路由数据

RouteParameter 类可以指定路由数据作为数据源控件中查询的参数值。例如:

<asp:sqldatasource id="SqlDataSource1" runat="server" 
 connectionstring="<%$ ConnectionStrings:MyNorthwind %>" 
 selectcommand="SELECT CompanyName,ShipperID FROM Shippers where 
CompanyName=@companyname" 
&lt;selectparameters> 
 <asp:routeparameter name="companyname" RouteKey="searchterm" /> 
 </selectparameters> 

</asp:sqldatasource> 

5) 设置客户 ID

新的 ClientIDMode 属性解决了 ASP.NET 的一个长久的问题,即控件如何为呈现的元素创建 id 属性。如果应用程序包含引用这些元素的客户脚本时为呈现的元素生成的 id 属性就很重要。

HTML 中为 Web 服务器控件呈现的的 id 属性是基于控件的 ClientID 属性产生的。直到 ASP.NET 4,从 ClientID 产生 id 属性的算法一直都是使用 ID 连接到命名容器(如果有),这样对于反复控件(repeated controls,即在数据控件中),会添加一个前缀和一系列连续的数字。这就保证了页面中控件的 ID 是唯一的,算法导致控件 ID 是不可预知的,因而在客户脚本中难以引用。

新的 ClientIDMode 属性使得可以更精确地指定如何为控件产生客户 ID。你可以为任何控件设置 ClientIDMode 属性,包括页面。可能的设置有:

  • AutoID —— 这和旧版本的 ASP.NET 中产生 ClientID 属性值的算法等价。
  • Static —— 这表示 ClientID 的值将会和 ID 的值相同,而不会连接父级命名容器的 ID。这对 Web 中的用户控件是有用的。因为一个 Web 用户控件可以放在不同的页面上以及在不同的容器控件中,对使用 AutoID 算法的控件编写客户脚本是很困难的,因为不能预测 ID 的值。
  • Predictable —— 这个选项主要用于使用重复模板的数据控件。它连接了控件的命名容器的 ID 属性,但产生的 ClientID 值不包含类似 "ctlxxx" 的字符串。这个设置和控件的 ClientIDRowSuffix 属性一直工作。设置 ClientIDRowSuffix 属性给数据字段的名称,这个字段的值用作产生的 ClientID 值的后缀。通常使用数据记录的主键作为 ClientIDRowSuffix 值。
  • Inherit —— 这个设置是控件的默认行为,它表示控件的 ID 产生和它的父容器相同。

可以在页面级别设置 ClientIDMode,这样就把当前页面中所有的控件定义了默认的 ClientIDMode 值。

在页面级别的默认的 ClientIDMode 值是 AutoID,控件级别默认的 ClientIDMode 值是 Inherit。

在 @ Page 指令中设置页面级别的值,例如:

<%@ Page Language="C#" AutoEventWireup="true" 
CodeFile="Default.aspx.cs" 
Inherits="_Default" 
ClientIDMode="Predictable" %> 

也可以在配置文件中设置 ClientIDMode 值,或者在计算机(机器)级别,或者在应用程序级别。这会在应用程序中所有页面的所有控件定义默认的 ClientIDMode 设置。如果在计算机级别设置值,就为那台计算机上所有的网站定义了默认的 ClientIDMode 设置。例如:

<system.web> 
 <pages clientIDMode="Predictable"></pages> 
</system.web>

ClientID 属性的值是从控件父控件的命名容器推断出来的。在某些场景中,例如当你使用母版页时,控件的 ID 可能呈现为下面的 HTML:

<div id="ctl00_ContentPlaceHolder1_ParentPanel"> 
 <div id="ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1"> 
 <input name="ctl00$ContentPlaceHolder1$ParentPanel$NamingPanel1$TextBox1" 
 type="text" value="Hello!" 
 id="ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1_TextBox1" /> 
</div> 

尽管标记中显示的 input 元素在页面中只有两个命名容器(嵌套的 ContentPlaceHolder 控件),因为母版页的处理方法,最终结果是控件的ID会像这样:

ctl00_ContentPlaceHolder1_ParentPanel_NamingPanel1_TextBox1

这个 ID 保证了在页面中是唯一的,但在大部分情况下是不必要的。想减少呈现的 ID 的长度,或者想控制 ID 是如何产生的(比如要消除 "ctlxxx" 前缀),最简单的解决方法是设置 ClientIDMode 属性,例如:

<tc:NamingPanel runat="server" ID="ParentPanel" ClientIDMode="Static"> 
 <tc:NamingPanel runat="server" ID="NamingPanel1" ClientIDMode="Predictable"> 
 <asp:TextBox ID="TextBox1" runat="server" Text="Hello!"></asp:TextBox> 
 </tc:NamingPanel> 

</tc:NamingPanel> 

在这个示例中,最外层的 NamingPanel 元素的 ClientIDMode 属性被设置为 static,内部的 NamingPanel 元素被设置为 Predictable。这些设置导致下面的标记(页面的其余部分和母版页假设和前面的示例相同):

<div id="ParentPanel"> 
 <div id="ParentPanel_NamingPanel1"> 
 <input name="ctl00$ContentPlaceHolder1$ParentPanel$NamingPanel1$TextBox1" 
 type="text" value="Hello!" id="ParentPanel_NamingPanel1_TextBox1" /> 
</div> 

Static 的设置会影响最外层 NamingPanel 元素内部任意控件的命名层次的重新设置,从产生的 ID 中消除 ContentPlaceHolder 和 MasterPage 的 ID(呈现元素的 name 属性没有受到影响,因此对事件、视图状态等的标准 ASP.NET 功能依然保留着)。重新设置命名层次的一个副作用是即使你移动 NamingPanel 元素到不同的 ContentPlaceHolder 控件上,呈现的客户 ID 和之前相同。

注意这取决于你来确保呈现的控件 ID 是唯一的。如果不是,会打断需要唯一 ID 的功能,例如客户的 document.getElementById 函数。

a. 在数据绑定控件中创建可预测的客户 ID

在数据绑定的列表控件中通过遗留算法为控件产生的 ClientID 值既长又无法预测。ClientIDMode 功能可以帮助控制这些 ID 如何产生。

在下面的示例中包含一个 ListView 控件:

<asp:ListView ID="ListView1" runat="server" DataSourceID="SqlDataSource1" 
 OnSelectedIndexChanged="ListView1_SelectedIndexChanged" 
 ClientIDMode="Predictable" 
 ClientIDRowSuffix="ProductID"> 
</asp:ListView> 

标记中 ClientIDMode 和 ClientIDRowSuffix 属性都被设置了。ClientIDRowSuffix 属性仅能用于数据绑定控件中,它的行为会因使用的控件而不同。区别在于:

  • GridView 控件 —— 可以指定数据源中一个或多个列的名字,它们会在运行时组合起来创建客户 ID。例如,如果你设置 ClientIDRowSuffix 为 "ProductName, ProductId",呈现元素的控件 ID将拥有类似下面的格式:rootPanel_GridView1_ProductNameLabel_Chai_1
  • ListView 控件 —— 可以指定数据源中的单个列追加到客户 ID。例如,如果你设置 ClientIDSuffix 为 "ProductName",呈现的控件 ID 将拥有类似这样的格式:rootPanel_ListView1_ProductNameLabel_1
  • Repeater 控件 —— 这个控件不支持 ClientIDRowSuffix 属性。在 Repeater 控件中,使用的是当前行的索引。当使用 ClientIDMode="Predictable"时,客户 ID的产生会有这样的格式:Repeater1_ProductNameLabel_0

FormView 和 DetailsView 控件不显示多行,所以它们不支持 ClientIDRowSuffix 属性。

6) 在数据控件中持久化行选择

GridView 和 ListView 控件能够让用户选择一行。在旧版本的 ASP.NET 中,选择是基于页面上的行索引。例如,如果你选择了页面 1 上的第三项然后移动到页面 2,这个页面的第三项会选中。

持久化选中开始仅在 .NET Framework 3.5 SP1 的动态数据(Dynamic Data)项目中支持。当这个特性启用时,当前选中的项是基于项的数据键。这意味着如果在页面 1 选中第三行并移到页面 2,页面 2 上什么也不会选中。当移回到页面 1,第三行仍然被选中。通过使用 EnablePersistedSelection 属性,持久化选中现在在所有项目中支持 GridView 和 ListView 控件,如下所示:

<asp:GridView id="GridView2" runat="server" EnablePersistedSelection="true"> 
</asp:GridView> 

7) ASP.NET Chart 控件

ASP.NET Chart 控件在 .NET Framework 中扩展了数据可视化提供。使用 Chart 控件,能够为复杂的统计或金融分析创建拥有直觉的和可视化的直观的图表的 ASP.NET 页面。ASP.NET Chart 控件作为 .NET Framework 3.5 SP1 的附加组件引入,现在是 .NET Framework 4 的一部分。

控件包含下列特性:

  • 35 个不同的图表类型
  • 无限数量的图表区域(areas),标题,图例(legends),和标注(annotation)
  • 大量的外观设置
  • 大多数图表类型的3D支持
  • 能自动适应数据点(fit around data points)的智能数据标签
  • 带状线,刻度中断和对数尺度(Strip lines, scale breaks, and logarithmic scaling)
  • 超过 50 个金融和统计公式用于数据分析和转换
  • 图表数据的简单绑定和操纵
  • 支持通用数据格式,如日期,时间,和货币
  • 支持交互性和事件驱动的定制,包括使用 Ajax 的客户单击事件
  • 状态管理
  • 二进制流

下面的图展示了金融图表的示例:

对于如何使用 Chart 控件的更多示例,可以下载 Samples Environment for Microsoft Char Controls 页面的示例代码。在 Chart Control Forum 可以找到更多的示例。

推荐:[英文]利用Visual Studio.NET 进行 ASP.NET的WEB开发

导 读:本文作者从一个WEB 开发者的角度谈了VISUAL STUDIO.NET 的一些优点,同时还为ASP程序员向.NET 编程转变提出了一些建议. Web Enabling Visual Studio.NET I

a. 添加 Chart 控件到 ASP.NET 页面

下面的例子展示了如何添加 Chart 控件到 ASP.NET 页面,在示例中,Chart 控件会为静态数据点产生一个柱状图。

<asp:Chart ID="Chart1" runat="server"> 
 <Series> 
 <asp:Series Name="Series1" ChartType="Column"> 
 <Points> 
 <asp:DataPoint AxisLabel="Product A" YValues="345"/> 
 <asp:DataPoint AxisLabel="Product B" YValues="456"/> 
 <asp:DataPoint AxisLabel="Product C" YValues="125"/> 
 <asp:DataPoint AxisLabel="Product D" YValues="957"/> &

lt;/Points> 
 </asp:Series> 
 </Series> 
 <ChartAreas> 
 <asp:ChartArea Name="ChartArea1"> 
 <AxisY IsLogarithmic="True" /> 
 </asp:ChartArea> 
 </ChartAreas> 
 <Legends> 
 <asp:Legend Name="Legend1" Title="Product Sales" /> 
 </Legends> 

</asp:Chart> 

b. 使用3-D图表

Chart 控件包含 ChartAreas 集合,包含定义图表区域特征的 ChartArea 对象。例如,要为图表区域使用 3-D,可以像下面的例子那样使用 Area3DStyle 属性:

<asp:ChartArea Name="ChartArea1"> 
 <area3dstyle 
 Rotation="10" 
 Perspective="10" 
 Enable3D="True" 
 Inclination="15" 
 IsRightAngleAxes="False" 
 WallWidth="0" 
 IsClustered="False" /> 
 
 <%
 1: -- Additional markup here --
%>
</asp:ChartArea>

下图展示了一个3-D图表。

c. 使用刻度中断和对数刻度

这两个特性对图表区域中的每个轴是特定的。例如,为了在图表区域的基本的Y轴使用这些特性,要使用ChartArea 对象中的AxisY.IsLogarithmic 和 ScaleBreakStyle 属性。下面的片断展示了如何在基本Y轴使用刻度中断:

<asp:ChartArea Name="ChartArea1">

 <axisy>

 <ScaleBreakStyle 
 BreakLineStyle="Wave" 
 CollapsibleSpaceThreshold="40" 
 Enabled="True" />
 </axisy>
...
</asp:ChartArea>

下图展示了效果:

8) 使用 QueryExtender 控件过滤数据

一个非常常见的任务是过滤数据。这传统上是通过在数据源控件中生成 Where 子句执行的。这个方法可能很复杂,有时 Where 语法并不能充分利用底层数据库的全部功能。

为了使过滤更容易,一个新的 QueryExtender 控件加入到 ASP.NET 4 中。 这个控件能够被添加到 EntityDataSource 或 LinqDataSource 控件中使能够过滤由这些控件返回的数据。因为 QueryExtender 控件依赖于 LINQ,所以在数据发送到页面之前,过滤要应用到数据库服务器上,这会带来非常高效的操作。

QueryExtender 控件支持各种各样的过滤选项。下列几节描述这些选项并提供如何使用它们的示例。

a. 查找(Search)

对于查找选项,QueryExtender 控件在指定的字段执行查找。在下面的例子中,控件使用输入到 TextBoxSearch 控件中的文本并在从 LinqDataSource 控件返回的数据中的 ProductName 和 Supplier.CompanyName 列中查找其内容。

<asp:LinqDataSource ID="dataSource" runat="server"> TableName="Products"> 
</asp:LinqDataSource> 
<asp:QueryExtender TargetControlID="dataSource" runat="server"> 
 <asp:SearchExpression DataFields="ProductName, Supplier.CompanyName" 
 SearchType="StartsWith"> 
 <asp:ControlParameter ControlID="TextBoxSearch" /> 
 </asp:SearchExpression> 
</asp:QueryExtender>

b. 范围(Range)

范围选项类似于查找选项,但是要指定一对定义范围的值。在下面的示例中,QueryExtender 控件查找 LinqDataSource 控件返回数据中的 UnitPrice 列。范围从 TextBoxFrom 和 TextBoxTo 控件读取。

<asp:LinqDataSource ID="dataSource" runat="server"> TableName="Products"> 
</asp:LinqDataSource> 
<asp:QueryExtender TargetControlID="dataSource" runat="server"> 
 <asp:RangeExpression DataField="UnitPrice" MinType="Inclusive" 
 MaxType="Inclusive"> 
 <asp:ControlParameter ControlID="TextBoxFrom" /> 
 <asp:ControlParameter ControlID="TexBoxTo" /> 
 </asp:RangeExpression> 

</asp:QueryExtender> 

c. 属性表达式(PropertyExpression)

属性表达式选项可以定义对属性值的比较。如果表达式演算为 true,那么被检查的数据会返回。下面的示例中,QueryExtender 控件通过比较 Disontinued 列中的数据和来自页面 CheckBoxDiscontinued 控件的值过滤数据。

<asp:LinqDataSource ID="dataSource" runat="server" TableName="Products">
</asp:LinqDataSource>
<asp:QueryExtender TargetControlID="dataSource" runat="server">
 <asp:PropertyExpression>
 <asp:ControlParameter ControlID="CheckBoxDiscontinued" Name="Discontinued" />
 </asp:PropertyExpression>
</asp:QueryExtender>

d. 自定义表达式(CustomExpression)

这个选项会调用页面中的函数,此函数定义了自定义过滤逻辑。下面的示例展示了如何声明式地指定一个自定义表达式。

<asp:LinqDataSource ID="dataSource" runat="server" TableName="Products"> 
</asp:LinqDataSource> 
<asp:QueryExtender TargetControlID="dataSource" runat="server"> 
 <asp:CustomExpression OnQuerying="FilterProducts" /> 
</asp:QueryExtender> 

下面的示例展示了会被 QueryExtender 控件调用的自定义函数。

protected void FilterProducts(object sender, CustomExpressionEventArgs e) 
{ 
e.Query = from p in e.Query.Cast() 
 where p.UnitPrice >= 10 
select p; 
}

这些示例仅展示了在 QueryExtender 控件中一次只使用一种表达式。然而,你能够在 QueryExtender 控件内部包含多种表达式。

9) HTML 编码的代码表达式

一些 ASP.NET 站点(尤其是使用 ASP.NET MVC)严重依赖使用 <%= expression %> 语法(常称作"Code nuggets")来编写一些文本到响应。当使用代码表达式时,很容易就会忘记 HTML 编码这些文本,如果文本来自用户输入,它可能会让页面对跨站点脚本(XSS)攻击开放。

ASP.NET 4 为代码表达式引入了下面的新语法:

<%: expression %>

当定入到响应时,这种语法默认使用 HTML 编码。这种新表达式实际会转换成下面的:

<%= HttpUtility.HtmlEncode(expression) %>

例如,<%: Request["UserInput"] %> 会在 Request["UserInput"] 的值上面执行 HTML 编码。

这个特性的目标是使得用新语法代替老语法的所有实例成为可能,这样就不用强迫在每个步骤决定要使用哪一个。然而,有一些情况即正在输出的文本哪些是 HTML 还是已经编码过了,这会导致双重编码。

为了解决这些情况,ASP.NET 4 引入了一个新接口,IHtmlString,和具体实现,HtmlString。这些类型的实例表示对要显示为 HTML 的返回值已经恰当地编码了(或另外检查了),因此值不必在被编码了。例如,下面不应当被(也没被)HTML编码:

<%
 1: : new HtmlString("<strong>HTML that is not encoded</strong>") 
%>

ASP.NET MVC 2 辅助方法已经被更新为和这种新语法一起工作这样就不会被双重编码了,但仅当你在运行 ASP.NET 4 的时候。这种新语法在应用程序使用 ASP.NET 3.5 SP1 运行的时候是不工作的。

记住这不保证来自 XSS 攻击的保护。例如,使用不包含在引号中的属性值的 HTML 能够包含依然会受影响的用户输入。注意 ASP.NET 控件的输出和 ASP.NET MVC 辅助方法总是把属性值包含在引号中,这是推荐的方法。

同样,这种语法不会执行 JavaScript 编码,例如在基于用户输入创建一个 JavaScript 字符串时。

10) 项目模板变化

在旧版本的 ASP.NET 提供的项目模板(一个空项目模板和一个仅有默认文档的模板)不利于指导初学者。因此,ASP.NET 4 引入了三个新模板,一个为空 Web 应用程序项目,另两个为一个 Web 应用程序和一个为网站项目。

a. 空 Web 应用程序模板

仅有一个 web.config 文件:

b. Web 应用程序和网站项目模板

项目包含大量文件。另外,Web 应用程序项目使用基本的会员功能进行配置,这可以快速地在安全访问新应用程序中开始起动。所以 web.config 文件包含了用于配置会员、角色和profiles的条目。

项目还在 Account 目录中包含第二个 Web.config 文件。这第二个配置文件提供了一种对非登录用户安全访问 ChangePassword.aspx 页面的方法。例如:

默认创建的页面同样包含很多内容。项目包含一个默认的母版页和 CSS 文件,以及一个配置为默认使用母版页的默认页面(Default.aspx)。结果就是当你第一次运行 Web 应用程序或网站时,默认页面(主页)就已经就绪了。事实上,当启动一个新的 MVC 应用程序时默认页面是相似的。

项目模板的这些改变的意图是提供一个指南,即如何开始构建一个新的 Web 应用程序。使用语义正确的,严格遵从 XHTML 1.0 的标记和使用 CSS 指定布局,模板中的页面为构建 ASP.NET 4 Web应用程序提供了最佳实践。

11) CSS 增强

ASP.NET 4 中的一个主要工作方面是帮助呈现遵从最新HTML标准的HTML。这包括ASP.NET Web服务器控件如何使用 CSS 样式。

a. 针对呈现的兼容性设置

默认地,当 Web 应用程序或网站针对 .NET Framework 4 时,页面元素的 controlRenderingCompatibilityVersion 属性会设置为 "4.0"。这个元素定义在机器级别的 Web.config 文件中,默认应用到所有的 ASP.NET 4 应用程序上:

<system.web> 
 <pages controlRenderingCompatibilityVersion="3.5|4.0"/> 
</system.web> 
controlRenderingCompatibilityVersion 是一个字符串,在当前发布版本中,支持下列的值:
  • "3.5"。这个设置表示遗留的呈现和标记。控件呈现的标记是100%向后兼容的,而 xhtmlConformance 属性是承兑的(honored 怎么翻译?)
  • "4.0"。如果是这个设置,ASP.NET 服务器控件会做下列事情:
    • xhtmlConformance 属性总是被视为 "Strict"。
    • 非输入控件不再呈现无效样式。
    • 隐藏域周围的 div 元素现在是有样式的,这样它们就不会妨碍用户创建的 CSS 规则。
    • Menu 控件呈现的标记是语义正确的而且遵从可访问性指南。
    • 验证控件不再呈现内联样式。
    • 以前会呈现 border="0" 的控件(即从ASP.NET Table 控件和 Image 控件派生的控件)不再呈现这个属性。

b. 禁用控件

在 ASP.NET 3.5 SP1 和更早版本中,框架会为任何 Enabled 属性设置为 false 的控件在 HTML 中呈现 disabled 属性。然而根据 HTML 4.01 规范,只有 input 元素才应当有这个属性。

在 ASP.NET 4 中,可以把 controlRenderingCompatibilityVersion 属性设置为 "3.5",例如:

<system.web> 
 <pages controlRenderingCompatibilityVersion="3.5"/> 
</system.web>

这时创建一个 Label 控件并禁用此控件,例如:

<asp:Label id="Label" runat="server" Text="Test" Enabled="false">

Label 控件会呈现如下的 HTML:

<span id="Label1" disabled="disabled">Test</span>

在 ASP.NET 4 中,可以把 controlRenderingCompatibilityVersion 为 "4.0",这时,当控件的 Enabled 属性设置为 false 时,只有呈现 input 元素的控件才会呈现 disabled 属性。不呈现为 HTML input 元素的控件则会呈现一个 class 属性引用一个 CSS 类,可以用来定义控件的禁用外观。例如,前面示例中展示的 Label 控件会产生下面的标记:

<span id="Span1" class="aspnetdisabled">Test</span>

为这个控件指定的类的默认值是 "aspnetdisabled"。通过设置 WebControl 类的静态属性 DisabledCssClass 可以更改这个默认值。对于控件开发人员,对特定控件使用的行为也可以使用 SupportsDisabledAttribute 属性定义。

12) 隐藏围绕隐藏域的 DIV 元素

ASP.NET 2.0 及以后的版本会把系统指定的隐藏域(例如用于存储视图状态信息的 hidden 元素)呈现在 div 元素中,这是为了遵从 XHTML 标准。然而,当 CSS 规则影响 div 元素时会导致问题。例如,它可能在页面隐藏的 div 元素上显示 1 像素的线。在 ASP.NET 4 中,包装了隐藏域的 div 元素会添加一个 CSS 类引用,如下所示:

<div class="aspNetHidden">...</div> 

接着可以定义一个 CSS 类只应用到隐藏元素。如下面所示:

<style type="text/css"> 
DIV# aspNetHidden {border:0;} 

</style> 

13) 为模板控件呈现外部表格

默认地,下面支持模板的 ASP.NET Web 服务器控件都会自动地包围在外部表格的里面并应用内联样式:

  • FormView
  • Login
  • PasswordRecovery
  • ChangePassword
  • Wizard
  • CreateUserWizard

一个新的名为 RenderOuterTable 的属性添加到这些控件上来允许外部表格从标记中移除。例如,考虑下面的 FormView 控件的例子:

<asp:FormView ID="FormView1" runat="server"> 
 <ItemTemplate> 
Content 
 </ItemTemplate> 

</asp:FormView>

这个标记会呈现下面的输出到页面,其中包含一个 HTML 表格:

<table cellspacing="0" border="0" id="Table1" style="border-collapse:collapse;"> 
 <tr> 
 <td colspan="2"> 
Content 
 </td> 
 </tr> 

</table> 

为了阻止表格被呈现,可以设置 FormView 控件的 RenderOuterTable 属性为 false,如下面所示:

<asp:FormView ID="FormView1" runat="server" RenderOuterTable="false">

这时输出就不会有 table, tr, 和 td 元素了,只有模板中的内容。

这个增强使得使用 CSS 对内容设置样式变得更加容易,因为没有未料到的标签被呈现。

注意这个变化禁止了对 Visual Studio 2010 设计器中的自动格式化功能的支持。

14) ListView 控件增强

ListView 控件在 ASP.NET 4 中变得更容易使用了。旧版本的这个控件需要指定一个布局模板,其中包含一个规定 ID 的服务器控件。下面的例子展示了在 ASP.NET 3.5 中 ListView 的典型示例:

<asp:ListView ID="ListView1" runat="server"> 
 <LayoutTemplate> 
 <asp:PlaceHolder ID="ItemPlaceHolder" runat="server"></asp:PlaceHolder> 
 </LayoutTemplate> 
 <ItemTemplate> 
 <%
 1: Eval("LastName")
%>
</ItemTemplate>
</asp:ListView>

在ASP.NET 4中,ListView 控件不再需要布局模板,前面的例子可以由下面的标记取代:

<asp:ListView ID="ListView1" runat="server"> 
 <ItemTemplate> 
 <%
 1: Eval("LastName")
%>
</ItemTemplate>
</asp:ListView>

15) CheckBoxList 和 RadioButtonList 控件增强

在 ASP.NET 3.5 中,使用两个值(Flow 和 Table)可以为 CheckBoxList 和 RadioButtonList 指定布局。例如:

<asp:CheckBoxList ID="CheckBoxList1" runat="server" RepeatLayout="Flow"> 
 <asp:ListItem Text="CheckBoxList" Value="cbl" /> 
</asp:CheckBoxList> 

<asp:RadioButtonList runat="server" RepeatLayout="Table"> 
 <asp:ListItem Text="RadioButtonList" Value="rbl" /> 
</asp:RadioButtonList>

默认地,控件会呈现如下类似的 HTML:

<span id="Span2"><input id="CheckBoxList1_0" type="checkbox" 
 name="CheckBoxList1$0" /><label for="CheckBoxList1_0">CheckBoxList</label></span> 
 
<table id="RadioButtonList1" border="0"> 
 <tr> 
 <td><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="rbl" /><label for="RadioButtonList1_0">RadioButtonList</label></td> 
 </tr> 
</table>

因为这些控件包含项的列表,要呈现语义正确的 HTML,应当使用 HTML 列表(li)呈现内容。

在 ASP.NET 4 中,CheckBoxList 和 RadioButtonList 控件的 RepeatLayout 属性支持两个新值:OrderedList 和 UnorderedList。

下面的例子展示了如何使用这些新值:

<asp:CheckBoxList ID="CheckBoxList1" runat="server" 
 RepeatLayout="OrderedList">
 <asp:ListItem Text="CheckBoxList" Value="cbl" />
</asp:CheckBoxList> 

<asp:RadioButtonList ID="RadioButtonList1" runat="server" 
 RepeatLayout="UnorderedList">
 <asp:ListItem Text="RadioButtonList" Value="rbl" />
</asp:RadioButtonList>

产生的HTML:

<ol id="CheckBoxList1">
 <li><input id="CheckBoxList1_0" type="checkbox" name="CheckBoxList1$0" value="cbl" /><label for="CheckBoxList1_0">CheckBoxList</label></li>
</ol>
 
<ul id="RadioButtonList1">
 <li><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="rbl" /><label for="RadioButtonList1_0">RadioButtonList</label></li>
</ul>

注意,如果把 RepeatLayout 设置为新值,RepeatDirection 属性就不能再使用,否则会在运行时抛出异常。这些控件的视觉布局可使用 CSS 定义。

16) Menu 控件增强

在 ASP.NET 4 之前,Menu 控件呈现为一系列 HTML 表格。这使得应用 CSS 样式变得很困难,而且也不遵从可访问性标准。

在 ASP.NET 4 中,这个控件现在使用语义标记呈现,即由一个无序列表和列表元素组成。下面的例子展示了 Menu 控件在页面中的标记:

<asp:Menu ID="Menu1" runat="server"> 
 <Items> <asp:MenuItem Text="Home" Value="Home" /> 
 <asp:MenuItem Text="About" Value="About" /> 
 </Items>
</asp:Menu> 

当页面呈现时,控件会产生下列 HTML:

<div id="Menu1"> 
 <ul> 
 <li><a href="#" onclick="...">Home</a></li> 
 <li><a href="#" onclick="...">About</a></li> 
 </ul> 
</div> 
<script type="text/javascript">
 1: 
 2: new Sys.WebForms.Menu('Menu1'); 
</script>

除了呈现的增强,菜单的键盘导航也使用焦点管理改进了。当 Menu 控件获得焦点时,可以使用箭头键导航元素。Menu 控件现在还能附加可访问富互联网应用程序(ARIA)角色和属性,以增强可访问能力。(见Menu ARIA guidelines

为菜单控件的样式呈现在页面顶部的样式块中,而不是内联在呈现的 HTML 元素中。如果想完全控制对控件的样式,可以把新的 IncludeStyleBlock 属性设置为 false,这会让样式块不被发出。另外,可以先运行页面,把呈现的样式块复制到外部 CSS 文件,再把控件的 IncludeStyleBlock 属性设置为 false。这样菜单外观就被定义到外部样式表中了。

17) Wizard 和 CreateUserWizard 控件

ASP.NET Wizard 和 CreateUserWizard 控件支持模板,用来定义呈现的 HTML。(CreateUserWizard 派生自 Wizard)下面的示例展示了一个完全模板化的 CreateUserWizard 控件的标记:

<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" ActiveStepIndex="0"> 
 <HeaderTemplate> 
 </HeaderTemplate>
 
 <SideBarTemplate> 
 </SideBarTemplate>
 
 <StepNavigationTemplate> 
 </StepNavigationTemplate> 

 <StartNavigationTemplate> 
 </StartNavigationTemplate> 

 <FinishNavigationTemplate> 
 </FinishNavigationTemplate> 

 <WizardSteps> 
 <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server"> 
 <ContentTemplate> 
 </ContentTemplate>
 
 <CustomNavigationTemplate> 
 </CustomNavigationTemplate>

 </asp:CreateUserWizardStep>
 
 <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server"> 
 <ContentTemplate> 
 </ContentTemplate> 
 </asp:CompleteWizardStep> 

 </WizardSteps>
</asp:CreateUserWizard> 

控件呈现类似下面的 HTML:

<table cellspacing="0" cellpadding="0" border="0" id="CreateUserWizard1" style="border-collapse:collapse;"> 
 <tr> 
 <td>Header</td> 
 </tr> 
 <tr style="height:100%;"> 
 <td> 
 <table cellspacing="0" cellpadding="0" border="0" style="height:100%;width:100%;border-collapse:collapse;"> 
 <tr> 
 <td style="height:100%;width:100%;"></td> 
 </tr> 
 </table> 
 </td> 
 </tr> 
 <tr> 
 <td align="right"></td> 
 </tr> 
</table> 

在 ASP.NET 3.5 SP1 中,尽管可以改变模板的内容,但仍然对控制 Wizard 控件的输出有限制。在ASP.NET 4中,可以创建一个 LayoutTemplate 模板并插入 PlaceHolder 控件(使用保留的名称)来指示想让 Wizard 控件如何呈现。下面的示例展示了这个过程:

<asp:CreateUserWizard ID="CreateUserWizard1" runat="server" ActiveStepIndex="1"> 
 <LayoutTemplate> 
 <asp:PlaceHolder ID="headerPlaceholder" runat="server" /> 
 <asp:PlaceHolder ID="sideBarPlaceholder" runat="server" /> 
 <asp:PlaceHolder id="wizardStepPlaceholder" runat="server" /> 
 <asp:PlaceHolder id="navigationPlaceholder" runat="server" /> 
 </LayoutTemplate> 
 <HeaderTemplate> 
Header 
 </HeaderTemplate> 
 <WizardSteps> 
 <asp:CreateUserWizardStep runat="server"> 
 <ContentTemplate> 
 </ContentTemplate> 
 </asp:CreateUserWizardStep> 
 <asp:CompleteWizardStep runat="server"> 
 <ContentTemplate> 
 </ContentTemplate> 
 </asp:CreateUserWizardStep> 
 </WizardSteps> 
</asp:CreateUserWizard>

示例包含了下列在 LayoutTemplate 元素中的命名占位符:

  • headerPlaceHolder——在运行时,这会被 HeaderTemplate 元素中的内容取代
  • sideBarPlaceHolder——在运行时,这会被 SideBarTemplate 元素的内容取代
  • wizardStepPlaceHolder——在运行时,这会被 WizardStepTemplate 元素的内容取代
  • navigationPlaceHolder——在运行时,这会被定义的导航模板所取代

示例中的标记使用占位符呈现了下列的 HTML(定义的模板中没有实际定义的内容):

<span>
</span>

唯一的不是用户定义的 HTML 是 span 元素。(我们期望在未来的发布中,甚至连 span 元素也不会呈现。)

4. ASP.NET MVC

2009年3月,ASP.NET MVC 作为一个附加框架加入到 ASP.NET 3.5 SP1 中。 Visual Studio 2010 包含了 ASP.NET MVC 2,它包含了新的特性和能力。

1) Area 支持

Area 可以把分组的控制器和视图放到大型应用程序的区域(sections)中,区域之间是相对隔离的。每个 area 都可以作为单独的 ASP.NET MVC 项目实现,然后由主应用程序引用。这样当构建一个大型应用程序时可以帮助管理复杂性,并使得多个团队在一个应用程序上一直工作变得容易了。

2) 数据注解特性验证支持(Data-Annotation Attribute Validation Support)

DataAnnotations 特性能够把验证逻辑附加到模型上。DataAnnotations 特性是在 ASP.NET 3.5 SP1 的 ASP.NET 动态数据中引入的,这些特性已经集成到默认的模型绑定器(model binder)上并提供一种元数据驱动的验证用户输入的方法。

3) 模板化助手(Templated Helper)

模板化助手能够自动自动地用数据类型把编辑和显示模板关联起来。例如,可以使用模板助手指定为 System.DateTime 值自动地呈现一个日期拾取 UI 元素。这和 ASP.NET 动态数据中的字段模板相似。

Html.EditorFor 和 Html.DisplayFor 助手方法拥有对呈现标准数据类型以及有多个属性的复杂对象的内置支持。它们还可以通过把数据注解特性(如 DisplayName 和 ScaffoldColumn)应用到 ViewModel 对象来定制呈现。

经常想更深入地从 UI 助手呈现输出,并对产生的内容进行完全的控制。Html.EditorFor 和 Html.DisplayFor 助手方法使用模板机制来支持这个功能,它通过定义外部模板来覆盖和控制呈现的输出。模板可以为一个类单独呈现。

5. 动态数据(Dynamic Data)

动态数据是在 2008 年中在 .NET Framework 3.5 SP1 中引入的。这个特性提供了许多创建数据驱动应用程序的增强。包括:

  • 一个为快速构建数据驱动网站的 RAD 体验
  • 基于数据模型中定义的限制的自动验证
  • 通过使用字段模板轻易地在 GridView 和 DetailsView 控件中更改为字段产生标记的能力。

更多信息,参见 Dynamic Data 文档

对于 ASP.NET 4,动态数据已经对开发人员做了增强,甚至能够更加强大地快速构建数据驱动的网站。

1) 为现存项目启用动态数据

.NET Framework 3.5 SP1 中的动态数据带来了以下新特性:

  • 字段模板——这些为数据绑定控件提供了基于数据类型的模板。字段模板提供了更加简单的方法来定制数据控件的外观。
  • 验证——动态数据在数据类上使用特性(attribute)来指定验证,这些验证是为通用的场景准备的,像必填字段,范围字段,类型检查,模式匹配(使用正则表达式),和自定义验证。验证是由数据控件实施的。

然而,这些特性需要下面的要求:

  • 数据访问层必须基于实体框架(Entity Framework)或 LINQ to SQL。
  • 支持这些特性的数据源控件只有 EntityDataSource 和 LinqDataSource 控件。
  • 需要使用动态数据或动态数据实体模板创建的Web项目,才能拥有所有支持这些特性必需的文件。

在 ASP.NET 4 中动态数据的主要目标是启用对任意 ASP.NET 应用程序的动态数据新功能。下面的例子展示了在现存页面中利用动态数据功能为控件产生标记的功能:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True" 
 DataKeyNames="ProductID" DataSourceID="LinqDataSource1"> 
</asp:GridView> 
<asp:LinqDataSource ID="LinqDataSource1" runat="server" 
 ContextTypeName="DataClassesDataContext" EnableDelete="True" EnableInsert="True" 
 EnableUpdate="True" TableName="Products"> 

</asp:LinqDataSource>

下面的代码必须添加到页面中,才能为这些控件启用动态数据支持:

GridView1.EnableDynamicData(typeof(Product));

当 GridView 控件处于编辑状态时,动态数据会自动验证输入的数据。如果验证失败,错误消息会显示出来。

这个功能还提供了其他好处,例如能够指定插入模式的默认值。没有动态数据,想要为字段实现默认值,必须附加一个事件,定位控件(使用 FindControl),设置值。在 ASP.NET 4 中,EnableDynamicData 调用支持一个为对象的任何字段传递默认值的第二参数。例如:

DetailsView1.EnableDynamicData(typeof(Product), new { ProductName = "DefaultName" });

2) 声明式 DynamicDataManager 控件语法

DynamicDataManager 控件已经增强,所以可以声明式地配置它,就像 ASP.NET 中的大多数控件一样,而不是只能用代码。例如:

<asp:DynamicDataManager ID="DynamicDataManager1" runat="server" 
 AutoLoadForeignKeys="true"> 
 <DataControls> 
 <asp:DataControlReference ControlID="GridView1" /> 
 </DataControls> 
</asp:DynamicDataManager> 
<asp:GridView id="GridView1" runat="server"> 
</asp:GridView>

这个启用了动态数据行为的标记在 DynamicDataManager 控件的 DataControls 节中被引用了。

3) 实体模板

实体模板提供了不需要创建自定义页面就能定制数据布局的新方法。页面模板使用 FormView 控件(取代旧版本使用的 DetailsView 控件)和 DynamicEntity 控件来呈现实体模板。这就能对动态数据呈现的标记有更多的控制。

下面的列表展示了新项目布局模板包含的实体模板:

\DynamicData\EntityTemplates
\DynamicData\EntityTemplates\Default.ascx
\DynamicData\EntityTemplates\Default_Edit.ascx
\DynamicData\EntityTemplates\Default_Insert.ascx

EntityTemplate 目录包含如何显示数据模型对象的模板。默认地,对象通过使用 Default.ascx 模板呈现。下面的例子展示了 Default.ascx 控件:

<asp:EntityTemplate runat="server" ID="TemplateContainer1"> 
 <ItemTemplate> 
 <tr> 
 <td> 
 <asp:Label ID="Label1" runat="server" OnInit="Label_Init" /> 
 </td> 
 <td> 
 <asp:DynamicControl runat="server" OnInit="DynamicControl_Init" /> 
 </td> 
 </tr> 
 </ItemTemplate> 
</asp:EntityTemplate> 

默认模板可以编辑来改变整个站点的外观。这些模板可以进行显示、编辑和插入操作。新模板可以基于数据对象的名称添加,这样才能只改变一种类型的对象的外观。例如,可以添加下面的模板:

\DynamicData\EntityTemplates\Products.aspx

模板可能包含下面的标记:

<tr> 
 <td>Name</td> 
 <td><asp:DynamicControl runat="server" DataField="ProductName" /></td> 
 <td>Category</td> 
 <td><asp:DynamicControl runat="server" DataField="Category" /></td> 
</tr>

新实体模板通过使用新的 DynamicEntity 显示在页面上。在运行时,这个控件使用实体模板的内容代替。下面的标记展示了使用实体模板的 Detail.aspx 页面模板中的 FormView 控件。注意标记中的 DynamicEntity 元素。

<asp:FormView runat="server" ID="FormView1" 
 DataSourceID="DetailsDataSource" 
 OnItemDeleted="FormView1_ItemDeleted"> 
 <ItemTemplate> 
 <table class="DDDetailsTable" cellpadding="6"> 
 <asp:DynamicEntity runat="server" /> 
 <tr class="td"> 
 <td colspan="2"> 
 <asp:DynamicHyperLink ID="EditHyperLink" runat="server" 
 Action="Edit" Text="Edit" /> 
 <asp:LinkButton ID="DeleteLinkButton" runat="server" 
 CommandName="Delete" 
 CausesValidation="false" 
 OnClientClick='return confirm("Are you sure you want to delete this item?");' 
 Text="Delete" /> 
 </td> 
 </tr> 
 </table> 
 </ItemTemplate> 
</asp:FormView>

4) 为 URL 和 E-mail 地址设计的新字段模板

ASP.NET 4 引入了两个新的内置字段模板,EmailAddress.ascx 和 Url.ascx。这些模板用于使用 DataType 特性标记为 EmailAddress 或 Url 的字段。对于 EmailAddress 对象,字段作为超链接显示,并使用 mailto: 协议创建。当用户点击链接,它打开用户的 e-mail 客户端并创建一个简略的消息。作为 Url 类型的对象则以普通超链接显示。

下面的例子展示了字段如何标记。

[DataType(DataType.EmailAddress)] 
public object HomeEmail { get; set; } 

[DataType(DataType.Url)] 
public object Website { get; set; }

5) 使用 DynamicHyperLink 控件创建链接

动态数据使用新的路由特性(.NET Framework 3.5 SP1 加入)来控制终端用户访问网站时看到的 URL。新的 DynamicHyperLink 控件使构造到页面的链接变得容易。下面的例子展示了如何使用 DynamicHyperLink 控件:

<asp:DynamicHyperLink ID="ListHyperLink" runat="server" 
 Action="List" TableName="Products"> 
Show all products 
</asp:DynamicHyperLink>

6) 支持数据模型中的继承

实体框架和 LINQ to SQL 都支持数据模型中的继承。例如数据库中有一个 InsurancePolicy 表,还有两个表 CarPolicy 和 HousePolicy,这两个表拥有和 InsurancePolicy 相同的字段并添加了更多字段。动态数据已经修改为能够理解数据模型中继承的对象并支持对继承数据表的 scaffolding(这个单词怎么翻译?)。

7) 支持多对多关系(仅对实体框架)

实体框架拥有在数据表之间进行多对多关联的丰富支持,这是通过在实体对象中以集合暴露关联来实现的。新的 ManyToMany.ascx 和 ManyToMany_Edit.ascx 字段模板已经添加了对有多对多关联数据的显示和编辑的支持。

8) 对控件显示和支持枚举的新特性(Attribute)

DisplayAttribute 添加了字段如何显示的额外控制。DisplayName 特性(Attribute)在旧版本的动态数据中允许更改作为字段标题的名称。新的 DisplayAttribute 类可以指定更多关于显示字段的选项,例如字段显示的顺序和字段是否用作过滤器。The attribute also provides independent control of the name used for the labels in a GridView control, the name used in a DetailsView control, the help text for the field, and the watermark used for the field (if the field accepts text input).

EnumDataTypeAttribute 用于把字段映射到枚举。当把这个特性应用到字段时,就指定了枚举类型。动态数据使用新的 Enumeration.ascx 字段模板为显示和编辑枚举值创建 UI。模板从数据库把值映射到枚举中的值。

9) 对过滤器的增强支持

动态数据 1.0 内置对 Boolean 列和外键列的过滤器。过滤器不允许指定它们是否显示或者以什么顺序显示。新的 DisplayAttribute 同时解决了这两个问题。

另外一个增强是过滤器支持已经重写来使用 Web Forms 的新特性。这可以不需要了解过滤器使用的数据源控件就能创建过滤器。有了这些扩展,过滤器同样也已经变成了模板控件,这样就允许添加新的。最后,DisplayAttribute 类允许重写默认过滤器,以同样的方式 UIHint 允许重写列的默认字段模板。

6. Visual Studio 2010 Web 开发增强

更好的 CSS 兼容性,通过 HTML 和 ASP.NET 标记片断提高生产力,以及新的动态的智能感知 JavaScript。

1) 增强的 CSS 兼容性

Visual Studio 2010 中的 Visual Web Developer 设计器已经提高了对 CSS 2.1 标准的遵从。设计器更好的保留了 HTML 源集成而且更加健壮。

2) HTML 和 JavaScript 代码片断

在 HTML 编辑器中,智能感知会自动完成标签名称。智能感知片断特性会自动完成整个标签甚至更多。在 Visual Studio 2010 中,智能感知片断支持 JavaScript,以及旧版就支持的 C# 和 VB。

Visual Studio 2010 包含超过200个片断,来帮助自动完成通用的 ASP.NET 和 HTML 标签,包括必须的属性(例如 runat="server")和特定标签的通用属性(例如 ID, DataSourceID, ControlToValidate, Text)。

可以下载额外的片断,或编写自己的片断,让自己的团队用于通用任务。

3) JavaScript 智能感知增强

在 Visual Studio 2010 中,JavaScript 智能感知已经重新设计来提供更加丰富的编辑体验。智能感知现在可以识别被方法(例如 registerNamespace 方法)或其他 JavaScript 框架的类似技术动态生成的对象。性能也提升了,分析大型脚本库和显示智能感知几乎没有处理延迟。兼容性也提升了,可以支持几乎所有第三方库和支持多种代码风格。Documentation comments are now parsed as you type and are immediately leveraged by IntelliSense.

7. 使用 Visual Studio 2010 开发 Web 应用程序

当 ASP.NET 开发人员部署 Web 应用程序时,他们经常发现他们会遇到下列问题:

  • 部署到共享的宿主站点需要诸如 FTP 的技术,这可能会比较缓慢。另外,必须手工执行诸如运行 SQL 脚本的任务来配置数据库,以及必须更改 IIS 设置,例如配置一个虚拟目录文件夹作为应用程序。
  • 在企业级环境中,除了部署 Web 应用程序文件,管理员必须经常修改 ASP.NET 配置文件和 IIS 设置。数据库管理员必须运行一系列 SQL 脚本来让应用程序的数据库运行。这些安装很费人力,经常要消耗数小时来完成,还要小心记录。

Visual Studio 2010 包含了解决这些问题的技术,使得可以无缝地部署 Web 应用程序。其中一个技术是 IIS Web Deployment Tool(MsDeploy.exe)。

VS2010 中的 Web 部署特性包含以下主要方面:

  • Web 打包
  • Web.config 转换
  • 数据库部署
  • One-click 发布 Web 应用程序

下面是有关这些特性的细节。

1) Web 打包

VS2010 使用 MSDeploy 工具为应用程序创建压缩文件(.zip),这称为 Web 包(Web package)。包文件包含关于应用程序的元数据以及下面的内容:

  • IIS 设置,包括应用程序池设置,错误页面设置,等等。
  • 实际的 Web 内容,包括 Web 页面,用户控件,静态内容(图像和 HTML 文件),等等。
  • SQL Server 数据库模式和数据。
  • 安全证书,在GAC中安装的组件,注册表设置,等等。

Web 包可以拷贝到任何服务器上,然后使用 IIS 管理器(IIS Manager)手动安装。此外,对于自动部署,包还可以通过命令行命令使用部署 API 来安装。

VS2010 提供了内置的 MSBuild 任务和目标来创建 Web 包。更多信息,参见 MSDN 网站的 ASP.NET Web Application Project Deployement Overview,和 Vishal Joshi 的博客文章 10+20 reasons why you should create a Web Package

2) Web.config 转换

对于 Web 应用程序部署,VS2010 引入了 XML 文档转换(XDT),这个特性用于把 Web.config 文件从开发设置转换到生产设置。转换设置是在名为 web.debug.config、web.release.config 等文件中指定的。(这些文件的名称匹配 MSBuild 配置)转换文件只包含需要放到部署的 web.config 文件中的变化。通过使用简单的语法就可以指定变化。

下面的例子展示了 web.release.config 文件的一部分,可能为发布配置(release configuration)部署生产的。Replace 关键字表示在部署过程中 Web.config 文件中的 connectionString 节点会使用例子中列出的值代替。

<connectionStrings xdt:Transform="Replace"> 
 <add name="BlogDB" connectionString="connection string detail]" />
</connectionStrings> 

更多信息,参见 MSDN 网站上的 Web.config Transformation Syntax for Web Application Project Deployement 和 Vishal Joshi 的博客文章Web Deployment: Web.config Transformation

3) 数据库部署

VS2010 部署包可以包含 SQL Server 数据库的依赖。作为包定义的一部分,可以为源数据库提供连接连接字符串。当创建 Web 包时,VS2010 会为数据库模式和数据(可选)创建 SQL 脚本,然后把这些脚本添加到包中。也可以提供自定义 SQL 脚本并指定在服务器中运行的顺序。在部署期间,可以提供一个适合目标服务器的连接字符串,部署进程随即会使用这个连接字符串运行脚本创建数据库模式并添加数据。

另外,通过使用一键发布,当应用程序发布到远程共享宿主站点时可以配置部署来直接发布数据库。更多信息,参见 MSDN 网站上的 How to: Deploy a Database With a Web Application Project 和 Vishal Joshi 的博客文章Database Deployment with VS 2010

4) One-Click 发布 Web 应用程序

VS2010 还可以使用 IIS 远程管理服务来把 Web 应用程序发布到远程服务器。可以为宿主账户或测试服务器或临时服务器(staging server)创建一个发布描述(publish profile)。每个描述都安全地保存了适当的证书(credentials)。然后通过使用 Web 一键发布工具栏一键就可以部署到任何目标服务器了。使用 VS2010 还可以通过使用 MSBuild 命令行发布。这要配置团队生成环境在持续集成模型中包含发布。更多信息,参见 MSDN 网站上的How to: Deploy a Web Application Project Using One-Click Publish and Web Deploy 和 Vishal Joshi 的博客文章Web 1-Click Publish with VS 2010。To view video presentations about Web application deployment in Visual Studio 2010, seeVS 2010 for Web Developer Previews on Vishal Joshi's blog.

5) 资源

下面的网站提供了关于 ASP.NET 4 和 Visual Studio 2010 的额外信息:

推荐:在 Visual Studio 2012 中创建 ASP.Net Web Service

在 Visual Studio 2012 中创建 ASP.Net Web Service,步骤非常简单。如下: 第一步:创建一个“ASP.Net Empty Web Application”项目 创建一个“ASP.Net Empty W

声明:本文是ASP.NET 白皮书 ASP.NET 4 and Visual Studio 2010 Web Development Overview 的阅读摘要,只是本人的学习记录,并非完整翻译,仅供参考,由于水平有限,有些翻译未必准确。点击下

相关阅读排行


相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。