[ASP.NET][MVC] ASP.NET MVC (3) : 加入資料檢視功能-Models

我們在前一篇文章中,實作了最簡單的 Controllers 與 Views,也看到了這兩個物件之間的關聯性,但是 MVC 中還少一個東西,就是 Models,但還是老樣子,雖然很多書都用 LINQ to SQL 或 Entity Framework 來當 Models,但是我仍然堅持要由最簡單最原始的方式來實作,所以我們一樣由類別來實作 Models。

我們在前一篇文章中,實作了最簡單的 Controllers 與 Views,也看到了這兩個物件之間的關聯性,但是 MVC 中還少一個東西,就是 Models,但還是老樣子,雖然很多書都用 LINQ to SQL 或 Entity Framework 來當 Models,但是我仍然堅持要由最簡單最原始的方式來實作,所以我們一樣由類別來實作 Models。

首先,在 Models 資料夾中加入自訂的類別 (以 Northwind 資料庫為範例):

namespace MvcApplication1.Models
{
    public class Customer
    {
        public string CustomerID { get; set; }
        public string CompanyName { get; set; }
        public string ContactName { get; set; }
        public string ContactTitle { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string Phone { get; set; }
        public string Fax { get; set; }
    }
}

然後加入一個讀取資料的物件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Data;
using System.Data.SqlClient;

namespace MvcApplication1.Models
{
    public class CustomerDataContext
    {
        public static List<Customer> LoadCustomers()
        {
            List<Customer> customers = new List<Customer>();
            SqlConnection conn = new 
                SqlConnection("initial catalog=northwind; integrated security=SSPI");
            SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", conn);

            conn.Open();
            SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            while (reader.Read())
            {
                Customer customer = new Customer();

                for (int i = 0; i < reader.FieldCount; i++)
                {
                    PropertyInfo property = 
                        customer.GetType().GetProperty(reader.GetName(i));
                    property.SetValue(customer, 
                        (reader.IsDBNull(i)) ? "[NULL]" : reader.GetValue(i), null);
                }

                customers.Add(customer);
            }

            reader.Close();

            return customers;
        }
    }
}

接著,修改 MyController,加入一個 Customers 方法,並且由 CustomerDataContext 將 Customer 資料讀出來,再交給 View:

public ActionResult Customers()
{
    List<Models.Customer> customers = Models.CustomerDataContext.LoadCustomers();
    return View(customers);
}

再來,和前一篇文章一樣,我們手動加入一個新的 View 在 /Views/My 資料夾下,名稱為 Customers:

@model IList<MvcApplication1.Models.Customer>
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <title>List Northwind Customers</title>
</head>
<body>
    <div>
        <p>
            Customer List:</p>
        <table cellpadding="9" cellspacing="0" border="1">
            <tr>
                <td>
                    ID
                </td>
                <td>
                    Company Name
                </td>
                <td>
                    Contactor Name
                </td>
                <td>
                    Address
                </td>
                <td>
                    Phone
                </td>
                <td>
                    Fax
                </td>
            </tr>
            @foreach (var modelItem in this.Model)
            {
                <tr>
                    <td>@modelItem.CustomerID
                    </td>
                    <td>@modelItem.CompanyName
                    </td>
                    <td>@modelItem.ContactName
                    </td>
                    <td>@modelItem.Country + @modelItem.City + @modelItem.Address
                    </td>
                    <td>@modelItem.Phone
                    </td>
                    <td>@modelItem.Fax
                    </td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

 

看起來和前一篇很像,但我們加了點工,為了要讓 View 認識我們傳入的 Model 的型別,我們先在第一行宣告了 Model 的型別,即使用 @model 指令,設定 Model 的型別,如此我們才可以在 Visual Studio 的編輯器中享有強型別的好處。然後加入一個表格,將資料繫結進去,語法一樣是使用 foreach,但這次資料來源不是 ViewData,而是 this.Model,this.Model 則是在 Controller 的程式中設定給 View 參數的物件。

執行起來如下圖:

image

只有列表還不夠,我們會想要實作一個 Master/Detail 的應用程式,所以除了 List 以外,我們還要有個 Detail,所以我們先修改 MyController,加入檢視 Detail 資料的動作:

public ActionResult Details(string CustomerID)
{
    var customer = from customerItem in Models.CustomerDataContext.LoadCustomers()
                    where customerItem.CustomerID == CustomerID
                    select customerItem;

    if (customer.Count() == 0)
        return new HttpNotFoundResult();
    else
        return View(customer.First());
}

然後再於 Views 中加入一個 Details.cshtml (Razor 的預設副檔名都是 cshtml,若是 ASPX 則是 .aspx):

@model MvcApplication1.Models.Customer
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Customer Detail</title>
</head>
<body>
    <div>
        <ul>
            <li>ID: @this.Model.CustomerID</li>
            <li>Company Name: @this.Model.CompanyName</li>
            <li>Contactor Name: @this.Model.ContactName</li>
            <li>Contactor Title: @this.Model.ContactTitle</li>
            <li>Address: @this.Model.Country @this.Model.City @this.Model.Address</li>
            <li>Phone: @this.Model.Phone</li>
            <li>Fax: @this.Model.Fax</li>
            <li>Region: @this.Model.Region</li>
        </ul>
        @Html.ActionLink("Return To List", "Customers")
    </div>
</body>
</html>

在明細頁的部份,我們使用了一個 HtmlHelper 的方法 ActionLink,它會產生連結到指定 Action 的頁面的連結,因為我們要回到列表頁,所以直接傳入 Customers 即可。接著,我們要修改列表頁,讓它可以進入明細頁,所以我們修改了 CustomerID 這一欄,同樣是設定 Html.ActionLink,但這次我們會傳入參數:

@foreach (var modelItem in this.Model)
{
    <tr>
        <td>@Html.ActionLink(modelItem.CustomerID, "Details", new { CustomerID = modelItem.CustomerID })
        </td>
        <td>@modelItem.CompanyName
        </td>
        <td>@modelItem.ContactName
        </td>
        <td>@modelItem.Country + @modelItem.City + @modelItem.Address
        </td>
        <td>@modelItem.Phone
        </td>
        <td>@modelItem.Fax
        </td>
    </tr>
}

完成後,瀏覽 /My/Customers,會看到原本 CustomerID 的部份會變成連結:

image

點進去後會變成明細頁:

image

 

PS: 有趣的是,如果參數是是字串,產生的 URL 會是 "/Action?name=value",但如果是整數,則會直接附加在 Action 之後,如 "/Action/{value}"。

 

Reference:

http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-2