【 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 小结
这本书探索了格式化数据库记录的两个方法。首先,我们直接在一个视图中格式化数据库记录。接下来,使用一个局部页面作为模板来格式化每一个数据库记录。