ASP.NET Web Forms模型繫結

by vivid 4. 十二月 2013 12:03

.NET Magazine國際中文電子雜誌
者:許薰尹
稿:張智凱
文章編號:N131214301
出刊日期:2013/12/4
開發工具:Visual Studio 2013 Ultimate
版本:.NET Framework 4.5.1

ASP.NET Web Forms模型繫結(Model Binding)功能能夠讓程式設計師,利用更直覺的方式來設計資料存取網頁應用程式,並能夠搭配實體資料模型(Entity Data Model)做整合。在這篇文章中,我們希望能夠透過ADO.NET實體資料模型 (ADO.NET Entity Data Model),讀取後端SQL Server Pubs資料庫資料,透過模型繫結的功能,將資料呈現在資料繫結控制項中。

我們從建立一個ASP.NET Web Site開始,從Visual Studio 2013開發工具 -「File」-「New」-「Web Site」,在「New Web Site」對話盒中選取程式語言,例如本範例選擇「Visual C#」,選取「ASP.NET Empty Web Site」,「Web location」則選擇適當的資料夾,本範例使用「WebFormBinding」,按下「OK」鍵便可以建立網站,請參考下圖所示:

clip_image002

圖 1:建立ASP.NET Web Site。

加入ASPX網頁。從「Solution Explorer」網站名稱上方,按按滑鼠右鍵,從選單選取「Add」-「Web Form」,請參考下圖所示:

clip_image004

圖 2:新增Web Form到網站。

在「Specify Name for Item」對話盒中設定新建立的網頁名稱為「Default」,然後按下「OK」按鈕,請參考下圖所示:

clip_image006

圖 3:設定新建立的網頁名稱。

加入一個ADO.NET實體資料模型(ADO.NET Entity Data Model),從「Solution Explorer」網站名稱上方,按按滑鼠右鍵,從選單選取「Add」-「Add New Item」,從對話盒選取「ADO.NET Entity Data Model」,設定名稱為「Model.edmx」,然按下「Add」按鈕,請參考下圖所示:

clip_image008

圖 4:加入ADO.NET實體資料模型(ADO.NET Entity Data Model)。

此時,便會出現一個對話盒,詢問是否將檔案放在App_Code資料夾,按「Yes」按鈕到下一個畫面,請參考下圖所示:

clip_image010

圖 5:將檔案放在App_Code資料夾。

下一步會跳出「Entity Data Model Wizard」對話盒,本文範例要從Pubs資料庫建立模型,選取「Generate from database」,然後按「Next」按鈕到下一個畫面,請參考下圖所示:

clip_image012

圖 6:從Pubs資料庫建立模型。

下一步設定資料連接(Data Connection),選取「New Connection」按鈕,在「Choose Data Source」對話盒中選取「Microsoft SQL Server」,然後按下「Continue」,請參考下圖所示:

clip_image014

圖 7:設定資料連接(Data Connection)。

在「Connection Properties」對話盒,設定以下資料,請參考下圖所示:

· 資料來源:Microsoft SQL Server (SqlClient)。

· 伺服器名稱:本範例程式將資料庫放在「.\sqlexpress」資料庫中,此處輸入「.\sqlexpress」。

· 登入伺服器:使用Windows驗證。

· 輸入資料庫名稱:選取Pubs資料庫。

clip_image016

圖 8:設定連線資訊。

進到下一個畫面,下方的核取方塊預設會勾選,表示要將資料庫連接字串資訊儲存在組態檔案之中,請參考下圖所示:

clip_image018

圖 9:將資料庫連接字串資訊儲存在組態檔案。

接下來精靈會詢問想使用的Entity Framework版本,在此範例中選取「Enity Framework 6.0」版,請參考下圖所示:

clip_image020

圖 10:選擇要使用的「Enity Framework 6.0」版本。

選取「Next」按鈕,進到下一個畫面,勾選「stores」資料表,以及勾選「Pluralize or singularize generated object names」來處理模型的命名,按下「Finish」按鈕結束精靈,Visual Studio 2013會在專案中產生一個edmx檔案,請參考下圖所示:

clip_image022

圖 11:選擇要使用的資料表。

