Asp.Net MVC 视图(显示数据库数据表格) - Part.3

在这篇教程中,我示范了显示一系列数据库记录的两个方法。我演示了在一个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 小结

这篇教程的目的是演示如何在一个HTML表格中显示一系列的数据库记录。我们探索了格式化数据库记录的两个方法。首先,我们直接在一个视图中格式化数据库记录。接下来,我们使用一个局部页面作为模板来格式化每一个数据库记录。