[ ASP.NET ] WebForm To MVC Tips - 資料列表

[ ASP.NET ] WebForm To MVC Tips - 資料列表

從趨勢來看ASP.NET MVC 已經是一個顯學了,而Web Form 雖然不至於進入墓碑,但可以預料的是相關的改進跟新功能會愈來愈少,這一點從Visual Studio 2013 到 Visual Studio 2015 版本間的演化可以很明顯的看出來。因此對於一直採用Web Form 的開發團隊而言,可能會面對到技術上的轉變,但是要從 Web From轉到 MVC 可以說是基本概念上完全打掉重來,尤其對依賴伺服器控制項元件很深的團隊來說,是一定不小的挑戰,當然團隊還是可以選擇持續走Web Form 的機制,只是面對愈來愈多的挑戰,採用Web Form 的團隊可能會比較辛苦一些。例如網站想要做RWD的話,可能光是要挑戰伺服器控制項元件所渲染出來的HTML,就會比採用MVC的團隊來的辛苦了。

有鑑於此,筆者試著從一位由ASP時代到ASP.NET WebForm時代的開發人員角度,將邁入ASP.NET MVC的一些Tips 整理上來,一方面做為一種學習過程的筆記分享,一方面也提供給從ASP.NET WebForm邁入ASP.NET MVC的開發人員做為參考。首先要說的是,關於ASP.NET MVC的基本概念並不會在這一系列Tips著墨太多,原因很簡單,不論是官方文件或是教學書籍都已經說明的很仔細了,因此我會假定您已經對於什麼是Control、View、Model已有一定程度的認知,並且也知道什麼是 Routes ,如果您對前面提的到這些還不了解,那麼我會建議您先買本入門書來看,我會推薦由多位MVP共筆的【ASP.NET MVC 5:網站開發美學】一書。所以接下來【WebForm To MVC Tips 】小品主要會著重在於從 WebForm 到 MVC 一些基本的功能該如何寫,重點在於怎麼簡單去明白如何跨出MVC的第一步,所以我不會講求很好設計架構 ( 呵,我想再談到架構的話,可能會逼死不少 WebForm的開發團隊吧,畢竟WebForm跟義大利麵是好朋友來著XD),好了前言廢話差不多了,開始吧。

首先第一個我想來看看的是,在應用系統上很常見【資料列表】功能,這篇小品先來看看從WebForm 到 MVC ,如果我們想單純做出資料列表,該怎麼下手。在WebForm 的做法,常見的就是以GridView 配合 ADO.NET,進行資料的繫結,所以首先會在ASPX頁面拉出一個 GridView 伺服器控制項元件,然後設定所需要的BoundField對吧。

<asp:GridView ID="PersonData" runat="server" AutoGenerateColumns="False">
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
        <asp:BoundField DataField="MiddleName" HeaderText="MiddleName" />
        <asp:BoundField DataField="LastName" HeaderText="LastName" />
    </Columns>
</asp:GridView>

 

接著在背後端程式碼裡,會以ADO.NET進行SQL Command的Query,再把結果集餵給 GridView 伺服器控制項元件,進行資料的繫結。當然也有很多是用精靈進行設定來達成,不過筆者一向不愛使用精靈,之所以稱為精靈,其另一面代表著當你想彈性做到其它功能時,會給自已找麻煩,因此事實上筆者幾乎想不起來最後一次使用精靈來"寫"程式是什麼時候了。我們來看一下程式碼會是如何?

protected void Page_Load(object sender, EventArgs e)
{
   if (!IsPostBack)
   {
       LoadData();
   }
}
 
private void LoadData()
{
   try
   {
       using (SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["defconn"].ConnectionString))
       {
           conn.Open();
           using (SqlCommand command = new SqlCommand("select FirstName,MiddleName,LastName from person.Person", conn))
           using (SqlDataReader reader = command.ExecuteReader())
           {
               this.PersonData.DataSource = reader;
               this.PersonData.DataBind();
           }
       }
   }
   catch (Exception)
   {
       throw;
   }
}

我想這樣的程式碼應該不用多做解釋,寫WebForm的開發人員應該都看的懂,接著我們直接 run 起來看一下結果。

image

那麼接著我們把場景轉到 MVC ,在 MVC 裡該怎麼做呢?首先在MVC裡強型別的設計是很自然不過的一件事,所以當您想呈現資料時,你必須要有一個相對的Model,(話說前陣子有人為了 Model 吵翻天了XD),首先我們先新增一個 Controller ,由於範例中是人員資料,所以 Controller 命名為 PersonController ,接著PersonController 裡預設會有個Index()方法,由於預設路由的設定是這樣的。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

所以當action沒有特別指定時,預設就會 Run Index方法,這裡我們就先不去改它,所以PersonController 會是這個樣子的,但這個樣子是跑不起來的,稍後我們再回來改。