Visual Studio 2013會自動在網站中加入Entity Framework相關組件到bin資料夾,此外也會自動在Web.config檔案,設定連線到資料庫所需的連接字串,以下是web.config檔案的內容,包含一個connectionString區段。

<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name = "entityFramework" type = "System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission = "false" />
  </configSections>
  <system.web>
    <compilation debug = "true" targetFramework = "4.5.1">
      <assemblies>
        <add assembly = "System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
        <add assembly = "System.Data.Entity.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
      <buildProviders>
        <add extension = ".edmx" type = "System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider" />
      </buildProviders>
    </compilation>
    <httpRuntime targetFramework = "4.5.1" />
  </system.web>
  <connectionStrings>
    <add name = "pubsEntities" connectionString = "metadata=res://*/App_Code.Model.csdl|res://*/App_Code.Model.ssdl|res://*/App_Code.Model.msl;
provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=pubs;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName = "System.Data.EntityClient" />
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type = "System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
    <providers>
      <provider invariantName = "System.Data.SqlClient" type = "System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

 

設計網頁

在Default.aspx加一個GridViewd控制項到設計畫面,在GridView的開頭標籤中設定ItemType為「store」,DataKeyNames設定為「stor_id」,在輸入資料的過程中,Visual Studio 會給予適當的提示[User1] ,請參考下圖所示:

clip_image024

圖 12:設定ItemType為「store」。

設定GridView控制項的SelectMethod屬性,選取選單上的「<Create New Method>」選項,請參考下圖所示:

clip_image026

圖 13:設定GridView控制項的SelectMethod屬性。

Visual Studio便會自動產生方法名稱「GridView1_GetData」:

<asp:GridView ItemType = "store" DataKeyNames = "stor_id" SelectMethod = "GridView1_GetData" ID = "GridView1" runat = "server"> </asp:GridView>

並自動在ASPX關聯的Default.aspx.cs檔案中,產生以下方法定義,這個SelectMethod方法用來撰寫查詢資料庫資料邏輯:

public IQueryable<store> GridView1_GetData()
    {
        return null;
    }

修改GridView1_GetData中的程式碼為:

public IQueryable<store> GridView1_GetData()
{
    pubsEntities db = new pubsEntities();
    var query = db.stores;
    return query;
}

 

宣告一個pubsEntities型別的db變數,它是用來連接到資料庫,以及處理資料異動的類別。

按CTRL+F5執行這個網頁,資料庫資料的內容便會自動地呈現在畫面上,請參考下圖所示:

clip_image028

圖 14:測試資料查詢。

自定欄位

若想要自訂GridView顯示的欄位資訊,可以從GridView智慧型標籤,點選「Edit Columns」,請參考下圖所示:

clip_image030

圖 15:自訂GridView顯示的欄位資訊。

在「Fields」對話盒中,清除勾選「Auto-generate fields」,並加入想使用的欄位,本文範例使用五個BoundField來顯示資料,設定每個BoundField的DataField,關聯到store類別的stor_id屬性;並利用HeaderText設定欄位表頭要顯示的文字,請參考下圖所示:

clip_image032

圖 16:設定欄位。

按相同方式設定每一個BoundField的DataField與HeaderText屬性:

· stor_name

· stor_address

· city

· state

· zip

到目前為止,Default.aspx中的HTML看起來如下:

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

<!DOCTYPE html>

<html xmlns = "http://www.w3.org/1999/xhtml">
<head runat = "server">
    <title> </title>
</head>
<body>
    <form id = "form1" runat = "server">
    <div>
      <asp:GridView
            ItemType = "store"
            DataKeyNames = "stor_id"
            SelectMethod = "GridView1_GetData"
            ID = "GridView1" runat = "server" AutoGenerateColumns = "False">
          <Columns>
              <asp:BoundField DataField = "stor_id" HeaderText = "stor_id" />
              <asp:BoundField DataField = "stor_name" HeaderText = "stor_name" />
              <asp:BoundField DataField = "stor_address" HeaderText = "stor_address" />
              <asp:BoundField DataField = "city" HeaderText = "city" />
              <asp:BoundField DataField = "state" HeaderText = "state" />
              <asp:BoundField DataField = "zip" HeaderText = "zip" />
          </Columns>
        </asp:GridView>

    </div>
    </form>
