ASP.NET 4 和 Visual Studio 2010 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 可以找到更多的示例。

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 的額外信息:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章