共用方式為


ASP.NET 4.5 的 Web Forms 新功能

Web Camp 小組

新版本的 ASP.NET Web Form引進了一些改善,著重於在處理數據時改善用戶體驗。

在舊版的 Web Form,使用數據系結發出對象成員的值時,您使用了數據系結運算式 Bind() 或 Eval()。 在新版本的 ASP.NET 中,您可以使用新的 ItemType 屬性來宣告控件將要繫結的數據類型。 設定此屬性可讓您使用強型別變數來接收Visual Studio開發體驗的完整優點,例如IntelliSense、成員導覽和編譯時間檢查。

透過數據綁定控件,您現在可以指定自己的自定義方法,以選取、更新、刪除和插入數據,簡化頁面控件與應用程式邏輯之間的互動。 此外,模型系結功能已新增至 ASP.NET,這表示您可以將頁面的數據直接對應至方法類型參數。

使用最新版本的 Web Form,驗證使用者輸入也應該更容易。 您現在可以使用 System.ComponentModel.DataAnnotations 命名空間的驗證屬性來標註您的模型類別,並要求所有網站控制使用該資訊驗證使用者輸入。 Web Form 中的用戶端驗證現在已與 jQuery 整合,提供更簡潔的用戶端程式代碼和不顯眼的 JavaScript 功能。

在要求驗證區域中,已進行改善,讓您更容易選擇性地關閉應用程式特定部分的要求驗證,或讀取無效的要求數據。

已對 Web Form 伺服器控制件進行一些改善,以利用 HTML5 的新功能:

  • TextBox 控制件的 TextMode 屬性已更新,以支援新的 HTML5 輸入類型,例如電子郵件、日期時間等等。
  • FileUpload 控件現在支援從支援此 HTML5 功能的瀏覽器上傳多個檔案。
  • 驗證程式控制項現在支援驗證 HTML5 輸入元素。
  • 新的 HTML5 元素,其屬性代表 URL 現在支援 runat=“server”。 因此,您可以在 URL 路徑中使用 ASP.NET 慣例,例如 ~ 運算符來代表應用程式根目錄(例如 <,視訊 runat=“server” src=“~/myVideo.wmv”></video>)。
  • UpdatePanel 控件已修正,以支援張貼 HTML5 輸入字段。

在官方 ASP.NET 入口網站中,您可以找到 ASP.NET WebForms 4.5: ASP.NET 4.5 和 Visual Studio 2012 新功能的更多範例

所有範例程式代碼和代碼段都包含在 Web Camp 訓練工具包

目標

在此實際操作實驗室中,您將瞭解如何:

  • 使用強型別的數據系結表達式
  • 在 Web Form 中使用新的模型系結功能
  • 使用值提供者將頁面數據對應至程式代碼後置方法
  • 使用數據批注進行使用者輸入驗證
  • 在 Web Form 中利用 jQuery 的不顯眼客戶端驗證
  • 實作細微的要求驗證
  • 在 Web Form 中實作異步頁面處理

必要條件

您必須有下列專案才能完成此實驗室:

設定

安裝代碼段

為了方便起見,您將在此實驗室中管理的大部分程式代碼都可以作為Visual Studio代碼段使用。 若要安裝代碼段,請執行 .\Source\Setup\CodeSnippets.vsi 檔案。

如果您不熟悉 Visual Studio 代碼段,而且想要瞭解如何使用這些代碼段,您可以參閱本檔中的附錄「附錄 C:使用代碼段」。

練習

此實際操作實驗室包含下列練習:

  1. 練習 1:ASP.NET Web Form中的模型系結
  2. 練習 2:數據驗證
  3. 練習 3:ASP.NET Web Form中的異步頁面處理

注意

每個練習都會隨附一個 End 資料夾,其中包含完成練習之後應該取得的結果解決方案。 如果您需要完成練習的其他協助,您可以使用此解決方案作為指南。

完成此實驗室的估計時間: 60 分鐘

練習 1:ASP.NET Web Form中的模型系結

新版本的 ASP.NET Web Form引進了一些增強功能,著重於在處理數據時改善體驗。 在此練習中,您將了解強型別的數據控制項和模型系結。

工作 1 - 使用強型別數據系結