</body>
</html>

 

 

按CTRL+F5執行default.aspx,網頁的執行結果,請參考下圖所示:

clip_image034

圖 17:自訂欄位網頁測試。

資料修改、編輯功能

修改GridView控制項,在開頭標籤設定UpdateMethod、DeleteMethod,讓Visual Studio自動產生並GridView1_UpdateItem與GridView1_DeleteItem方法的定義,並將AutoGenerateEditButton與AutoGenerateDeleteButton屬性設定為「true」以便在GridView控制項中的每一筆資料前方自動加上編輯與刪除資料的連結:

<asp:GridView
    ItemType = "store"
    DataKeyNames = "stor_id"
    SelectMethod = "GridView1_GetData"
    UpdateMethod = "GridView1_UpdateItem"
    DeleteMethod = "GridView1_DeleteItem"
    AutoGenerateEditButton = "true"
    AutoGenerateDeleteButton = "true"
    ID = "GridView1" runat = "server" AutoGenerateColumns = "False">
    <Columns>
        <asp:BoundField DataField = "stor_id" HeaderText = "stor_id" />
        <asp:BoundField DataField = "stor_name" HeaderText = "stor_name" />
        <asp:BoundField DataField = "stor_address" HeaderText = "stor_address" />
        <asp:BoundField DataField = "city" HeaderText = "city" />
        <asp:BoundField DataField = "state" HeaderText = "state" />
        <asp:BoundField DataField = "zip" HeaderText = "zip" />
    </Columns>
</asp:GridView>

 

Visual Studio 2013工具自動產生的GridView1_UpdateItem與GridView1_DeleteItem方法定義如下:

// The id parameter name should match the DataKeyNames value set on the control
    public void GridView1_UpdateItem( int id )
    {
        store item = null;
        // Load the item here, e.g. item = MyDataLayer.Find( id );
        if (item == null)
        {
            // The item wasn't found
            ModelState.AddModelError( "", String.Format( "Item with id {0} was not found", id ));
            return;
        }
        TryUpdateModel(item);
        if (ModelState.IsValid)
        {
            // Save changes here, e.g. MyDataLayer.SaveChanges();

        }
    }

    // The id parameter name should match the DataKeyNames value set on the control
    public void GridView1_DeleteItem(int id)
    {

    }

 

 

自動產生出的程式碼並不能夠滿足我們的需求,修改GridView1_UpdateItem方法與GridView1_DeleteItem的參數型別為store,以讓ASP.NET 的模型繫結功能,自動傳入要修改與刪除的store物件:

public void GridView1_UpdateItem( store s )
    {
        pubsEntities db = new pubsEntities();
        store item = db.stores.Find( s.stor_id );
        // Load the item here, e.g. item = MyDataLayer.Find( id );
        if (item == null)
        {
            // The item wasn't found
            ModelState.AddModelError( "", String.Format("Item with id {0} was not found", s.stor_id ));
            return;
        }
        TryUpdateModel( item );
        if ( ModelState.IsValid )
        {
            // Save changes here, e.g. MyDataLayer.SaveChanges();
            db.SaveChanges();

        }
    }

    // The id parameter name should match the DataKeyNames value set on the control
public void GridView1_DeleteItem( store s ) {
  pubsEntities db = new pubsEntities( );
  db.Entry( s ).State = System.Data.Entity.EntityState.Deleted;
  try {
    db.SaveChanges( );
  } catch ( DbUpdateConcurrencyException ) {
    ModelState.AddModelError( "" ,
      String.Format( "找不到資料!!" , s.stor_id ) );
  }

}

 

 

在GridView1_UpdateItem方法中,宣告一個store型別的item變數,叫用db.stores.Find方法將要修改的資料載入,若找不到此項目,則叫用ModelState.AddModelError方法設定錯誤訊息。TryUpdateModel方法則用來將Web Form中資料繫結項目的值和store物件屬性關聯在一起。最後若資料沒有錯誤,則利用DbContext的SaveChanges方法將異動過的資料寫到資料庫。