public class PersonController : Controller
{
    
    // GET: Person
    public ActionResult Index()
    {
        return View();
    }
}

有了 Controller 接著我們要新增 Model ,首先我們加一個類別 Person 用來對應到資料庫,它的功能就只是一個DTO 的類別,所以裡面不會有任何的方法。

public class Person
{
   public String FirstName { get; set; }
   public String MiddleName { get; set; }
   public String LastName { get; set; }
}

 

接著我們再新加一個類別 PersonRepository,這個類別的用途在於提供資料,所以有個QueryAll() 的方法,這裡我們並沒有採用EF機制,原因很簡單,在Web Form的開發上最常見的都是自已使用ADO.NET來做資料繫結,也就是說團隊成員相當習慣跟SQL Command相處了,如果因為要轉MVC而一下全面要求改用EF,那麼團隊的學習曲線會拉高,抗拒性會較大不是個好現象,當然如果團隊已經早就有在使用EF的話,那麼就另當別論囉。所以這裡我採用了一個輕量化的ORM Framework Dapper來做,如果想知道 Dapper 是什麼,可以參考我先前的文章 ( Dapper - 輕量級ORM ) ,使用 Dapper 的話,基本上程式在撰寫上不用調整太多,同樣用熟悉的SQL語法,程式碼會是這樣的。

public List<Person> QueryAll()
{
   List<Person> result = new List<Person>();
 
   using (SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["defconn"].ConnectionString))
   {
       result = conn.Query<Person>("select * from Person.Person").ToList();
   }
   return result;
}

好了,當我們備妥 Controller 和 Model之後 ,接著我們回到 Controller ,在Controller 裡宣告一個 PersonRepository 私有成員 ,然後在 Index() 方法裡回傳 PersonRepository.QueryAll方法的結果集合。

public class PersonController : Controller
{
   private PersonRepository personRepository = new PersonRepository(); 
 
   // GET: Person
   public ActionResult Index()
   {
       return View(personRepository.QueryAll());
   }
}

有了Controller 和 Model,接著就是View了,要新增一個 View 很簡單,只要在 Controller 的方法上按右鍵,就有新增檢視的功能,以這個範例來說就是在Index方法上按右鍵。

image

接著會有個對話框來進行相關設定,View 的名稱與Controller 的方法相同,範本這裡我們先選擇 List ( 有其它選擇往後我們再談 ),模型類別就選擇我們的 Model【Person】,然後取消使用版面配置頁。

image

 

 

完成後,就會在View / Person 目錄裡產生檢視頁面的檔案。

image

@model IEnumerable<MVCStartup.Models.Person>
 
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.FirstName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.MiddleName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.LastName)
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.FirstName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.MiddleName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
    }
    
    </table>
</body>
</html>

檢視頁面的組成,如果您有寫過ASP的話,應該會感到很眼熟,裡面就是很標準的HTML,這跟使用 Web From 就有很大的差別,在 Web From 裡常見都是ASP.NET的控制項宣告Tag,而ASP.NET MVC 則沒有伺服器控制項的慨念,就是標準的HTML,這也就是為什麼說如果您想處理 RWD 的網站,使用 ASP.NET MVC 會比較容易的原因,因為你可以完全操控 HTML ,除了HTML之外,您還可以看到有 foreach ,這裡常會有人質疑說,MVC 不是強調程式碼邏輯跟UI 分離嗎? 怎麼這裡還會有foreach呢? 其實這裡的foreach只是用來控制 UI 的展現邏輯,而不是所謂的商業邏輯,千萬可別誤會了。而在檢視頁面的開頭我們必須告知與哪一個Model進行綁定,綁定之後,在編排 HTML 時就可以直接採用物件屬性的方式來進行繫結【@Html.DisplayFor(modelItem => item.LastName)】,執行後會是這樣的,當然樣式美觀的部份就由CSS來處理囉,在這裡我們就先略過。

image

在本篇中簡單的講解了從 WebForm 到 MVC 如何跨出資料列表的第一步,在這個過程中會發現在,原本在WebForm 可能就單一隻程式碼檔搞定,但是在 MVC裡就必須分成多個檔案來處理,而 MVC 的精神也就在於職責分離,該是View 就只要負責 View 就好,同理Controller、Model也是如此。在這裡我們不談EF,也先不談系統設計架構,單純從WebForm 到 MVC 的角度來看,期許讓WebForm 開發人員用最簡單的方式,了解到跨入MVC 是怎麼一回事,當然再進階一點就會是整體的系統設計架構了,不過那會是另一個議題層面就是了。在下一篇我們要來看看如何加入單筆資料的明細檢視功能。

 

若本文對您有所幫助,歡迎轉貼,但請在加註【轉貼】及來源出處,並在附上本篇的超連結,感恩您的配合囉。

By No.18