原文出处:Chapter 2 - Building a Simple ASP.NET MVC Application
在上一章,我们讨论了ASP.NET MVC 框架的崇高目标,在本章中,我们完全忽略它们,我们以最简单的可能方式来构建一个数据库驱动的ASP.NET MVC 应用程序。我们忽略设计原则和模式,甚至连简单的单元测试也不会创建。本章的目标就是说明构建ASP.NET MVC 应用程序的基本机制。
在本章中,我们构建一个简单的玩具商店程序,我们的程序可以现实一个玩具的列表,并且可以新建玩具。换言之,它可以说明如何构建应用程序,来对数据库执行基本的操作。
*** Begin Note ***
本书的第三部分专门用来讲述如何通过“正确”的方式来构建ASP.NET MVC 程序,我们会利用软件设计原则和模式以及测试驱动来构建一个论坛应用程序。
*** End Note ***
Starting with a Blank Slate
让我们开始创建一个新的ASP.NET MVC 程序,并且移除所有的示例文件。请按照以下步骤新建一个ASP.NET MVC 应用程序工程:
1. 运行Visual Studio 2008 。
2. 选择File->New Project 。
3. 在New Project 对话框中 ,选择你喜欢的编程语言和ASP.NET MVC Web 应用程序模板( 参见图1 )。
4. 为你的新工程命名为ToyStore ,点击OK 按钮。
图1 – 创建新的ASP.NET MVC 工程
当你创建一个新的ASP.NET MVC 工程,会自动出现创建单元测试工程的对话框(参见图2 ),当被询问是否创建一个单元测试工程时,选择Yes, 创建一个测试工程 ( 通常,你应该总是选择Yes ,因为当你创建好ASP.NET MVC 工程后,在条件单元测试工程,会是一个痛苦的过程) 。
图2 – 创建单元测试工程对话框
*** Begin Note ***
当你使用Microsoft Visual Web Developer 创建ASP.NET MVC 工程时,单元测试工程对话框是不会出现的,因为Visual Web Developer 不支持测试工程类型。
*** End Note ***
就像我们在上一章中讨论的那样,当创建一个ASP.NET MVC 应用程序时,你会默认得到几个示例文件。这些文件对我我们构建一个新的应用程序来说,是一个阻碍。请在ASP.NET MVC 工程中删除以下文件:
[C#]
\Controllers\HomeController.cs
\Views\Home\About.aspx
\Views\Home\Index.aspx
[VB]
\Controllers\HomeController.vb
\Views\Home\About.aspx
\Views\Home\Index.aspx
Delete the following file from your Test project.
[C#]
\Controllers\HomeControllerTest.cs
[VB]
\Controllers\HomeControllerTest.vb
*** Begin Tip ***
如果你想总是以一个空的ASP.NET MVC 工程开始,那么在删除示例文件后,你可以创建一个新的Visual Studio 工程模板,可以通过选择File->Export Template 来创建一个新的工程模板。
*** End Tip ***
Creating the Database
我们需要创建一个数据库和数据库表,来保存我们玩具商店中的玩具列表,ASP.NET MVC 框架和任何当前主流的数据库兼容,包括Oracle 11g 、MySQL 和Microsoft SQL Server 。
在本书中,我们使用Microsoft SQL Server Express 作为我们的数据库。Microsoft SQL Server Express 是Microsoft SQL Server 的一个免费版本,它包含了Microsoft SQL Server 完整版本的所有基本功能(使用的数据库引擎是一样的)。
*** Begin Note ***
当你安装Visual Studio 或者Visual Web Developer 时,可以选择安装Microsoft SQL Server Express (这是一个安装选项)。你可以通过访问以下站点对Microsoft SQL Server Express 进行网络安装:http://www.asp.net/downloads/ 。
*** End Note ***
请按照以下步骤在Visual Studio 中创建一个新的数据库:
1. 在解决方案窗口的App_Data 文件上单击鼠标右键,选择Add->New Items 。
2. 在Add New Item 对话框中,选择SQL Server Database 模板 ( 参见图3) 。
3. 为新的数据库命名为ToyStoreDB 。
4. 点击Add 按钮。
图3– 添加一个新的SQL Server 数据库
在创建完数据库后,你需要创建一个Table ,来保存玩具列表。请按照以下步骤创建Products 表:
1. 在App_Data 文件夹中双击ToyStoreDB.mdf 文件,打开连接ToyStoreDB 数据库的Server Explorer 窗口。
2. 在Tables 文件夹上点击鼠标右键,选择Add New Table 。
3. 在Table 设计器中输入表1 所列的所有列(参见图4 )。
4. 通过以下方式将Id 列设置为Identify 列:在Column Properties 中展开Identify Specification 节点,然后将 Is Identity 属性设置为Yes 。
5. 通过以下方式将Id 列设置为主键列:在Table 设计器中选择该列,然后点击Set Primary Key 按钮。
6. 通过点击Save 按钮保存Table 。Save the new table by clicking the Save button ( 一个带有过时的软盘图标的按钮) 。
7. 在Choose Name 对话框中,输入名称 Products 。
表 1 – Products 表中的列
列名
数据类型
是否允许为空
Id
Int
False
Name
Nvarchar(100)
False
Description
nvarchar(MAX)
False
Price
money
False
图 4 – 创建Products 表
*** Begin Note ***
在Visual Web Developer 中,服务器浏览器被称为数据库浏览器。
*** End Note ***
在完成Products 表的创建后,你应该向其中插入一些数据。在服务器窗口中右键单击Products 表,选择Show Table Data ,输入两三条产品信息(参见图5 )。
图 5 – 在Products 表中输入示例数据
Creating the Model
在ASP.NET MVC 程序中,我们需要创建模型类来表示数据库中的表,创建模型类最容易的方法就是利用ORM ,自动的从数据库中生成模型类。
你可以将你喜欢的ORM 和ASP.NET MVC 框架合在一起使用,ASP.NET MVC 框剪并没有和任何ORM 绑定在一起。例如,ASP.NET MVC 和Microsoft LINQ to SQL 、NHibernate 以及Microsoft Entity 框架都兼容。
在本书中,我们使用Microsoft Entity 框架来生成我们的模型类,我们关注Microsoft Entity 框架是因为这个框架啊是Microsoft 在数据访问解决方案方面推荐的框架。
*** Begin Note ***
为了使用Microsoft Entity 框架, 你需要安装.NET Framework 3.5 SP1 。
*** End Note ***
请按照以下步骤生成数据模型类:
1. 在解决方案窗口的Models 文件夹上右键点击鼠标,选择 Add->New Item 。
2. 选择Data 种类和ADO.NET Entity Data Model 模板 ( 参见图6) 。
3. 将数据模型命名为ToyStoreDataModel.edmx ,点击Add 按钮。
图6 – 添加ADO.NET Entity 数据模型类
在完成以上步骤后,会运行Entity 模型数据向导。完成以下这些向导步骤:
1. 在Choose Model Contents 步骤, 选择Generate from database 。
2. 在Choose Your Data Connection 步骤, 选择ToyStoreDB.mdf 数据连接,将实体连接命名为ToyStoreDBEntities ( 参见图7) 。
3. 在Choose Your Database Objects 步骤, 选择Products 表,并输入模型类的命名空间 ( 参见图8) 。
4. 点击Finish 按钮,完成向导。
图 7 – 选择数据连接
Figure 8 – 输入模型类的命名空间
在完成Entity 数据模型向导后,可以看到Entity 设计器,设计器中只带了一个名为Products 的实体(参见图9 )。Entity 框架已经生成了一个名为Products 的类,用来表示数据库中的Products 表。
大部分情况下,你会想重命名通过Entity 框架生成的模型类,Entity 框架简单的将实体的名字命名为数据苦衷对应的表名,因为Products 类代表一个特定的产品,你可能想将其名称更改为Products 。 ( 单数而不是复数) 。
在Entity 设计器中右键单击Products 实体,选择Rename ,输入名称Product 。
图9 – Entity 设计器
至此,我们已经成功的创建了模型类。在ASP.NET MVC 程序中,我们可以使用这些类来代表ToyStoreDB 数据库中的表。
*** Begin Note ***
在以后,你可以通过双击Models 文件夹中的ToyStoreDataModel.edmx 来打开Entity 设计器。
*** End Note ***
Creating the Controller
在ASP.NET MVC 程序中,控制器控制应用程序执行的流程。被默认出发的控制器名为Home ,我们可以通过以下步骤创建Home 控制器:
1. 在Controller 文件夹上右键点击鼠标,选择Add Controller 。
2. 在Add Controller 对话框中, 输入控制器的名称: HomeController , 然后勾选上Add action methods for Create, Update, and Details scenarios ( 参见图10) 。
3. 点击Add 按钮,创建新的控制器。
图10 – 添加新的控制器
Home 控制器的内容如列表1 所示。
列表1 – Controllers\HomeController.cs [C#]
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
using
System.Web.Mvc.Ajax;
namespace
ToyStore.Controllers {
public
class
HomeController : Controller {
//
//
GET: /Home/
public
ActionResult Index() {
return
View(); }
//
//
GET: /Home/Details/5
public
ActionResult Details(
int
id) {
return
View(); }
//
//
GET: /Home/Create
public
ActionResult Create() {
return
View(); }
//
//
POST: /Home/Create
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult Create(FormCollection collection) {
try
{
//
TODO: Add insert logic here
return
RedirectToAction(
"
Index
"
); }
catch
{
return
View(); } }
//
//
GET: /Home/Edit/5
public
ActionResult Edit(
int
id) {
return
View(); }
//
//
POST: /Home/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult Edit(
int
id, FormCollection collection) {
try
{
//
TODO: Add update logic here
return
RedirectToAction(
"
Index
"
); }
catch
{
return
View(); } } } }
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
namespace ToyStore.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
//
// GET: /Home/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /Home/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Home/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
try
{
// TODO: Add insert logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Home/Edit/5
public ActionResult Edit(int id)
{
return View();
}
//
// POST: /Home/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection collection)
{
try
{
// TODO: Add update logic here
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
ing System;
列表 1 – Controllers\HomeController.vb [VB]
Public
Class
HomeController
Inherits
System.Web.Mvc.Controller
'
'
GET: /Home/
Function
Index()
As
ActionResult
Return
View()
End Function
'
'
GET: /Home/Details/5
Function
Details(
ByVal
id
As
Integer
)
As
ActionResult
Return
View()
End Function
'
'
GET: /Home/Create
Function
Create()
As
ActionResult
Return
View()
End Function
'
'
POST: /Home/Create
<
AcceptVerbs(HttpVerbs.Post)
>
_
Function
Create(
ByVal
collection
As
FormCollection)
As
ActionResult
Try
'
TODO: Add insert logic here
Return
RedirectToAction(
"
Index
"
)
Catch
Return
View()
End
Try
End Function
'
'
GET: /Home/Edit/5
Function
Edit(
ByVal
id
As
Integer
)
As
ActionResult
Return
View()
End Function
'
'
POST: /Home/Edit/5
<
AcceptVerbs(HttpVerbs.Post)
>
_
Function
Edit(
ByVal
id
As
Integer
,
ByVal
collection
As
FormCollection)
As
ActionResult
Try
'
TODO: Add update logic here
Return
RedirectToAction(
"
Index
"
)
Catch
Return
View()
End
Try
End Function
End Class
因为我们在新建Home 控制器时,勾选了Public Class HomeController
Inherits System.Web.Mvc.Controller
'
' GET: /Home/
Function Index() As ActionResult
Return View()
End Function
'
' GET: /Home/Details/5
Function Details(ByVal id As Integer) As ActionResult
Return View()
End Function
'
' GET: /Home/Create
Function Create() As ActionResult
Return View()
End Function
'
' POST: /Home/Create
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(ByVal collection As FormCollection) As ActionResult
Try
' TODO: Add insert logic here
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
'
' GET: /Home/Edit/5
Function Edit(ByVal id As Integer) As ActionResult
Return View()
End Function
'
' POST: /Home/Edit/5
<AcceptVerbs(HttpVerbs.Post)> _
Function Edit(ByVal id As Integer, ByVal collection As FormCollection) As ActionResult
Try
' TODO: Add update logic here
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
generate Create, Update, and Details methods, 所以列表1 所示的内容中包括了这些action 。特别的,Home 控制器对外暴露了以下action :
· Index() – 这是控制器默认的action ,一般的,这个action 用来显示一些条目的列表。
· Details(id) – 这个action 显示某一个特定条目的详细内容。
· Create() – 这个action 显示一个新建条目的窗体。
· Create (collection) – 这个action 将一个新的条目插入到数据库中。
· Edit(id) – 这个action 显示一个用于编辑现有条目的窗体。
· Edit(id, collection) – 这个action 将现有条目更新到数据库中。
目前,Home 控制器中只包含了这些action 的声明,我们继续使用由Entity 框架生成的数据模型类来实现Index () 和 Create ()。更新后的Home 控制器内容如列表2 所示。
列表2 – Controllers\HomeController.cs [C#]
using
System.Linq;
using
System.Web.Mvc;
using
ToyStore.Models;
namespace
ToyStore.Controllers {
public
class
HomeController : Controller {
private
ToyStoreDBEntities _dataModel
=
new
ToyStoreDBEntities();
//
//
GET: /Home/
public
ActionResult Index() {
return
View(_dataModel.ProductSet.ToList()); }
//
//
GET: /Home/Create
public
ActionResult Create() {
return
View(); }
//
//
POST: /Home/Create
[AcceptVerbs(HttpVerbs.Post)]
public
ActionResult Create([Bind(Exclude
=
"
Id
"
)]Product productToCreate) {
if
(
!
ModelState.IsValid)
return
View();
try
{ _dataModel.AddToProductSet(productToCreate); _dataModel.SaveChanges();
return
RedirectToAction(
"
Index
"
); }
catch
{
return
View(); } } } }
using System.Web.Mvc;
using ToyStore.Models;
namespace ToyStore.Controllers
{
public class HomeController : Controller
{
private ToyStoreDBEntities _dataModel = new ToyStoreDBEntities();
//
// GET: /Home/
public ActionResult Index()
{
return View(_dataModel.ProductSet.ToList());
}
//
// GET: /Home/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Home/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude="Id")]Product productToCreate)
{
if (!ModelState.IsValid)
return View();
try
{
_dataModel.AddToProductSet(productToCreate);
_dataModel.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}
列表using System.Linq;
2 – Controllers\HomeController.vb [VB]
Public
Class
HomeController
Inherits
System.Web.Mvc.Controller
Private
_dataModel
As
New
ToyStoreDBEntities()
'
'
GET: /Home/
Function
Index()
As
ActionResult
Return
View(_dataModel.ProductSet.ToList())
End Function
'
'
GET: /Home/Create
Function
Create()
As
ActionResult
Return
View()
End Function
'
'
POST: /Home/Create
<
AcceptVerbs(HttpVerbs.Post)
>
_
Function
Create(
<
Bind(Exclude:
=
"
Id
"
)
>
ByVal
productToCreate
As
Product)
As
ActionResult
If
Not
ModelState.IsValid
Then
Return
View()
End
If
Try
_dataModel.AddToProductSet(productToCreate) _dataModel.SaveChanges()
Return
RedirectToAction(
"
Index
"
)
Catch
Return
View()
End
Try
End Function
End Class
请注意在列表2 所示内容的顶部有一个私有字段,类型为DBStoreEntities ,名为_dataModel 。DBStoreEntities 类是由Entity 模型数据向导生成的一个类,用于和数据库进行通信。 Public Class HomeController
Inherits System.Web.Mvc.Controller
Private _dataModel As New ToyStoreDBEntities()
'
' GET: /Home/
Function Index() As ActionResult
Return View(_dataModel.ProductSet.ToList())
End Function
'
' GET: /Home/Create
Function Create() As ActionResult
Return View()
End Function
'
' POST: /Home/Create
<AcceptVerbs(HttpVerbs.Post)> _
Function Create(<Bind(Exclude:="Id")> ByVal productToCreate As Product) As ActionResult
If Not ModelState.IsValid Then
Return View()
End If
Try
_dataModel.AddToProductSet(productToCreate)
_dataModel.SaveChanges()
Return RedirectToAction("Index")
Catch
Return View()
End Try
End Function
End Class
Index ()action 已经被改为返回一个产品的列表。_dataModel.ProductSet.ToList() 语句返回从Products 表中返回的一个products 的列表。
内容中包含了两个Create () action ,第一个Create () action 用于显示一个创建新产品的窗体,这个窗体被提交给第二个Create () action ,这个action 向数据库中插入新产品。
请注意第二个Create () action 已经被改为接收一个Products 参数。Product 类也是由Entity 模型数据向导生成的,它里面的每一个属性对应数据库Products 表中的一列。
最后,Create () action 调用以下方法来向数据库中添加新的产品信息:
[C#]
_dataModel.AddToProductSet(productToCreate);
_dataModel.SaveChanges();
[VB]
_dataModel.AddToProductSet(productToCreate)
_dataModel.SaveChanges()
现在Home 控制器中已经包含了所有必要的数据库逻辑。我们可以使用这个控制器返回一个产品的集合,并可以新建一个产品。
请注意Index ()和Create ()方法都返回一个View 对象,接下来,也是最后一步,我们来创建这些View 。
Creating the Views
一个MVC 视图中包含了所有的HTML 标签和用于生成HTML 页的视图逻辑。这些由ASP.NET MVC 程序暴露出来的视图集合就是程序的可以看到的外表。
*** Begin Note ***
视图并不一定是HTML 。例如,你可以创建一个Sliverlight 视图。
*** End Note ***
我们的简单程序需要两个视图:Index 视图和Create 视图。我们使用Index 视图来现实所有的产品列表,使用Create 视图来显示创建新产品的窗体。
Adding the Index View
让我们先创建Index 视图,请按照以下步骤创建:
1. 选择菜单Build->Build Solution 来编译应用程序。
2. 在代码编辑器中右键单击Index (),选择Add View ( 参见图11).
3. 在Add View 对话框中,选择 Create a strongly-typed view 。
4. 在Add View 对话框中, 从View data class 的下拉列表中,选择ToyStore.Models.Product 类。
5. 在Add View 对话框中, 从View Content 的下拉列表中,选择List 。
6. 点击Add 按钮,将新的视图添加到你的工程中(参见图12 )。
图 11 – 添加一个视图
图 12 – 添加视图对话框
*** Begin Note ***
为了在View data class 下拉列表中显示类的名字,你需要在添加视图之前重新编译程序。如果程序编译不通过,那么这个列表会显示为空。
*** End Note ***
视图会被添加到Views 文件夹,视图遵循一个特别的命名约定。通过Home 控制器的Index ()返回的视图的存储位置如下:
\Views\Home\Index.aspx
一般,视图遵循以下的命名约定:
\Views\Controller Name \Action Name .aspx
Index 视图的内容如列表3 所示,这个视图循环了所有的产品,然后将其显示到HTML 中的表格中(参见图13 )。
列表3 – Views\Home\Index.aspx [C#]
<%
@ Page Title
=
""
Language
=
"
C#
"
MasterPageFile
=
"
~/Views/Shared/Site.Master
"
Inherits
=
"
System.Web.Mvc.ViewPage<IEnumerable<ToyStore.Models.Product>>
"
%>
<
asp:Content
ID
="Content1"
ContentPlaceHolderID
="head"
runat
="server"
>
<
title
>
Index
</
title
>
</
asp:Content
>
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
Index
</
h2
>
<
table
>
<
tr
>
<
th
></
th
>
<
th
>
Id
</
th
>
<
th
>
Name
</
th
>
<
th
>
Description
</
th
>
<
th
>
Price
</
th
>
</
tr
>
<%
foreach (var item in Model) {
%>
<
tr
>
<
td
>
<%
=
Html.ActionLink(
"
Edit
"
,
"
Edit
"
,
new
{
/*
id
=
item.PrimaryKey
*/
})
%>
|
<%
=
Html.ActionLink(
"
Details
"
,
"
Details
"
,
new
{
/*
id
=
item.PrimaryKey
*/
})
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Id)
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Name)
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Description)
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Price)
%>
</
td
>
</
tr
>
<%
}
%>
</
table
>
<
p
>
<%
=
Html.ActionLink(
"
Create New
"
,
"
Create
"
)
%>
</
p
>
</
asp:Content
>
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<ToyStore.Models.Product>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Index</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Index</h2>
<table>
<tr>
<th></th>
<th>
Id
</th>
<th>
Name
</th>
<th>
Description
</th>
<th>
Price
</th>
</tr>
<% foreach (var item in Model) { %>
<tr>
<td>
<%= Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
<%= Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ })%>
</td>
<td>
<%= Html.Encode(item.Id) %>
</td>
<td>
<%= Html.Encode(item.Name) %>
</td>
<td>
<%= Html.Encode(item.Description) %>
</td>
<td>
<%= Html.Encode(item.Price) %>
</td>
</tr>
<% } %>
</table>
<p>
<%= Html.ActionLink("Create New", "Create") %>
</p>
</asp:Content>
列表3 – Views\Home\Index.aspx [VB]
<%
@ Page Title
=
""
Language
=
"
VB
"
MasterPageFile
=
"
~/Views/Shared/Site.Master
"
Inherits
=
"
System.Web.Mvc.ViewPage(Of IEnumerable(Of ToyStore.Product))
"
%>
<
asp:Content
ID
="Content1"
ContentPlaceHolderID
="head"
runat
="server"
>
<
title
>
Index
</
title
>
</
asp:Content
>
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
Index
</
h2
>
<
p
>
<%
=
Html.ActionLink(
"
Create New
"
,
"
Create
"
)
%>
</
p
>
<
table
>
<
tr
>
<
th
></
th
>
<
th
>
Id
</
th
>
<
th
>
Name
</
th
>
<
th
>
Description
</
th
>
<
th
>
Price
</
th
>
</
tr
>
<%
For
Each
item In Model
%>
<
tr
>
<
td
>
<%
--<
%
=
Html.ActionLink(
"
Edit
"
,
"
Edit
"
,
New
With
{.id
=
item.PrimaryKey})
%>
|
<%
=
Html.ActionLink(
"
Details
"
,
"
Details
"
,
New
With
{.id
=
item.PrimaryKey})
%>
--%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Id)
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Name)
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Description)
%>
</
td
>
<
td
>
<%
=
Html.Encode(item.Price)
%>
</
td
>
</
tr
>
<%
Next
%>
</
table
>
</
asp:Content
>
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of IEnumerable(Of ToyStore.Product))" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Index</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Index</h2>
<p>
<%=Html.ActionLink("Create New", "Create")%>
</p>
<table>
<tr>
<th></th>
<th>
Id
</th>
<th>
Name
</th>
<th>
Description
</th>
<th>
Price
</th>
</tr>
<% For Each item In Model%>
<tr>
<td>
<%--<%=Html.ActionLink("Edit", "Edit", New With {.id = item.PrimaryKey})%> |
<%=Html.ActionLink("Details", "Details", New With {.id = item.PrimaryKey})%>--%>
</td>
<td>
<%=Html.Encode(item.Id)%>
</td>
<td>
<%=Html.Encode(item.Name)%>
</td>
<td>
<%=Html.Encode(item.Description)%>
</td>
<td>
<%=Html.Encode(item.Price)%>
</td>
</tr>
<% Next%>
</table>
</asp:Content>
图 13 – The Index view
请注意,在Index 视图的底部,有一个链接名为Create New ,我们接下来添加Create 视图。
Adding the Create View
Create 视图显示一个用于添加新产品的窗体,我们可以按照类似的步骤添加Create 视图:
1. 在代码编辑器窗口中右键单击第一个Create (),选择Add View 。
2. 在Add View 对话框中, 选择Create a strongly-typed view 。
3. 在Add View 对话框中, 在View data class 的下拉列表中 , 选择ToyStore.Models.Product 类。
4. 在Add View 对话框中, 在View Content 的下拉列表中, 选择Create 。
5. 单击Add 按钮,将视图添加到工程中(参见图14 )。
图 14 – 添加Create 视图
Create 视图被添加到项目的以下位置:
\Views\Home\Create.aspx
Create 视图的内容如列表4 所示:
列表 4 – Views\Home\Create.aspx [C#]
<%
@ Page Title
=
""
Language
=
"
C#
"
MasterPageFile
=
"
~/Views/Shared/Site.Master
"
Inherits
=
"
System.Web.Mvc.ViewPage<ToyStore.Models.Product>
"
%>
<
asp:Content
ID
="Content1"
ContentPlaceHolderID
="head"
runat
="server"
>
<
title
>
Create
</
title
>
</
asp:Content
>
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
Create
</
h2
>
<%
=
Html.ValidationSummary()
%>
<%
using (Html.BeginForm()) {
%>
<
fieldset
>
<
legend
>
Fields
</
legend
>
<
p
>
<
label
for
="Id"
>
Id:
</
label
>
<%
=
Html.TextBox(
"
Id
"
)
%>
<%
=
Html.ValidationMessage(
"
Id
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="Name"
>
Name:
</
label
>
<%
=
Html.TextBox(
"
Name
"
)
%>
<%
=
Html.ValidationMessage(
"
Name
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="Description"
>
Description:
</
label
>
<%
=
Html.TextBox(
"
Description
"
)
%>
<%
=
Html.ValidationMessage(
"
Description
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="Price"
>
Price:
</
label
>
<%
=
Html.TextBox(
"
Price
"
)
%>
<%
=
Html.ValidationMessage(
"
Price
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
input
type
="submit"
value
="Create"
/>
</
p
>
</
fieldset
>
<%
}
%>
<
div
>
<%
=
Html.ActionLink(
"
Back to List
"
,
"
Index
"
)
%>
</
div
>
</
asp:Content
>
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<ToyStore.Models.Product>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Create</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</h2>
<%= Html.ValidationSummary() %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Id">Id:</label>
<%= Html.TextBox("Id") %>
<%= Html.ValidationMessage("Id", "*") %>
</p>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextBox("Description") %>
<%= Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="Price">Price:</label>
<%= Html.TextBox("Price") %>
<%= Html.ValidationMessage("Price", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
列表 4 – Views\Home\Create.aspx [VB]
<% @ Page Title = "" Language = " VB " MasterPageFile = " ~/Views/Shared/Site.Master " Inherits = " System.Web.Mvc.ViewPage(Of ToyStore.Product) " %> < asp:Content ID ="Content1" ContentPlaceHolderID ="head" runat ="server" > < title > Create </ title > </ asp:Content > < asp:Content ID ="Content2" ContentPlaceHolderID ="MainContent" runat ="server" > < h2 > Create </ h2 > <% = Html.ValidationSummary() %> <% Using Html.BeginForm() %> < fieldset > < legend > Fields </ legend > < p > < label for ="Id" > Id: </ label > <% = Html.TextBox( " Id " ) %> <% = Html.ValidationMessage( " Id " , " * " ) %> </ p > < p > < label for ="Name" > Name: </ label > <% = Html.TextBox( " Name " ) %> <% = Html.ValidationMessage( " Name " , " * " ) %> </ p > < p > < label for ="Description" > Description: </ label > <% = Html.TextBox( " Description " ) %> <% = Html.ValidationMessage( " Description " , " * " ) %> </ p > < p > < label for ="Price" > Price: </ label > <% = Html.TextBox( " Price " ) %> <% = Html.ValidationMessage( " Price " , " * " ) %> </ p > < p > < input type ="submit" value ="Create" /> </ p > </ fieldset > <% End Using %> < div > <% = Html.ActionLink( " Back to List " , " Index " ) %> </ div > </ asp:Content >
<%
@ Page Title
=
""
Language
=
"
VB
"
MasterPageFile
=
"
~/Views/Shared/Site.Master
"
Inherits
=
"
System.Web.Mvc.ViewPage(Of ToyStore.Product)
"
%>
<
asp:Content
ID
="Content1"
ContentPlaceHolderID
="head"
runat
="server"
>
<
title
>
Create
</
title
>
</
asp:Content
>
<
asp:Content
ID
="Content2"
ContentPlaceHolderID
="MainContent"
runat
="server"
>
<
h2
>
Create
</
h2
>
<%
=
Html.ValidationSummary()
%>
<%
Using Html.BeginForm()
%>
<
fieldset
>
<
legend
>
Fields
</
legend
>
<
p
>
<
label
for
="Id"
>
Id:
</
label
>
<%
=
Html.TextBox(
"
Id
"
)
%>
<%
=
Html.ValidationMessage(
"
Id
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="Name"
>
Name:
</
label
>
<%
=
Html.TextBox(
"
Name
"
)
%>
<%
=
Html.ValidationMessage(
"
Name
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="Description"
>
Description:
</
label
>
<%
=
Html.TextBox(
"
Description
"
)
%>
<%
=
Html.ValidationMessage(
"
Description
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="Price"
>
Price:
</
label
>
<%
=
Html.TextBox(
"
Price
"
)
%>
<%
=
Html.ValidationMessage(
"
Price
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
input
type
="submit"
value
="Create"
/>
</
p
>
</
fieldset
>
<%
End
Using
%>
<
div
>
<%
=
Html.ActionLink(
"
Back to List
"
,
"
Index
"
)
%>
</
div
>
</
asp:Content
>
<%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage(Of ToyStore.Product)" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>Create</title>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</h2>
<%= Html.ValidationSummary() %>
<% Using Html.BeginForm()%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Id">Id:</label>
<%= Html.TextBox("Id") %>
<%= Html.ValidationMessage("Id", "*") %>
</p>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextBox("Description") %>
<%= Html.ValidationMessage("Description", "*") %>
</p>
<p>
<label for="Price">Price:</label>
<%= Html.TextBox("Price") %>
<%= Html.ValidationMessage("Price", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% End Using %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
Create 视图显示一个用于创建新产品的HTML 窗体(参见图15 )。Add 视图对话框会生成一个针对Product 类的每个属性的HTML 窗体。如果你输入完HTML 窗体,然后提交,一条新的产品会被插入到数据库中。
图 15 – Create 视图
Summary
在本章中,我们使用ASP.NET MVC 框架构建了一个简单的数据库驱动的web 应用程序,我们创建了模型、视图和控制器。
首先,我们创建数据库和数据库模型我们使用Microsoft SQL Server Express 作为数据库,利用Microsoft Entity 框架生成模型类。
接下来,我们创建了Home 控制器。我们使用Visual Studio 自动生成了Home 控制器中的action ,天价了一些数据访问逻辑代码来和数据库进行交互。
最后,我们创建了两个视图。我们创建了Index 视图来在HTML 表格中现实所有的产品列表;创建了Create 视图来显示一个用于添加新产品的HTML 窗体。