在這項工作中,您將探索 ASP.NET 4.5 中可用的新強型別系結。

  1. 開啟位於Source/Ex1-ModelBinding/Begin/ 資料夾的 Begin 方案。

    1. 您必須先下載一些遺漏的 NuGet 套件,才能繼續。 若要這樣做,請按兩下 [ 專案] 功能表,然後選取 [ 管理 NuGet 套件]。

    2. 在 [ 管理 NuGet 套件 ] 對話框中,按兩下 [ 還原 ] 以下載遺漏的套件。

    3. 最後,按兩下 [建置建置方案] 來建 | 置方案。

      注意

      使用 NuGet 的優點之一是,您不需要寄送專案中的所有連結庫,以減少專案大小。 使用 NuGet Power Tools 時,藉由在 Packages.config 檔案中指定套件版本,您就能夠在第一次執行專案時下載所有必要的連結庫。 這就是為什麼您必須從此實驗室開啟現有的解決方案之後執行這些步驟。

  2. 開啟 [Customers.aspx] 頁面。 將未編號的清單放在主控制件中,並在 內包含重複項控制件,以列出每個客戶。 將重複程式名稱設定為 customersRepeater, 如下列程式代碼所示。

    在舊版的 Web Form,當使用數據系結在您要系結的對象上發出成員的值時,您會使用數據系結運算式,以及呼叫 Eval 方法,以字串形式傳入成員的名稱。

    在運行時間,這些對 Eval 的呼叫會針對目前系結的物件使用反映,以讀取具有指定名稱的成員值,並在 HTML 中顯示結果。 此方法可讓您輕鬆地針對任意、未調整的數據進行數據系結。

    不幸的是,您在 Visual Studio 中失去了許多絕佳的開發時間體驗功能,包括成員名稱的 IntelliSense、瀏覽的支援(例如移至定義),以及編譯時間檢查。

    ...
    <asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
      <h3>Customers</h3>
      <ul>
        <asp:Repeater ID="customersRepeater" runat="server">
          <ItemTemplate>
                <li>
                    <%# Eval("FirstName") %>
                    <%# Eval("LastName") %>
                </li>
          </ItemTemplate>
        </asp:Repeater>
      </ul>
      <a href="CustomerDetails.aspx">Add a New Customer</a>
    </asp:Content>
    
  3. 開啟Customers.aspx.cs檔案。

  4. 新增下列 using 陳述式。

    using System.Linq;
    
  5. 在 Page_Load 方法中,新增程序代碼,以將客戶清單填入重複項。

    (代碼段 - Web Form 實驗室 - Ex01 - 系結客戶資料來源

    protected void Page_Load(object sender, EventArgs e)
    {
        using (var db = new WebFormsLab.Model.ProductsContext())
        {
            this.customersRepeater.DataSource = db.Customers.ToList();
            this.customersRepeater.DataBind();
        }
    }
    

    解決方案會搭配 CodeFirst 使用 EntityFramework 來建立及存取資料庫。 在下列程式代碼中,customersRepeater 會系結至具體化查詢,以傳回資料庫中的所有客戶。

  6. F5 執行解決方案,並移至 [客戶 ] 頁面以查看重複程式的運作情形。 當解決方案使用 CodeFirst 時,資料庫將會在執行應用程式時,在本機 SQL Express 實例中建立並填入資料庫。

    使用重複項列出客戶

    使用重複項列出客戶

    注意

    在 Visual Studio 2012 中,IIS Express 是預設的 Web 開發伺服器。

  7. 關閉瀏覽器並返回 Visual Studio。

  8. 現在取代 實作以使用強型別系結。 開啟Customers.aspx頁面,並使用重複項中的新 ItemType 屬性,將 Customer 類型設定為系結類型。

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
      <ul>
        <asp:Repeater ID="customersRepeater" 
                      ItemType="WebFormsLab.Model.Customer" 
                      runat="server">
          <ItemTemplate>
             ...
          </ItemTemplate>
        </asp:Repeater>
      </ul>
      <a href="CustomerDetails.aspx">Add a New Customer</a>
    </asp:Content>
    

    ItemType 屬性可讓您宣告控件要系結的數據類型,並可讓您在數據綁定控件內使用強型別系結。

  9. 以下列程序代碼取代 ItemTemplate 內容。

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
      ...
      <ul>
        <asp:Repeater ID="customersRepeater" ItemType="WebFormsLab.Model.Customer" runat="server">
          <ItemTemplate>
            <li>
              <a href="CustomerDetails.aspx?id=<%#: Item.Id %>">
                <%#: Item.FirstName %> <%#: Item.LastName %>
              </a>
            </li>
          </ItemTemplate>
        </asp:Repeater>
      </ul>
      <a href="CustomerDetails.aspx">Add a New Customer</a>
    </asp:Content>
    

    上述方法的一個缺點是,對 Eval() 和 Bind() 的呼叫是晚期綁定的 ,這表示您傳遞字串來代表屬性名稱。 這表示您不會取得成員名稱的 Intellisense、程式代碼瀏覽的支援(例如移至定義),也不會取得編譯時間檢查支援。

    設定 ItemType 屬性會導致在數據系結表達式的範圍中產生兩個新的具型別變數: ItemBindItem。 您可以在數據系結運算式中使用這些強型別變數,並取得 Visual Studio 開發體驗的完整優點。

    表達式中使用的 「 」 會自動將輸出 HTML 編碼,以避免安全性問題(例如跨網站腳本攻擊)。 此表示法自 .NET 4 開始可供回應寫入使用,但現在也可用於數據系結表達式。

    注意

    Item 成員適用於單向系結。 如果您想要執行雙向系結, 請使用 BindItem 成員。

    強型別系結中的 IntelliSense 支援

    強型別系結中的 IntelliSense 支援

  10. F5 執行解決方案,並移至 [客戶] 頁面,以確定變更如預期般運作。

    列出客戶詳細數據

    列出客戶詳細數據

  11. 關閉瀏覽器並返回 Visual Studio。

工作 2 - 在 Web Form 中引進模型系結

在舊版的 ASP.NET Web Form中,當您想要執行雙向數據系結時,您需要使用數據源物件。 這可能是對象數據源、SQL 數據源、LINQ 數據源等等。 不過,如果您的案例需要自定義程式碼來處理數據,則需要使用對象數據源,這帶來了一些缺點。 例如,您需要避免複雜的類型,而且在執行驗證邏輯時需要處理例外狀況。

在新版本的 ASP.NET Web Form數據綁定控件支援模型系結。 這表示您可以直接在數據綁定控件中指定選取、更新、插入和刪除方法,以從程式代碼後置檔案或另一個類別呼叫邏輯。

若要瞭解這一點,您將使用 GridView,使用新的 SelectMethod 屬性列出產品類別。 這個屬性可讓您指定擷取 GridView 資料的方法。

  1. 開啟Products.aspx頁面,並包含 GridView。 設定 GridView,如下所示使用強型別系結,並啟用排序和分頁。

    <asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
     <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryID">
        <Columns>
          <asp:BoundField DataField="CategoryId" HeaderText="ID" SortExpression="CategoryId" />
          <asp:BoundField DataField="CategoryName" HeaderText="Name" SortExpression="CategoryName" />
          <asp:BoundField DataField="Description" HeaderText="Description" />
          <asp:TemplateField HeaderText="# of Products">
            <ItemTemplate><%#: Item.Products.Count %></ItemTemplate>
          </asp:TemplateField>
        </Columns>
      </asp:GridView>
    </asp:Content>
    
  2. 使用新的 SelectMethod 屬性來設定 GridView 以呼叫 GetCategories 方法來選取數據。

    <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
        SelectMethod="GetCategories">
      <Columns>
        <asp:BoundField DataField="CategoryId" HeaderText="ID" SortExpression="CategoryId" />
        <asp:BoundField DataField="CategoryName" HeaderText="Name" SortExpression="CategoryName" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="# of Products">
          <ItemTemplate><%#: Item.Products.Count %></ItemTemplate>
        </asp:TemplateField>
      </Columns>
    </asp:GridView>
    
  3. 開啟Products.aspx.cs程序代碼後置檔案,並新增下列using語句。

    (代碼段 - Web Form 實驗室 - Ex01 - 命名空間

    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Linq;
    using WebFormsLab.Model;
    
  4. 在 Products 類別中新增私人成員,並指派 ProductsContext 的新實例 這個屬性會儲存 Entity Framework 資料內容,讓您能夠連線到資料庫。

    public partial class Products : System.Web.UI.Page
    {
        private ProductsContext db = new ProductsContext();
        ...
    
  5. 建立 GetCategories 方法,以使用 LINQ 擷取類別清單。 查詢會包含 Products 屬性,讓 GridView 可以顯示每個類別的產品數量。 請注意,方法會傳回原始的 IQueryable 物件,代表稍後在頁面生命週期上執行的查詢。

    (代碼段 - Web Form 實驗室 - Ex01 - GetCategories

    public IQueryable<Category> GetCategories()
    {
      var query = this.db.Categories
        .Include(c => c.Products);
    
      return query;
    }
    

    注意

    在舊版 ASP.NET Web Form中,在對象數據源內容中使用您自己的存放庫邏輯啟用排序和分頁,需要撰寫您自己的自定義程式碼並接收所有必要的參數。 現在,由於數據系結方法可以傳回 IQueryable,這表示仍要執行的查詢,ASP.NET 可以負責修改查詢以新增適當的排序和分頁參數。

  6. F5 開始對網站進行偵錯,並移至 [產品] 頁面。 您應該會看到 GridView 已填入 GetCategories 方法所傳回的類別。

    使用模型系結填入 GridView

    使用模型系結填入 GridView

  7. SHIFT F5 停止偵錯+

工作 3 - 模型系結中的值提供者

模型系結不僅可讓您指定自定義方法,直接在數據綁定控件中處理您的數據,也可讓您將數據從頁面對應至這些方法的參數。 在 方法參數上,您可以使用值提供者屬性來指定值的數據源。 例如:

  • 頁面上的控件
  • 查詢字串值
  • 檢視資料
  • 工作階段狀態
  • Cookie
  • 張貼的表單數據
  • 檢視狀態
  • 也支援自定義值提供者

如果您已使用 ASP.NET MVC 4,您會發現模型系結支持類似。 事實上,這些功能取自 ASP.NET MVC,並移至 System.Web 元件,以便能夠在 Web Form 上使用它們。

在這項工作中,您將更新 GridView,依每個類別的產品數量來篩選其結果,並接收具有模型系結的篩選參數。

  1. 返回 Products.aspx 頁面。

  2. 在 GridView 頂端,新增 LabelComboBox 以選取每個類別的產品數目,如下所示。

    <h3>Categories</h3>
    <asp:Label ID="Label1" runat="server" AssociatedControlID="minProductsCount">
         Show categories with at least this number of products:
    </asp:Label>
    <asp:DropDownList runat="server" ID="minProductsCount" AutoPostBack="true">
      <asp:ListItem Value="" Text="-" />
      <asp:ListItem Text="1" />
      <asp:ListItem Text="3" />
      <asp:ListItem Text="5" />
    </asp:DropDownList>
    <br/>
    
  3. 將 EmptyDataTemplate 新增至 GridView,以在沒有具有所選產品數目的類別時顯示訊息。

    <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
        SelectMethod="GetCategories">
      <Columns>
        <asp:BoundField DataField="CategoryId" HeaderText="ID" />
        <asp:BoundField DataField="CategoryName" HeaderText="Name" />
        <asp:BoundField DataField="Description" HeaderText="Description" />
        <asp:TemplateField HeaderText="# of Products">
          <ItemTemplate><%#: Item.Products.Count %></ItemTemplate>
        </asp:TemplateField>
      </Columns>
      <EmptyDataTemplate>
          No categories found with a product count of <%#: minProductsCount.SelectedValue %>
      </EmptyDataTemplate>
    </asp:GridView>
    
  4. 開啟程式代碼後置Products.aspx.cs,並新增下列 using 語句。

    using System.Web.ModelBinding;
    
  5. 修改 GetCategories 方法以接收整數 minProductsCount 自變數,並篩選傳回的結果。 若要這樣做,請將 方法取代為下列程序代碼。

    (代碼段 - Web Form 實驗室 - Ex01 - GetCategories 2

    public IQueryable<Category> GetCategories([Control]int? minProductsCount)
    {
        var query = this.db.Categories
        .Include(c => c.Products);
    
        if (minProductsCount.HasValue)
        {
            query = query.Where(c => c.Products.Count >= minProductsCount);
        }
    
        return query;
    }
    

    minProductsCount 自變數上的[Control] 屬性會讓 ASP.NET 知道其值必須使用頁面上的控件填入。 ASP.NET 會尋找符合自變數名稱的任何控件(minProductsCount),並執行必要的對應和轉換,以將參數填入控件值。

    或者,屬性會提供多載建構函式,可讓您從何處指定控件以取得值。

    注意

    數據系結功能的其中一個目標是減少需要為頁面互動撰寫的程式代碼數量。 除了 [Control] 值提供者之外,您還可以在方法參數中使用其他模型系結提供者。 其中一些會列在工作簡介中。

  6. F5 開始對網站進行偵錯,並移至 [產品] 頁面。 在下拉式清單中選取一些產品,並注意 GridView 現在如何更新。

    使用下拉式清單值篩選 GridView

    使用下拉式清單值篩選 GridView

  7. 停止偵錯。

工作 4 - 使用模型系結進行篩選

在這項工作中,您將新增第二個子 GridView 以顯示所選類別內的產品。

  1. 開啟 [Products.aspx] 頁面,並更新 GridView 類別以自動產生 [選取] 按鈕。

    <asp:GridView ID="categoriesGrid" runat="server"
      AutoGenerateColumns="false"
      ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
      SelectMethod="GetCategories"
      AutoGenerateSelectButton="true">
    
  2. 在底部新增名為 productsGrid 的第二個 GridView 將 ItemType 設定為 WebFormsLab.Model.ProductDataKeyNames 設定為 ProductId,並將 SelectMethod 設定為 GetProducts 將 AutoGenerateColumns 設定false,並新增 ProductId、ProductName、Description 和 UnitPrice 的數據行。

    <h3>Products</h3>
    <asp:GridView ID="productsGrid" runat="server" 
        CellPadding="4"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Product"
        DataKeyNames="ProductId"
        SelectMethod="GetProducts">
        <Columns>
            <asp:BoundField DataField="ProductId" HeaderText="ID" />
            <asp:BoundField DataField="ProductName" HeaderText="Name" />
            <asp:BoundField DataField="Description" HeaderText="Description" HtmlEncode="false" />
            <asp:BoundField DataField="UnitPrice" HeaderText="Price" />
        </Columns>
        <EmptyDataTemplate>
            Select a category above to see its products
        </EmptyDataTemplate>
    </asp:GridView>
    
  3. 開啟程式代碼後置檔案Products.aspx.cs。 實作 GetProducts 方法,以從 GridView 類別接收類別識別碼,並篩選產品。 模型系結將使用 categoriesGrid 中選取的數據列來設定參數值。 由於自變數名稱和控件名稱不相符,因此您應該在 Control 值提供者中指定控制件的名稱。

    (代碼段 - Web Form 實驗室 - Ex01 - GetProducts

    public IEnumerable<Product> GetProducts([Control("categoriesGrid")]int? categoryId)
    {
        return this.db.Products.Where(p => p.CategoryId == categoryId);
    }
    

    注意

    此方法可讓您更輕鬆地對這些方法進行單元測試。 在未執行 Web Form 的單元測試內容上,[Control] 屬性將不會執行任何特定動作。

  4. 開啟 [Products.aspx] 頁面,然後找出產品 GridView。 更新產品 GridView 以顯示編輯所選產品的連結。

    <h3>Products</h3>
    <asp:GridView ID="productsGrid" runat="server" 
      CellPadding="4"
      AutoGenerateColumns="false"
      ItemType="WebFormsLab.Model.Product"
      DataKeyNames="ProductId"
      SelectMethod="GetProducts">
      <Columns>
        <asp:TemplateField>
          <ItemTemplate>
            <a href="ProductDetails.aspx?productId=<%#: Item.ProductId %>">View</a>
          </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="ProductId" HeaderText="ID" />
        <asp:BoundField DataField="ProductName" HeaderText="Name" />
        <asp:BoundField DataField="Description" HeaderText="Description" HtmlEncode="false" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price" />
      </Columns>
      <EmptyDataTemplate>
        Select a category above to see its products
      </EmptyDataTemplate>
    </asp:GridView>
    
  5. 開啟ProductDetails.aspx頁代碼後置,並以下列程式代碼取代 SelectProduct 方法。

    (代碼段 - Web Form 實驗室 - Ex01 - SelectProduct 方法

    public Product SelectProduct([QueryString]int? productId)
    {
        return this.db.Products.Find(productId);
    }
    

    注意

    請注意, [QueryString] 屬性是用來從查詢字串中的 productId 參數填入方法參數。

  6. F5 開始對網站進行偵錯,並移至 [產品] 頁面。 從 GridView 類別中選取任何類別,並注意 GridView 已更新產品。

    顯示所選類別的產品

    顯示所選類別的產品

  7. 按兩下產品上的 [ 檢視 ] 連結,以開啟ProductDetails.aspx頁面。

    請注意,頁面會使用查詢字串中的 productId 參數,使用 SelectMethod 擷取產品。

    檢視產品詳細數據

    檢視產品詳細數據

    注意

    在下一個練習中將會實作輸入 HTML 描述的能力。

工作 5 - 使用模型系結進行更新作業

在上一個工作中,您主要使用模型系結來選取數據,在此工作中,您將瞭解如何在更新作業中使用模型系結。

您將更新 GridView 類別,讓使用者更新類別。

  1. 開啟 [Products.aspx] 頁面,並更新 GridView 類別以自動產生 [編輯] 按鈕,並使用新的 UpdateMethod 屬性來指定 UpdateCategory 方法來更新選取的專案。

    <asp:GridView ID="categoriesGrid" runat="server"
        AutoGenerateColumns="false"
        ItemType="WebFormsLab.Model.Category" DataKeyNames="CategoryId"
        SelectMethod="GetCategories"
        AutoGenerateSelectButton="true"
        AutoGenerateEditButton="true"
        UpdateMethod="UpdateCategory">
    

    GridView 中的 DataKeyNames 屬性會定義哪些是可唯一識別模型系結對象的成員,因此,這是更新方法至少應該接收的參數。

  2. 開啟Products.aspx.cs程序代碼後置檔案,並實作 UpdateCategory 方法。 方法應該會收到類別標識碼以載入目前的類別、填入 GridView 中的值,然後更新類別目錄。

    (代碼段 - Web Form 實驗室 - Ex01 - UpdateCategory

    public void UpdateCategory(int categoryId)
    {
        var category = this.db.Categories.Find(categoryId);
    
        this.TryUpdateModel(category);
    
        if (this.ModelState.IsValid)
        {
            this.db.SaveChanges();
        }
    }
    

    Page 類別中的新 TryUpdateModel 方法會負責使用頁面中控件的值填入模型物件。 在此情況下,它會取代目前 GridView 資料列中正在編輯至 類別 物件的更新值。

    注意

    下一個練習將說明 ModelState.IsValid 的使用方式,以在編輯物件時驗證使用者輸入的數據。

  3. 執行網站並移至 [產品] 頁面。 編輯類別。 輸入新的名稱,然後按兩下 [ 更新 ] 以保存變更。

    編輯類別

    編輯類別

練習 2:數據驗證

在本練習中,您將瞭解 ASP.NET 4.5 中的新數據驗證功能。 您將會在 Web Form 中查看新的不顯眼驗證功能。 您將使用應用程式模型類別中的數據批注進行使用者輸入驗證,最後,您將瞭解如何開啟或關閉頁面上個別控件的要求驗證。

工作 1 - 不顯眼的驗證

含有複雜數據的表單,包括驗證程式,通常會在頁面中產生太多 JavaScript 程式代碼,這代表大約 60% 的程式代碼。 啟用不顯眼的驗證后,您的 HTML 程式代碼看起來會更簡潔且更簡潔。

在本節中,您會在 ASP.NET 中啟用不顯眼的驗證,以比較這兩個組態所產生的 HTML 程式代碼。

  1. 開啟 Visual Studio 2012,然後開啟位於此實驗室的 Source\Ex2-Validation\Begin 資料夾中的 Begin 方案。 或者,您可以從上一個練習繼續處理現有的解決方案。

    1. 如果您開啟提供的 Begin 解決方案,您必須先下載一些遺漏的 NuGet 套件,才能繼續。 若要這樣做,請在 方案總管 中,按兩下 [WebFormsLab] 專案 [管理 NuGet 套件]。

    2. 在 [ 管理 NuGet 套件 ] 對話框中,按兩下 [ 還原 ] 以下載遺漏的套件。

    3. 最後,按兩下 [建置建置方案] 來建 | 置方案。

      注意

      使用 NuGet 的優點之一是,您不需要寄送專案中的所有連結庫,以減少專案大小。 使用 NuGet Power Tools 時,藉由在 Packages.config 檔案中指定套件版本,您就能夠在第一次執行專案時下載所有必要的連結庫。 這就是為什麼您必須從此實驗室開啟現有的解決方案之後執行這些步驟。

  2. F5 啟動 Web 應用程式。 移至 [客戶] 頁面,然後按下 [ 新增客戶 ] 連結。

  3. 以滑鼠右鍵按下瀏覽器頁面,然後選取 [檢視來源 ] 選項,以開啟應用程式所產生的 HTML 程式代碼。

    顯示網頁 HTML 程式代碼

    顯示網頁 HTML 程式代碼

  4. 捲動頁面原始程式碼,並注意 ASP.NET 已在頁面中插入 JavaScript 程式代碼和資料驗證程式,以執行驗證並顯示錯誤清單。

    CustomerDetails 頁面中的驗證 JavaScript 程式代碼

    CustomerDetails 頁面中的驗證 JavaScript 程式代碼

  5. 關閉瀏覽器並返回 Visual Studio。

  6. 現在您將啟用不顯眼的驗證。 開啟 Web.Config,並在 AppSettings 區段中找出 ValidationSettings:UnobtrusiveValidationMode 機碼將索引鍵值設定為 WebForms

    <configuration>
      ...
      <appSettings>
        <add key="aspnet:uselegacysynchronizationcontext" value="false" />
        <add key="ValidationSettings:UnobtrusiveValidationMode" value="WebForms"/>
    

    注意

    您也可以在 「Page_Load」事件中設定此屬性,以防您想要只針對某些頁面啟用「非干擾驗證」。

  7. 開啟 CustomerDetails.aspx ,然後按 F5 啟動 Web 應用程式。

  8. 按 F12 鍵以開啟 IE 開發人員工具。 開啟開發人員工具之後,請選取腳本 索引標籤。從功能表中選取 [CustomerDetails.aspx ],並記下頁面上執行 jQuery 所需的腳本已從本機網站載入瀏覽器。

    直接從本機 IIS 伺服器載入 jQuery JavaScript 檔案

    直接從本機 IIS 伺服器載入 jQuery JavaScript 檔案

  9. 關閉瀏覽器以返回 Visual Studio。 再次開啟 Site.Master 檔案,並找出 ScriptManager使用 True新增 EnableCdn 屬性。 這會強制從在線 URL 載入 jQuery,而不是從本機網站的 URL 載入。

  10. 在 Visual Studio 中開啟 CustomerDetails.aspx 。 按 F5 鍵以執行月臺。 Internet Explorer 開啟之後,請按 F12 鍵開啟開發人員工具。 選取 [ 腳稿] 索引標籤,然後查看下拉式清單。 請注意,jQuery JavaScript 檔案已不再從本機網站載入,而是從在線 jQuery CDN 載入。

    從 CDN 載入 jQuery JavaScript 檔案

    從 CDN 載入 jQuery JavaScript 檔案

  11. 使用瀏覽器中的 [檢視來源] 選項,再次開啟 HTML 網頁原始程式碼。 請注意,藉由啟用不顯眼的驗證 ASP.NET 已將插入的 JavaScript 程式代碼取代為 data- *attributes。

    不顯眼的驗證程序代碼

    不顯眼的驗證程序代碼

    注意

    在此範例中,您已瞭解如何將包含數據批註的驗證摘要簡化為少數 HTML 和 JavaScript 行。 先前,如果沒有不顯眼的驗證,您新增的驗證控件越多,JavaScript 驗證程序代碼就會變大。

工作 2 - 使用數據批注驗證模型

ASP.NET 4.5 引進 Web Form 的數據批注驗證。 您現在可以在模型類別中定義條件約束,並在所有 Web 應用程式中使用這些條件約束,而不是在每個輸入上擁有驗證控件。 在本節中,您將瞭解如何使用數據批註來驗證新的/編輯客戶窗體。

  1. 開啟 CustomerDetail.aspx 頁面。 請注意,使用 RequiredFieldValidator 控件驗證 EditItemTemplate 和 InsertItemTemplate 區段中的客戶名字和第二個名稱 每個驗證程式都與特定條件相關聯,因此您必須包含與條件一樣多的驗證程式。

  2. 新增數據批注來驗證 Customer 模型類別。 在 Model 資料夾開啟Customer.cs類別,並使用資料批注屬性裝飾每個屬性。

    (代碼段 - Web Form 實驗室 - Ex02 - 資料批注

    namespace WebFormsLab.Model
    {
      using System.Collections.Generic;
      using System.ComponentModel.DataAnnotations;
    
      public class Customer
      {
         [Key]
         public int Id { get; set; }
    
         [Required]
         public string FirstName { get; set; }
    
         [Required]
         public string LastName { get; set; }
    
         [Range(0, 130)]
         public int Age { get; set; }
    
         public Address Address { get; set; }
    
         [Phone]
         public string DaytimePhone { get; set; }
    
         [EmailAddress, StringLength(256)]
         public string EmailAddress { get; set; }
      }
    }
    

    注意

    .NET Framework 4.5 已擴充現有的數據批注集合。 這些是一些您可以使用的數據批注:[CreditCard]、[Phone]、[EmailAddress]、[Range]、[Compare]、[Url]、[FileExtensions]、[Required]、[Key]、[RegularExpression]。

    一些使用範例:

    [索引鍵]: 指定屬性為唯一標識符

    [Range(0.4, 0.5, ErrorMessage=“{Write an error message}”]: Double range

    [EmailAddress(ErrorMessage=“Invalid Email”),MaxLength(56)]:相同行中的兩個批注。

    您也可以在每個屬性內定義自己的錯誤訊息。

  3. 開啟 CustomerDetails.aspx, 並移除 FormView 控件之 EditItemTemplate 和 InsertItemTemplate 區段中第一個和姓氏欄位的所有 RequiredFieldValidators。

    <EditItemTemplate>
      <fieldset>
         <p><asp:Label runat="server" AssociatedControlID="firstName">First Name: </asp:Label></p>
         <p><asp:TextBox runat="server" ID="firstName" Text='<%#: BindItem.FirstName %>' />
            &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="firstName" ErrorMessage="Please enter a value for First Name" ForeColor="Red" />
        </p>
    
         <p><asp:Label runat="server" AssociatedControlID="lastName">Last Name: </asp:Label></p>
         <p><asp:TextBox runat="server" ID="lastName" Text='<%#: BindItem.LastName %>' />
              &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="lastName" ErrorMessage="Please enter a value for Last Name" ForeColor="Red" />
        </p>
      ...
    <InsertItemTemplate>        
     <fieldset>
       <p><asp:Label runat="server" AssociatedControlID="firstName">First Name: </asp:Label></p>
       <p><asp:TextBox runat="server" ID="firstName" Text='<%#: BindItem.FirstName %>' />           
         &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="firstName" ErrorMessage="Please enter a value for First Name" ForeColor="Red" />
        </p>
    
       <p><asp:Label runat="server" AssociatedControlID="lastName">Last Name: </asp:Label></p>                
        <p><asp:TextBox runat="server" ID="lastName" Text='<%#: BindItem.LastName %>' />
         &nbsp;<asp:RequiredFieldValidator runat="server" ControlToValidate="lastName" ErrorMessage="Please enter a value for Last Name" ForeColor="Red" />
        </p>
      ...
    

    注意

    使用數據批注的其中一個優點是驗證邏輯不會在應用程式頁面中重複。 您可以在模型中定義一次,並在操作數據的所有應用程式頁面上使用它。

  4. 開啟 CustomerDetails.aspx程序 代碼後置並找出 SaveCustomer 方法。 在插入新的客戶,並從 FormView 控制項值接收 Customer 參數時,會呼叫這個方法。 當頁面控件與參數對象之間的對應發生時,ASP.NET 會針對所有數據批注屬性執行模型驗證,並填入 ModelState 字典,如果有的話,就會發生錯誤。

    只有在模型的所有欄位在執行驗證之後,ModelState.IsValid 才會傳回 true。

    public void SaveCustomer(Customer customer) 
    {
        if (this.ModelState.IsValid)
        { 
            using (var db = new ProductsContext())
            {
                ...
    
  5. 在 CustomerDetails 頁面結尾新增 ValidationSummary 控件,以顯示模型錯誤清單。

    </fieldset>
        </InsertItemTemplate>
      </asp:FormView>
    
      <asp:ValidationSummary runat="server" ShowModelStateErrors="true" 
           ForeColor="Red" HeaderText="Please check the following errors:"/>
    </asp:Content>
    

    ShowModelStateErrors 是 ValidationSummary 控件上的新屬性,當設定為 true 時,控件會顯示 ModelState 字典的錯誤。 這些錯誤來自數據批註驗證。

  6. F5 以執行 Web 應用程式。 使用某些錯誤值完成表單,然後按兩下 [ 儲存 ] 以執行驗證。 請注意底部的錯誤摘要。

    使用數據批註進行驗證

    使用數據批註進行驗證

工作 3 - 使用 ModelState 處理自訂資料庫錯誤

在舊版的 Web Form 中,處理資料庫錯誤,例如太長字串或唯一索引鍵違規,可能會涉及在您的存放庫程式代碼中擲回例外狀況,然後處理程式代碼後置上的例外狀況以顯示錯誤。 需要大量的程式代碼才能執行相對簡單的動作。

在 Web Form 4.5 中,ModelState 對象可用來以一致的方式,以一致的方式,在頁面上顯示錯誤。

在這項工作中,您將新增程式代碼以正確處理資料庫例外狀況,並使用 ModelState 對象向使用者顯示適當的訊息。

  1. 當應用程式仍在執行時,請嘗試使用重複的值來更新類別的名稱。

    使用重複的名稱更新類別

    使用重複的名稱更新類別

    請注意,因為 CategoryName 數據行的 「unique」 條件約束而擲回例外狀況。

    重複類別名稱的例外狀況

    重複類別名稱的例外狀況

  2. 停止偵錯。 在 Products.aspx.cs 程序代碼後置檔案中 ,更新 UpdateCategory 方法來處理 db 擲回的例外狀況。SaveChanges() 方法呼叫並將錯誤新增至 ModelState 物件。

    新的 TryUpdateModel 方法會使用使用者所提供的表單數據,更新從資料庫擷取的類別物件。

    (代碼段 - Web Form 實驗室 - Ex02 - UpdateCategory 處理錯誤

    public void UpdateCategory(int categoryId)
    {
      var category = this.db.Categories.Find(categoryId);
    
      this.TryUpdateModel(category);
    
      if (this.ModelState.IsValid)
      {
        try
        {
          this.db.SaveChanges();
        }
        catch (DbUpdateException)
        {
          var message = string.Format("A category with the name {0} already exists.", category.CategoryName);
          this.ModelState.AddModelError("CategoryName", message);
        }
      }
    }
    

    注意

    在理想情況下,您必須識別 DbUpdateException 的原因,並檢查根本原因是否違反唯一索引鍵條件約束。

  3. 開啟 Products.aspx,並在 GridView 類別下方新增 ValidationSummary 控件,以顯示模型錯誤清單。

    <asp:GridView ID="categoriesGrid" runat="server"
      ...
    </asp:GridView>
    
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowModelStateErrors="true" />
    
    <h3>Products</h3>
    
  4. 執行網站並移至 [產品] 頁面。 嘗試使用重複的值來更新類別的名稱。

    請注意,已處理例外狀況,而且錯誤訊息會出現在 ValidationSummary 控件中

    重複的類別錯誤

    重複的類別錯誤

工作 4 - ASP.NET Web Form 4.5 中的要求驗證

ASP.NET 中的要求驗證功能提供特定層級的默認保護,以防止跨網站腳本 (XSS) 攻擊。 在舊版 ASP.NET 中,預設會啟用要求驗證,而且只能針對整個頁面停用。 使用新版本的 ASP.NET Web Form,您現在可以停用單一控件的要求驗證、執行延遲要求驗證或存取未經驗證的要求數據(如果您這麼做!)。

  1. Ctrl+F5 啟動網站而不進行偵錯,並移至 [產品] 頁面。 選取類別,然後按兩下 任何產品的 [編輯] 連結。

  2. 輸入包含潛在危險內容的描述,例如包含 HTML 標籤。 請注意由於要求驗證而擲回的例外狀況。

    編輯具有潛在危險內容的產品

    編輯具有潛在危險內容的產品

    因要求驗證而擲回例外狀況

    因要求驗證而擲回例外狀況

  3. 關閉頁面,並在 Visual Studio 中按 SHIFT+F5 以停止偵錯。

  4. 開啟 [ProductDetails.aspx] 頁面,然後找出 [描述 TextBox]。

  5. 將新的 ValidateRequestMode 屬性新增至 TextBox,並將其值設定為 Disabled

    新的 ValidateRequestMode 屬性可讓您在每個控件上以細微方式停用要求驗證。 當您想要使用可接收 HTML 程式代碼的輸入,但想要讓驗證持續對頁面的其餘部分運作時,這非常有用。

    <p>
      <asp:TextBox runat="server" ID="Description" TextMode="MultiLine" 
                Cols="60" Rows="8" Text='<%# BindItem.Description %>' 
        ValidateRequestMode="Disabled" />
    </p>
    
  6. F5 執行 Web 應用程式。 再次開啟編輯產品頁面,並完成產品描述,包括 HTML 標籤。 請注意,您現在可以將 HTML 內容新增至描述。

    已停用產品描述的要求驗證

    已停用產品描述的要求驗證

    注意

    在生產應用程式中,您應該清理使用者輸入的 HTML 程式代碼,以確保只輸入安全的 HTML 標籤(例如,沒有 <腳本> 標記)。 若要這樣做,您可以使用 Microsoft Web 保護連結庫

  7. 再次編輯產品。 在 [名稱] 欄位中輸入 HTML 程式代碼,然後按兩下 [ 儲存]。 請注意,只有 [描述] 字段已停用要求驗證,其餘字段仍會針對潛在的危險內容進行驗證。

    在其餘欄位啟用要求驗證

    在其餘欄位啟用要求驗證

    ASP.NET Web Form 4.5 包含新的要求驗證模式,以延遲執行要求驗證。 當要求驗證模式設定為 4.5 時,如果一段程式代碼存取 Request.Form[“key”],ASP.NET 4.5 的要求驗證只會觸發窗體集合中該特定元素的要求驗證。

    此外,ASP.NET 4.5 現在包含來自 Microsoft Anti-XSS Library v4.0 的核心編碼例程。 反 XSS 編碼例程是由新 System.Web.Security.AntiXss 命名空間中找到的新 AntiXssEncoder 類型實作。 當 encoderType 參數設定為使用 AntiXssEncoder 時,ASP.NET 中的所有輸出編碼都會自動使用新的編碼例程。

  8. ASP.NET 4.5 要求驗證也支援對要求數據的未驗證存取。 ASP.NET 4.5 會將新的集合屬性新增至名為 Unvalidated 的 HttpRequest 物件。 當您流覽至 HttpRequest.Unvalidated 時,您可以存取所有常見的要求數據片段,包括 Forms、QueryStrings、Cookie、URL 等等。

    Request.Unvalidated 物件

    Request.Unvalidated 物件

    注意

    請小心使用 HttpRequest.Unvalidated 屬性! 請確定您仔細對原始要求數據執行自定義驗證,以確保危險文字不會四捨五入並轉譯回給不知情的客戶!

練習 3:ASP.NET Web Form中的異步頁面處理

在此練習中,您將會在 ASP.NET Web Form 中介紹新的異步頁面處理功能。

工作 1 - 更新產品詳細數據頁面以上傳和顯示影像

在這項工作中,您將更新產品詳細數據頁面,讓使用者指定產品的影像 URL,並將其顯示在唯讀檢視中。 您將同步下載所指定映像的本機複本。 在下一個工作中,您將更新此實作,使其以異步方式運作。

  1. 開啟 Visual Studio 2012,並從此實驗室的資料夾載入 Source\Ex3-Async\Begin 中的 Begin 方案。 或者,您可以從先前的練習繼續處理現有的解決方案。

    1. 如果您開啟提供的 Begin 解決方案,您必須先下載一些遺漏的 NuGet 套件,才能繼續。 若要這樣做,請在 方案總管 中,按兩下 [WebFormsLab] 項目,然後選取 [管理 NuGet 套件]。

    2. 在 [ 管理 NuGet 套件 ] 對話框中,按兩下 [ 還原 ] 以下載遺漏的套件。

    3. 最後,按兩下 [建置建置方案] 來建 | 置方案。

      注意

      使用 NuGet 的優點之一是,您不需要寄送專案中的所有連結庫,以減少專案大小。 使用 NuGet Power Tools 時,藉由在 Packages.config 檔案中指定套件版本,您就能夠在第一次執行專案時下載所有必要的連結庫。 這就是為什麼您必須從此實驗室開啟現有的解決方案之後執行這些步驟。

  2. 開啟ProductDetails.aspx頁面來源,並在 FormView 的 ItemTemplate 中新增欄位以顯示產品影像。

    <ItemTemplate>
         <fieldset>
              <p><b><asp:Label ID="Label2" runat="server" AssociatedControlID="itemProductName">Name:</asp:Label></b></p>
              <p><asp:Label runat="server" ID="itemProductName" Text='<%#: Item.ProductName %>' /></p>
              <p><b><asp:Label ID="Label3" runat="server" AssociatedControlID="itemDescription">Description (HTML):</asp:Label></b></p>
              <p><asp:Label runat="server" ID="itemDescription" Text='<%# Item.Description %>' /></p>
              <p><b><asp:Label ID="Label4" runat="server" AssociatedControlID="itemUnitPrice">Price:</asp:Label></b></p>
              <p><asp:Label runat="server" ID="itemUnitPrice" Text='<%#: Item.UnitPrice %>' /></p>
    
              <p><b><asp:Label ID="Label5" runat="server" AssociatedControlID="itemUnitPrice">Image:</asp:Label></b></p>
              <p>
                    <img src="<%# string.IsNullOrEmpty(Item.ImagePath) ? "/Images/noimage.jpg" : 
                    Item.ImagePath %>" alt="Image" />
              </p>
    
              <br />
              <p>
                    <asp:Button ID="Button1" runat="server" CommandName="Edit" Text="Edit" />&nbsp;
                    <asp:HyperLink NavigateUrl="~/Products.aspx" Text="Back" runat="server" />
              </p>
         </fieldset>
    </ItemTemplate>
    
  3. 新增欄位以指定 FormView 的 EditTemplate 中的影像 URL。

    <fieldset>
         <p><asp:Label ID="Label2" runat="server" AssociatedControlID="ProductName">Name:</asp:Label></p>
         <p><asp:TextBox runat="server" ID="ProductName" Text='<%#: BindItem.ProductName %>' /></p>
         <p><asp:Label ID="Label3" runat="server" AssociatedControlID="Description">Description (HTML):</asp:Label></p>
         <p>
              <asp:TextBox runat="server" ID="Description" TextMode="MultiLine" Cols="60" Rows="8" Text='<%# BindItem.Description %>'
                    ValidateRequestMode="Disabled" />
         </p>
         <p><asp:Label ID="Label4" runat="server" AssociatedControlID="UnitPrice">Price:</asp:Label></p>
         <p><asp:TextBox runat="server" ID="UnitPrice" Text='<%#: BindItem.UnitPrice %>' /></p>
    
         <p><asp:Label ID="Label1" runat="server" AssociatedControlID="ImagePath">Image URL:</asp:Label></p>
         <p><asp:TextBox runat="server" ID="ImagePath" Text='<%#:  BindItem.ImagePath %>' /></p>
    
         <br />
         <p>
              <asp:Button runat="server" CommandName="Update" Text="Save" />
              <asp:Button runat="server" CommandName="Cancel" Text="Cancel" CausesValidation="false" />
         </p>
    </fieldset>
    
  4. 開啟ProductDetails.aspx.cs程式代碼後置檔案,並新增下列命名空間指示詞。

    (代碼段 - Web Form 實驗室 - Ex03 - 命名空間

    using System.IO;
    using System.Net;
    using System.Web;
    
  5. 建立 UpdateProductImage 方法,將遠端影像儲存在本機 Images 資料夾中,並使用新的映像位置值更新產品實體。

    (代碼段 - Web Form 實驗室 - Ex03 - UpdateProductImage

    private void UpdateProductImage(Product product)
    {
        string imageUrl = product.ImagePath;
    
        if (!string.IsNullOrEmpty(imageUrl) && !VirtualPathUtility.IsAbsolute(imageUrl))
        {
            product.ImagePath = string.Format(
                                     "/Images/{0}{1}", 
                                     product.ProductId, 
                                     Path.GetExtension(imageUrl));
    
            using (var wc = new WebClient())
            {
                wc.DownloadFile(imageUrl, Server.MapPath(product.ImagePath));
            }
        }
    }
    
  6. 更新 UpdateProduct 方法以呼叫 UpdateProductImage 方法。

    (代碼段 - Web Form 實驗室 - Ex03 - UpdateProductImage 呼叫

    public void UpdateProduct(int productId)
    {
        var product = this.db.Products.Find(productId);
    
        this.TryUpdateModel(product);
    
        this.UpdateProductImage(product);
    
        if (this.ModelState.IsValid)
        {
            this.db.SaveChanges();
        }
    }
    
  7. 執行應用程式,並嘗試上傳產品的影像。

    設定產品的影像

    設定產品的影像

工作 2 - 將異步處理新增至產品詳細數據頁面

在這項工作中,您將更新產品詳細數據頁面,使其以異步方式運作。 您將使用 ASP.NET 4.5 異步頁面處理來增強長時間執行的工作 - 映射下載程式。

Web 應用程式中的異步方法可用來優化使用線程集區 ASP.NET 的方式。 在 ASP.NET 線程集區中有一些線程可用於出席要求,因此,當所有線程忙碌時,ASP.NET 開始拒絕新的要求、傳送應用程式錯誤訊息,並讓您的網站無法使用。

您網站上的耗時作業是異步程式設計的絕佳候選項目,因為它們長時間佔用指派的線程。 這包括長時間執行的要求、具有許多不同元素的頁面和需要離線作業的頁面,例如查詢資料庫或存取外部網頁伺服器。 優點是,如果您針對這些作業使用異步方法,而頁面正在處理時,線程會釋出並傳回至線程集區,並可用來出席新的頁面要求。 這表示,頁面會在線程集區中的一個線程中開始處理,而且可能會在異步處理完成之後,在不同的線程中完成處理。

  1. 開啟ProductDetails.aspx頁面。 在Page元素中新增Async屬性,並將其設定為 true。 這個屬性會告知 ASP.NET 實作 IHttpAsyncHandler 介面。

    <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
        CodeBehind="ProductDetails.aspx.cs" Inherits="WebFormsLab.ProductDetails"
        Async="true" %>
    
  2. 在頁面底部新增標籤,以顯示執行頁面的線程詳細數據。

    <EmptyDataTemplate>Product not found</EmptyDataTemplate>
      </asp:FormView>
    
      <asp:Label ID="threadsMessageLabel" runat="server" />
    </asp:Content>
    
  3. 開啟 ProductDetails.aspx.cs 並新增下列命名空間指示詞。

    (代碼段 - Web Form 實驗室 - Ex03 - 命名空間 2

    using System.Web.UI;
    using System.Threading;
    
  4. 修改 UpdateProductImage 方法,以使用異步工作下載映像。 您將使用 DownloadFileTaskAsync 方法取代 WebClient DownloadFile 方法,並包含 await 關鍵詞。

    (代碼段 - Web Form 實驗室 - Ex03 - UpdateProductImage Async

    private void UpdateProductImage(Product product)
    {
        string imageUrl = product.ImagePath;
    
        if (!string.IsNullOrEmpty(imageUrl) && !VirtualPathUtility.IsAbsolute(imageUrl))
        {
            product.ImagePath = string.Format(
                "/Images/{0}{1}", 
                product.ProductId, 
                Path.GetExtension(imageUrl));
    
            this.RegisterAsyncTask(new PageAsyncTask(async (t) =>
            {
                using (var wc = new WebClient())
                {
                    await wc.DownloadFileTaskAsync(imageUrl, this.Server.MapPath(product.ImagePath));
                }
            }));
        }
    }
    

    RegisterAsyncTask 會註冊新的頁面異步工作,以在不同的線程中執行。 它會接收具有要執行之Task (t) 的 Lambda 運算式。 DownloadFileTaskAsync 方法中的 await 關鍵詞會將方法的其餘部分轉換成在 DownloadFileTaskAsync 方法完成之後以異步方式叫用的回呼。 ASP.NET 會自動維護所有 HTTP 要求原始值,以繼續執行 方法。 .NET 4.5 中的新異步程序設計模型可讓您撰寫類似同步程式代碼的異步程序代碼,並讓編譯程式處理回呼函式或接續程式代碼的複雜性。

    注意

    RegisterAsyncTask 和 PageAsyncTask 自 .NET 2.0 起已可供使用。 await 關鍵詞是 .NET 4.5 異步程序設計模型的新功能,可與 .NET WebClient 物件的新 TaskAsync 方法搭配使用。

  5. 新增程式代碼以顯示程式代碼啟動和完成執行所在的線程。 若要這樣做,請使用下列程式代碼更新 UpdateProductImage 方法。

    (代碼段 - Web Form 實驗室 - Ex03 - 顯示線程

    private void UpdateProductImage(Product product)
    {
      string imageUrl = product.ImagePath;
    
      if (!string.IsNullOrEmpty(imageUrl) && !VirtualPathUtility.IsAbsolute(imageUrl))
      {
        product.ImagePath = string.Format(
             "/Images/{0}{1}", 
             product.ProductId, 
             Path.GetExtension(imageUrl));
    
        this.RegisterAsyncTask(new PageAsyncTask(async (t) =>
        {
          var startThread = Thread.CurrentThread.ManagedThreadId;
    
          using (var wc = new WebClient())
          {
            await wc.DownloadFileTaskAsync(imageUrl, this.Server.MapPath(product.ImagePath));
          }
    
          var endThread = Thread.CurrentThread.ManagedThreadId;
    
          this.threadsMessageLabel.Text = string.Format("Started on thread: {0}<br /> Finished on thread: {1}", startThread, endThread);
        }));
      }
    }
    
  6. 開啟網站的 Web.config 檔案。 新增下列 appSetting 變數。

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
    
  7. F5 執行應用程式,並上傳產品的影像。 請注意程式代碼啟動和完成的線程標識碼可能不同。 這是因為異步工作會在與 ASP.NET 線程集區不同的線程上執行。 當工作完成時,ASP.NET 會將工作放回佇列,並指派任何可用的線程。

    以異步方式下載映像

    以異步方式下載映像

注意

此外,您可以遵循附錄 B:使用 Web Deploy 發佈 ASP.NET MVC 4 應用程式,將此應用程式部署至 Azure


摘要

在此實際操作實驗室中,已解決並示範下列概念:

  • 使用強型別的數據系結表達式
  • 在 Web Form 中使用新的模型系結功能
  • 使用值提供者將頁面數據對應至程式代碼後置方法
  • 使用數據批注進行使用者輸入驗證
  • 在 Web Form 中利用 jQuery 的不顯眼客戶端驗證
  • 實作細微的要求驗證
  • 在 Web Form 中實作異步頁面處理

附錄 A:安裝 Visual Studio Express 2012 for Web

您可以使用 Microsoft Web Platform Installer 安裝 Microsoft Visual Studio Express 2012 for Web 或其他「快速」版本。 下列指示會引導您使用 Microsoft Web Platform Installer 安裝 Visual Studio Express 2012 for Web 所需的步驟。

  1. 移至 [https://go.microsoft.com/?linkid=9810169](https://go.microsoft.com/?linkid=9810169)。 或者,如果您已安裝 Web Platform Installer,您可以開啟它,並搜尋產品「Visual Studio Express 2012 for Web with Azure SDK」。

  2. 按兩下 [ 立即安裝]。 如果您沒有 Web Platform Installer ,系統會將您重新導向以先下載並安裝。

  3. 開啟 Web Platform Installer 之後,按兩下 [安裝] 以啟動安裝程式。

    安裝 Visual Studio Express

    安裝 Visual Studio Express

  4. 閱讀所有產品的授權和條款,然後按兩下 [ 我接受 ] 繼續。

    接受授權條款

    接受授權條款

  5. 等候下載和安裝程式完成。

    安裝進度

    安裝進度

  6. 安裝完成時,按兩下 [ 完成]。

    安裝已完成

    安裝已完成

  7. 按兩下 [結束 ] 以關閉 Web Platform Installer。

  8. 若要開啟 Visual Studio Express for Web,請移至 [開始] 畫面並開始撰寫 “VS Express”,然後按兩下 [VS Express for Web] 圖格。

    VS Express for Web 圖格

    VS Express for Web 圖格

附錄 B:使用 Web Deploy 發佈 ASP.NET MVC 4 應用程式

本附錄將說明如何從 Azure 入口網站建立新的網站,併發佈您遵循實驗室取得的應用程式,並利用 Azure 所提供的 Web Deploy 發佈功能。

工作 1 - 從 Azure 入口網站建立新網站

  1. 移至 Azure 管理入口網站並使用與您訂用帳戶相關聯的Microsoft認證登入。

    注意

    使用 Azure,您可以免費裝載 10 ASP.NET 網站,然後在流量成長時進行調整。 您可以在這裏註冊

    登入 Windows Azure 入口網站

    登入入口網站

  2. 按兩下 命令行上的 [新增 ]。

    建立新的網站

    建立新的網站

  3. 按兩下 [計算 | 網站]。 然後選取 [ 快速建立] 選項。 提供新網站的可用 URL,然後按兩下 [ 建立網站]。

    注意

    Azure 是可在雲端中執行之 Web 應用程式的主機,您可以控制及管理。 [快速建立] 選項可讓您從入口網站外部將已完成的 Web 應用程式部署至 Azure。 不包含設定資料庫的步驟。

    使用快速建立建立新網站

    使用快速建立建立新網站

  4. 等到新 網站 建立為止。

  5. 建立網站之後,按兩下URL數據行底下的連結。 檢查新的網站是否正常運作。

    流覽至新網站

    流覽至新網站

    執行的網站

    執行的網站

  6. 返回入口網站,然後按兩下 [ 名稱 ] 資料行底下的網站名稱,以顯示管理頁面。

    開啟網站管理頁面

    開啟網站管理頁面

  7. 在 [儀錶板] 頁面的 [快速瀏覽] 區段下,按兩下 [下載發佈配置檔] 連結。

    注意

    發行 配置檔 包含針對每個啟用的發行方法,將 Web 應用程式發佈至 Azure 所需的所有資訊。 發行配置檔包含連線和驗證發行集方法的每個端點所需的 URL、使用者認證和資料庫字串。 Microsoft WebMatrix 2,Microsoft Visual Studio Express for WebMicrosoft Visual Studio 2012 支援讀取發佈配置檔,以自動設定這些程式以將 Web 應用程式發佈至 Azure。

    下載網站發佈配置檔

    下載網站發佈配置檔

  8. 將發行配置檔檔案下載至已知位置。 在本練習中,您將瞭解如何使用此檔案從Visual Studio將Web應用程式發佈至 Azure。

    儲存發行配置檔案

    儲存發行配置檔案

工作 2 - 設定資料庫伺服器

如果您的應用程式使用 SQL Server 資料庫,您必須建立 SQL 資料庫 伺服器。 如果您想要部署不使用 SQL Server 的簡單應用程式,您可以略過這項工作。

  1. 您需要 SQL 資料庫 伺服器來儲存應用程式資料庫。 您可以在 Azure 管理入口網站中,在 Sql Databases | Server 伺服器的儀錶板中檢視訂用帳戶中的 SQL 資料庫 伺服器。 | 如果您沒有建立伺服器,您可以使用命令行上的 [新增] 按鈕來建立伺服器。 記下 伺服器名稱和 URL、系統管理員登入名稱和密碼,因為您會在下一個工作中使用這些名稱。 尚未建立資料庫,因為它將在稍後階段建立。

    SQL 資料庫 伺服器儀錶板

    SQL 資料庫 伺服器儀錶板

  2. 在下一個工作中,您將測試來自 Visual Studio 的資料庫連線,基於這個理由,您必須在伺服器的 [允許的 IP 位址] 清單中 包含本機 IP 位址。 若要這樣做,請按兩下 [ 設定],從 [目前用戶端 IP 位址] 選取IP位址 ,然後將它貼到 [開始IP位址 ] 和 [結束IP位址] 文字框中,然後按下 add-client-ip-address-ok-button 按鈕。

    新增用戶端IP位址

    新增用戶端IP位址

  3. [用戶端 IP 位址] 新增至允許的 IP 位址 清單之後,按兩下 [ 儲存 ] 以確認變更。

    確認變更

    確認變更

工作 3 - 使用 Web Deploy 發佈 ASP.NET MVC 4 應用程式

  1. 返回 ASP.NET MVC 4解決方案。 在 方案總管 中,以滑鼠右鍵按兩下網站專案,然後選取 [發佈]。

    發佈應用程式

    發佈網站

  2. 匯入您在第一個工作中儲存的發行配置檔。

    匯入發行配置檔

    匯入發行配置檔

  3. 按兩下 [ 驗證連線]。 驗證完成後,按 [ 下一步]。

    注意

    當您看到綠色複選標記出現在 [驗證連線] 按鈕旁時,驗證就會完成。

    驗證連線

    驗證連線

  4. 在 [設定] 頁面的 [資料庫] 區段底下,按兩下資料庫連線文本框旁的按鈕(也就是DefaultConnection)。

    Web 部署設定

    Web 部署設定

  5. 設定資料庫連線,如下所示:

    • 在 [伺服器名稱],使用 tcp: 前置詞輸入您的 SQL 資料庫 伺服器 URL。

    • 在 [ 用戶名稱] 中,輸入您的伺服器管理員登入名稱。

    • 在 [ 密碼 ] 中,輸入您的伺服器管理員登入密碼。

    • 輸入新的資料庫名稱。

      設定目的地 連接字串

      設定目的地 連接字串

  6. 然後按一下 [確定] 。 當系統提示您建立資料庫時,按兩下 [ ]。

    建立資料庫

    建立資料庫

  7. 您將用來連線至 Azure 中 SQL 資料庫 的 連接字串 會顯示在 [預設連線] 文字框中。 然後按一下 [下一步]。

    指向 SQL 資料庫的連接字串

    指向 SQL 資料庫的連接字串

  8. 在 [ 預覽] 頁面中,按兩下 [ 發佈]。

    發佈 Web 應用程式

    發佈 Web 應用程式

  9. 發佈程式完成後,您的預設瀏覽器將會開啟已發佈的網站。

附錄 C:使用代碼段

使用代碼段時,您會有指尖所需的所有程序代碼。 實驗室文件會告訴您何時可以使用它們,如下圖所示。

使用 Visual Studio 代碼段將程式代碼插入專案中

使用 Visual Studio 代碼段將程式代碼插入專案中

使用鍵盤新增代碼段 (僅限 C#)

  1. 放置您想要插入程式碼的游標。
  2. 開始輸入代碼段名稱(不含空格或連字元)。
  3. 觀看 IntelliSense 會顯示相符的代碼段名稱。
  4. 選取正確的代碼段(或持續輸入,直到選取整個代碼段的名稱為止)。
  5. 按下 Tab 鍵兩次,以在游標位置插入代碼段。

開始輸入代碼段名稱

開始輸入代碼段名稱

按 Tab 鍵以選取醒目提示的代碼段

按 Tab 鍵以選取醒目提示的代碼段

再次按 Tab 鍵,代碼段將會展開

再次按 Tab 鍵,代碼段將會展開

若要使用滑鼠新增代碼段 (C#、Visual Basic 和 XML) 1。 以滑鼠右鍵按下您要插入代碼段的位置。

  1. 選取 [插入代碼段 ],後面接著 [我的代碼段]。
  2. 按兩下它,從清單中挑選相關的代碼段。

以滑鼠右鍵按下您要插入代碼段的位置,然後選取 [插入代碼段]

以滑鼠右鍵按下您要插入代碼段的位置,然後選取 [插入代碼段]

按兩下相關代碼段,從清單中挑選相關代碼段

按兩下相關代碼段,從清單中挑選相關代碼段