GridView1_DeleteItem方法則將要刪除的資料的狀態(State)標示為Deleted,然後叫用DbContext的SaveChanges方法將刪除資料庫資料,若刪除發生錯誤,則可能是此筆資料已被其它使用者刪除,便顯示「找不到資料理!」的訊息。

按CTRL+F5執行default.aspx,網頁的執行結果如下,點選任一筆資料旁的「Edit」連結便可切換到編輯模式(若無法進入編輯畫面,而得到Unobtrusive Validation相關錯誤,請參考「修訂Unobtrusive Validation錯誤」一節的說明) ,請參考下圖所示:

clip_image036

圖 18:編輯資料。

在編輯模式中,欄位改以文字方塊顯示,你可以修改欄位內容,然後再按下「Update」連結將資料儲存到資料庫,請參考下圖所示:

clip_image038

圖 19:修改資料。

修改完成後,便回到瀏覽畫面,請參考下圖所示:

clip_image040

圖 20:將異動的資料儲存到資料庫。

修訂Unobtrusive Validation錯誤

若網頁執行發生以下錯誤:

WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. Please add a ScriptResourceMapping named jquery(case-sensitive).

錯誤畫面請參考下圖所示:

clip_image042

圖 21:Unobtrusive Validation錯誤。

你可以關閉Unobtrusive Validation功能,在web.config檔案中,<connectionStrings>標籤之前加入以下設定:

<appSettings>

<add key="ValidationSettings:UnobtrusiveValidationMode" value="none" />

</appSettings>

顯示錯誤訊息

若資料在異動或修改的過程中發生錯誤,你可以在網頁中使用ValidationSummary顯示集中式的錯誤訊息。例如在Default.aspx之中GridView控制項上方,加入ValidationSummary控制項,設定ShowModelStateErrors屬性為「true」:

<asp:ValidationSummary runat = "server" ShowModelStateErrors = "true" />

則當你修改一筆資料,而此資料可能被其它使用者刪除時,就會得到錯誤訊息,請參考下圖所示:

clip_image044

圖 22:顯示Model錯誤。

新增資料

最後讓我們來說明一下資料新增的動作,在這個範例中,我們選擇使用DetailsView來實作資料新增功能。在Default.aspx網頁中,加入一個DetailsView控制項。選取畫面上的DetailsView控制項,點選智慧型標籤,再選取「Edit Fields」,加一個「New, Insert, Cancel」欄位,請參考下圖所示:

clip_image046

圖 23:加一個「New, Insert, Cancel」欄位。

設定ItemType為「store」;DefaultMode為「Insert」,InsertMethod為「DetailsView1_InsertItem」,目前的標籤看起來如下:

<asp:DetailsView
     ItemType = "store"
     InsertMethod = "DetailsView1_InsertItem"
     DefaultMode = "Insert"
     ID = "DetailsView1" runat = "server" Height = "50px" Width = "125px">
     <Fields>
         <asp:CommandField ShowInsertButton = "True" />
     </Fields>
</asp:DetailsView>

 

Default.aspx.cs中的程式,修改工具產生出的DetailsView1_InsertItem方法,將參數型別設定為store,然後利用Entity Framework將新增的資料寫到後端資料庫,然後導向default.aspx以顯示新增的資料:

public void DetailsView1_InsertItem( store s ) {
 
  TryUpdateModel( s );
  if ( ModelState.IsValid ) {
    // Save changes here
    pubsEntities db = new pubsEntities( );
    db.stores.Add( s );
    db.SaveChanges( );
    Response.Redirect( "Default.aspx");
  }
}

 

按CTRL+F5執行default.aspx,網頁的執行結果如下 (若無法顯示畫面,而得到Unobtrusive Validation相關錯誤,請參考「修訂Unobtrusive Validation錯誤」一節的說明),輸入要新增的資料,然後按下「Insert」按鈕,請參考下圖所示:

clip_image048

圖 24:新增資料測試。

資料便會寫入資料庫,並顯示在GridView控制項之中,請參考下圖所示:

clip_image050

圖 25:資料新增完成。


Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List