2011年2月17日 星期四

ASP.NET Dynamic Data Web Site

前言:
Dynamic Data技術從.NET 3.5時代出現之後,就受到了不少開發人員的關注,其中DataAnnotations機制以及相關的概念,也擴展應用到了MVCSilverlight應用程式的開發當中。它讓我們有機會建構出UI層與後端資料庫徹底隔離的應用程式,有效的降低了開發的成本,並提高程式碼的可重用性。
ASP.NET 4.0版當中,Dynamic Data技術甚至可直接整合進傳統的Web Forms網站當中,這對於需要設計大型資料庫應用系統的開發人員來說,將有相當大的助益,使得Dynamic Data技術成為您不可不知的一環


關於Dynamic Data技術

 

        ASP.NET 4當中的Dynamic Data技術,可以讓我們建立所謂的data-driven applications,其中的DataAnnotations AttributeControl Template、和Field Template…等機制,讓開發人員可以透過模板技術建立出一套面對不同資料庫()依舊可以正常運行的Web應用程式,而不需像過去ASP.NET Web Forms的資料庫存取機制,在面對不同的資料表時常常需要重新截取資料結構或重新設計Template Field的窘境,讓我們得已有機會能夠用同一套模版來建立出可適用於多種不同資料表結構的資料庫應用程式。

        會有這樣的需求是有典故的,舉個簡單的例子,在真實世界的專案中,實務上我們常常會需要針對不同資料表建立CRUD(Create, Read, Update and Delete)等功能,如果能夠用一個模板(僅僅開發一次),在面對不同的資料表時可以完全不需要修改程式碼一樣可以運作,豈不是便利至極?

        過去在ASP.NET中透過FormView, DetalsView…等控制項開發出來的網頁恐怕不可能做到,但Dynamic Data Web Site則是針對這需求而來,這就是Dynamic Data技術將提供給開發人員的好處。
        ASP.NET 4.0中的Dynamic Data Web Site還增加了更多的新功能,諸如支援新的Display Attribute,還有針對ADO.NET Entity Framework中的Many-to-Many Relationships的支援,以及針對現有(過去已經開發好的)網站的支援等,這些新功能讓Dynamic Data技術可以更廣泛的應用在已開發的專案當中。

讓現有網站支援Dynamic Data機制

 

        過去你要建立出具有上述功能的網站,得要重頭建立一個所謂的『ASP.NET Dynamic Data應用程式(或網站)』,這等於要開發人員把過去建立好的網站整個砍掉重練,對於開發人員來說恐怕是相當為難,或許也因為如此,Dynamic Data Web Site這個功能一直都無法得到開發人員的重視與利用。

        有鑑於此,在這次新版的ASP.NET 4.0當中,我們可以針對傳統的Web Forms型態網站,直接加入Dynamic Data支援,讓DetailsView, GridView之類的控制項可以直接享有DataAnnotations所帶來的種種好處。

        舉例來說,我們可以讓過去我們相當熟悉的DetailsView控制項直接加入Dynamic Data支援,使用的方式很簡單,請看底下的程式碼片段:

EX
public partial class WebForm1 : System.Web.UI.Page
{
    //建立LinqToSql NorthwindDataContext
    NorthwindDataContext db = new NorthwindDataContext();
    protected void Page_Load(object sender, EventArgs e)
    {
        //設定自動產生編輯,新增鈕,並將預設模式指定為'編輯'
        this.DetailsView1.AutoGenerateEditButton = true;
        this.DetailsView1.AutoGenerateInsertButton = true;
        this.DetailsView1.DefaultMode = DetailsViewMode.Edit;
        //設定自動產生欄位
        this.DetailsView1.AutoGenerateRows = true;
        //資料來源設為LinqToSql資料來源的Customers資料表
        this.DetailsView1.DataSource = db.Customers;
        //DetailsView1支援EnableDynamicData(參考型別為Linq To Sql Data Model中的Customers)
        this.DetailsView1.EnableDynamicData(typeof(Customers));
        //進行DataBind
        this.DetailsView1.DataBind();
    }
}


        透過DetailsView控制項新支援的EnableDynamicData()方法,我們可以讓UI的呈現直接參考Customers物件的MetaData。請注意,Customers物件是我們透過LinqToSql(當然也支援Entity Framework)所建立的Data Model中的資料表,也就是我們的Entity

        開發人員可以在Visual Studio 2010當中,輕易的透過Designer來設計這些Entity

        完成之後,Visual Studio 2010會自動幫我們產生需要的指令碼。但這樣建立好的Entity並沒有經過DataAnnotations的修飾,所以欄位名稱以及驗證方式都尚未建立。因此,我們要為該Entity建立相對應的 Metadata,用來描述Customers中的欄位的呈現方式以及驗證機制。請特別留意程式碼中的[…]修飾字:
