【 MVC 】顯示資料庫資料表格
之前看。net之美很多地方都看不明白,但是今天重新看了一下,覺得很有感悟。
我演示了在一個HTML表格中格式化一系列資料庫記錄的兩個方法。首先,我演示瞭如何直接在檢視中格式化資料庫記錄。接下來,我示範瞭如何在格式化資料庫記錄時利用部分類。
1.1建立模型類
我們將要顯示Movies資料庫表中的一系列記錄。Movies資料庫表包含下面的列:
Column Name | Data Type | Allow Nulls |
Id | Int | False |
Title | Nvarchar(200) | False |
Director | NVarchar(50) | False |
DateReleased | DateTime | False |
為了表示Movies資料庫表,我們將利用Linq to SQL作為我們的資料訪問技術。換言之,我們將會使用LINQ to SQL來繫結我們的MVC模型類。
建立一系列LINQ to SQL類的最快辦法就是利用Visual Studio Object Relational Designer(Visual Studio 物件關係設計器)。右鍵點選Models資料夾,選擇“Add(新增)”,“New Item(新建項)”,選擇Linq To Sql類模板,將這個類命名為Movie.dbml,並且點選Add按鈕(如圖1)。
圖1:建立LINQ to SQL類
在你建立完Movie Linq to Sql 類以後,會立即出現物件關係設計器。你可以將資料庫表從伺服器瀏覽器(Server Explorer)視窗中拖曳到物件關係設計器中,以便建立代表著特定資料庫表的Linq to Sql類。你需要將Movies資料庫表新增到物件關係設計器中(如圖2)。
圖2:使用物件關係設計器
預設情況下,物件關係設計器將會試圖建立一個類名,該類名是資料庫表名的單數版本。換言之,如果你有一個叫做Customers的資料庫表,那麼物件關係設計器將會建立一個叫做Customer的類名。
通常,物件關係設計器非常適合完成這件事。不幸的是,物件關係設計器將資料庫表名Movies轉換為了Movy(很接近,但是錯的)。通過在設計器中的類名上點選,並且將類名由Movy改為Movie,你可以很容易地修正這個問題。
最後,記得點選“Save(儲存)”(軟盤圖示)按鈕來儲存LINQ to SQL類。否則的話,LINQ to SQL類將不會由物件關係設計器生成。
1.2 在控制器動作中使用LINQ to SQL
現在我們已經有了LINQ to SQL類,我們可以使用這些類從資料庫獲取資料。程式碼清單1中的控制器類使用LINQ to SQL類獲取來自Movies資料庫表的記錄。
程式碼清單1 – Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers{
[HandleError]
public class
HomeController : Controller {
public ActionResult Index() {
var dataContext =
new MovieDataContext();
var movies = from m in dataContext.Movies
select m;
return View(movies);
}
}
}
程式碼清單1中的Index()動作使用LINQ to SQL MovieDataContext類來獲取來自資料庫表中的電影。電影列表被傳遞給了Index檢視,作為ViewData.Model屬性的值。
1.3 在檢視中進行格式化
格式一系列資料庫記錄最簡單、但不一定是最好的辦法,就是直接在檢視中執行格式化。舉個例子,程式碼清單2中的Index檢視在一個HTML表格中呈現了movie資料庫的記錄。
程式碼清單2 – Views\Home\Index.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<table>
<tr>
<th>Id</th><th>Title</th><th>Release Date</th>
</tr>
<% foreach (Movie m in (IEnumerable)ViewData.Model)
{ %>
<tr>
<td><%= m.Id %></td>
<td><%= Html.Encode(m.Title) %></td>
<td><%= m.DateReleased %></td>
</tr>
<% } %>
</table>
</asp:Content>
程式碼清單2中的檢視包含了一個foreach迴圈,該迴圈遍歷了movie記錄集中的每一個記錄。Movie的每一個屬性值都顯示在了各自的表格單元格中。表格的行由HTML <tr>標籤建立,表格單元格由HTML <td>標籤建立。
注意到Html.Encode()幫助方法用於在顯示每個屬性值之前對其進行編碼。任何時候當你接受使用者輸入,並且將輸入重新顯示在網頁上時,對輸入進行編碼以阻止JavaScript注入攻擊都是很重要的。當你對顯示HTML內容前對它進行編碼漠不關心時,黑客便可以做一些惡毒且邪惡的事情,例如從你的網站使用者中盜取私人資料。
當你執行應用程式,Index檢視會呈現如圖3所示的頁面。
圖3:使用HTML表格格式化了的資料庫記錄
圖3中HTML表格的格式化並不那麼令人興奮。我們可以通過建立層疊樣式表來改進HTML表格的外觀。因為程式碼清單2中的檢視是一個content檢視,我們必須將層疊樣式表新增到與content檢視相關聯的模板頁中。這個模板頁位於下面路徑:
\Views\Shared\Site.master
為了改進HTML表格的外觀,我們可以將程式碼清單3中的樣式表新增到模板頁<head>的開閉標籤之間。
程式碼清單3 – 層疊樣式表
<style type="text/css">
table
{
border-collapse:collapse;
}
table td, table th
{
border: solid 1px black;
padding:10px;
}
</style>
程式碼清單3中的樣式表將單元格之間的邊框合併起來,並且添加了網格(gridlines)。在你將這個樣式表新增到模板頁之後,Index檢視呈現出圖4中的頁面。
圖4:使用了樣式的HTML表格
1.4 在區域性中格式化
除了在檢視本身中執行所有的格式化以外,你可以使用區域性頁面(partial)作為一個模板來格式化每一個數據庫記錄。舉個例子,程式碼清單4中的區域性頁面代表著對於一個特定movie資料庫記錄的格式化。
程式碼清單4 –\Views\Movies\MovieTemplate.ascx
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="MovieTemplate.ascx.cs" Inherits="MvcApplication1.Views.Movies.MovieTemplate" %>
<tr>
<td> <%=ViewData.Model.Id%></td>
<td> <%=Html.Encode(ViewData.Model.Title)%></td>
<td> <%=ViewData.Model.DateReleased.ToString("D")%></td>
</tr>
程式碼清單4中的模板將每個movie記錄格式化為一個HTML表格行。模板應用到每一個數據庫記錄上。注意到ViewData.Model屬性,位於區域性頁面中,代表著單個數據庫記錄,而不是所有的資料庫記錄集。
為了將ViewData.Model屬性轉換為Movie類的例項,你需要為這個區域性頁面建立一個程式碼後置類。程式碼清單5中的程式碼後置類指定了MovieTemplate部分類繼承自一個泛型類,該泛型類將Movie作為它的型別引數。
程式碼清單5 - \Views\Movies\MovieTemplate.ascx.cs
using MvcApplication1.Models;
namespace MvcApplication1.Views.Movies
{
public partial class
MovieTemplate : System.Web.Mvc.ViewUserControl<Movie>
{
}
}
MovieTemplate類繼承自ViewUserControl<movie>類。因為MovieTemplate類繼承自這個類,ViewData.Model屬性自動轉換為Movie。
程式碼清單6中的Index檢視演示瞭如何在檢視中使用MovieTemplate部分類。Html.RenderPartial()方法用於呈現MovieTemplate區域性頁面。
程式碼清單 6 – \Views\Movies\Index.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Movies.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<table>
<tr>
<th>Id</th><th>Title</th><th>Release Date</th>
</tr>
<% foreach (Movie m in (IEnumerable)ViewData.Model)
{
Html.RenderPartial("MovieTemplate", m);
} %>
</table>
</asp:Content>
在程式碼清單6中,Html.RenderPartial()方法用於為每個Movie記錄呈現MovieTemplate區域性頁面。兩個引數傳遞給了RenderPartial()方法。第一個引數是將要呈現的區域性頁面的名稱。和檢視一樣,預設情況下,區域性頁面必須位於Views\ControlName 資料夾或者是 Views\Shared資料夾。
第二個引數指定了傳遞給部分的檢視資料。在區域性頁面內部,ViewData.Model屬性將會代表一個特定的Movie記錄。
還有一個重要的警告。與大多數其他幫助方法不同,Html.RenderPartial()方法並不會返回一個字串。這意味著你不能像下面這樣呼叫RenderPatial()方法:
<%= Html.RenderPartial("MovieTemplate", m) %>
相反,你應該這樣呼叫這個方法:
<% Html.RenderPartial("MovieTemplate", m) %>
RenderPartial()方法完成了一些事情,但它不會表示出來。
1.5 小結
這本書探索了格式化資料庫記錄的兩個方法。首先,我們直接在一個檢視中格式化資料庫記錄。接下來,使用一個區域性頁面作為模板來格式化每一個數據庫記錄。