EX
//描述其MetadataTypeCustomerMetadata
[MetadataType(typeof(CustomerMetadata))]
public partial class Customers  //Entity 'Customers' partial class
{ }
//實際的DataAnnotations修飾字建立在CustomerMetadata
//用以修飾Customers中的欄位
public partial class CustomerMetadata
{
    [Display(Name = "地址", Order = 5)] //Name是欄位標題文字, Order則是排列順序
    public string Address;
    [Display(Name = "客戶編號", Order = 1)]
    [ReadOnly(true)] //ReadOnly描述該欄位為唯讀
    public string CustomerID;
    [Display(Name = "客戶名稱", Order = 2)]
    [Required(ErrorMessage = "此為必要欄位")] //Required(…)指出該欄位為必要欄位
    public string CompanyName;
    [Display(Name = "聯絡人名稱", Order = 3)]
    public string ContactName;
    [Display(Name = "頭銜", Order = 4)]
    public string ContactTitle;
    [Display(Name = "城市", Order = 7)]
    public string City;
    [Display(Name = "區域", Order = 6)]
    public string Region;
    [Display(Name = "郵遞區號", Order = 8)]
    public string PostalCode;
    [Display(Name = "國家", Order = 9)]
    public string Country;
    [Display(Name = "電話號碼", Order = 10)]
    public string Phone;
    [Display(Name = "傳真號碼", Order = 11)]
    public string Fax;
}


        完成之後,我們可以建置這個專案並執行,您會發現結果如下:
        呈現出的DetailsView就是我們透過CustomerMetadata所描述的結果,不僅欄位的標題就是我們在[Display(Name = "…", Order = …)]修飾字中所撰寫的,欄位也依照Order參數的順序排列。而且您會發現ReadOnlyRequired修飾字都各自發揮了效果,不僅如此,如果使用者沒有輸入客戶名稱,還會出現我們在CustomerMetadata中所描述的錯誤訊息呢!!!

        這些修飾字就是透過DataAnnotations技術來完成的,回顧上面的動作,我們將資料在UI層的呈現方式以及驗證方式都撰寫在CustomerMetadata(Model),這樣有幾個好處:
1.                前端UI(上例中是DetailsView),與繫結的資料(Customer資料表)完全無關,將兩者之間的相依性降到最低。程式碼餵給DetailsView什麼DataSourceDetailsView就會自動呈現出相對應的欄位。
2.                DetailsView在呈現(或處理)資料時,將會參考CustomerMetadata中所描述的DataAnnotations修飾字,由修飾字決定資料在DetailsView中的呈現方式和驗證方式。
3.                由於DataAnnotations撰寫在CustomerMetadata中,Entity若有微幅修改(或透過Designer重新截取或設計欄位),也不會需要完全重新建立Metadata

        千萬別小看這樣的功能,如此一來,整個DetailsView的繫結對象完全依照程式碼中的DataSource來決定,而UI層不需要寫死任何與後端Model層有關的程式碼或template宣告,如此一來,我們就可以用同一個.aspx頁面維護所有的資料表了,再也不需要針對每一個資料表設計一組DetailsView以及一個.aspx頁面。
        這整個架構就是Dynamic Data的核心精神,這個概念也影響了MVC以及Silverlight應用程式,現在在Silverlight應用程式當中也開始廣泛的使用DataAnnotations技術了。

ASP.NET 4.0中的Dynamic Data應用程式

 

        因此,整個DynamicData應用程式的重點在UI層與Data Model脫鉤,讓相依性降低到接近零,如此一來,我們就可以用同一套模板維護各種不同的實體(Entity)對象,也就是說,我們可以僅僅寫一套模板(程式),就能處理各種不同資料表。
當您在Visual Studio 2010當中建立Dynamic Data應用程式之後,會看到專案結構如下,其實整個重點在Templates

        在這幾個資料夾底下,已經包含了各式各樣的預設模板,透過這些模板已經可以應付絕大部分的需求。因此當您建立好DynamicData專案,並設置了DataModel之後,不須撰寫任何一行程式碼,即可出現資料表的編輯畫面:
        您在上圖中看到的每一個各種不同形式的欄位,是依照資料型別自動產生的,欄位的模塊就是定義在FieldTemplates裡面的每一組.ascx檔案。當然輸入欄位前的標題以及驗證方式,都可以透過我們撰寫在Metadata裡面的DataAnnotations修飾字來定義。

        在這一次推出的4.0版當中,針對Field Templates還增加了URLsE-mail Addresses模塊,我們一樣只需要透過修飾字來設定即可使用:
EX
[DataType(DataType.EmailAddress)]
public object HomeEmail { get; set; }

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

        不僅如此,相較於ASP.NET 3.5時代, Display 修飾字的功能也有所增強,可以對欄位有更細緻的描述,並且加入了針對ADO.NET Entity Framework中的Many-to-Many Relationships的支援。

        除此之外,還增加了Entity Templates,讓開發人員可以更輕鬆的客製化資料呈現方式,同時也針對了Filter機制進行了擴充。凡此種種,都說明了微軟在Dynamic Data技術上所注入的投資。

結語

 

        Dynamic Data技術以及DataAnnotations機制,確實讓開發人員對於建構大型資料庫Web應用程式有了更好的選擇,這個概念也影響了Silverlight的應用程式設計,在.NET 4.0當中,我們看到了DataAnnotations已經廣泛的應用在各種場合,這也是開發人員所必須要留意的部分。

        關於Dynamic Data網站的設計細節以及範例程式,可參考筆者的部落格http://blog.StudyHost.com,或本網誌後面的內容,在當中我們將有更詳細的介紹。

沒有留言:

張貼留言