admin 管理员组

文章数量: 887021


2024年1月12日发(作者:易语言模块是什么意思)

MVC3 快速入门

第一节 概述

1.1本教程的学习内容

在本教程中,你将学会如下内容:

如何创建一个 MVC的工程。

如何创建 MVC的控制器(controller)与视图(view)。

如何使用Entity Framework code-first 范例来创建一个新的数据库。

如何获取和显示数据。

如何编辑数据并且进行数据的有效性验证。

1.2创建工程

如果要创建一个 MVC3的工程时,首先运行Visual Web Developer 2010 Express,并且在起始页(start page)中选择“新建项目”。

Visual Web Developer是一个集成开发环境,你可以使用它来进行各种应用程序的开发。在Visual Web Developer的菜单的下面有一个工具条,可以直接点击工具条中的各个工具按钮来进行各种操作,也可以直接点击菜单中的各个菜单项来进行各种操作,此处我们点击“文件”菜单中的“新建项目”菜单项。

图1-1 Visual Web Developer 2010 Express中的起始页

1.3 创建你的第一个应用程序

你可以使用Visual Basic 或Visual C#作为开发语言来创建应用程序。在本教程中,选择C#来作为开发语言。点击“新建项目”菜单项后,在打开的“新建项目”对话框中,双击左边的“Visual C#”使其成为展开状态,然后点击“Web”,点击右边的“ MVC

3 Web 应用程序”,然后在下方的名称文本框中填入应用程序的名称,在本教程中命名为“MvcMovie”,然后点击确定按钮。

图1-2 在新建项目对话框中选择 MVC3应用程序并为应用程序命名

在接下来打开的“新 MVC 3 项目”对话框中,点击选中“Internet 应用程序”,在“视图引擎”下拉框中保持默认的“Razor”选项不作修改(Razor视图是

MVC3种新增的一种十分重要的视图类型,使用它可以使得Web应用程序的开发变得更加方便快捷,在后文中将对此进行详细介绍)。

图1-3 选择项目模板与视图引擎

点击确定按钮,Visual Web Developer会为你所创建的 MVC项目提供一个默认模板,这样的话你就拥有了一个可以立刻运行的应用程序。默认的模板中提供的是一个很简单的显示“欢迎使用 MVC!”文字的应用程序,你可以以此作为你的开发起点。

图1-4 Visual Web Developer提供了一个默认的应用程序模板

点击“调试”菜单中的“启动调试”菜单项(该菜单项的快捷键为F5),Visual Web

Developer将启动一个内置的服务器,并且在该服务器中打开当前Web应用程序的主页,如图1-5所示。

图1-5 MVC3的默认应用程序模板的调试画面

请注意该页面在浏览器中的地址为“localhost:4423/”。其中“localhost”代表了本机上你刚刚创建的Web应用程序的临时网站地址,4423代表了Visual Web

Developer使用的一个随机端口,每次调试的时候,Visual Web Developer都会使用这个端口来作为内置服务器的端口号。在各计算机上,该端口号都是不相同的,因为该端口号是Visual Web Developer随机选择的。

在这个模板应用程序的页面的右上角,提供了两个按钮与一个“登录”链接,点击“登录”链接,页面跳转到登录页面,点击“主页”按钮,页面返回到主页,点击“关于”按钮,页面跳转到“关于”页面。

接下来,让我们开始逐步将这个默认的应用程序修改为我们所要的应用程序,在这个过程中逐步了解 MVC 3的有关知识。首先,让我们关闭浏览器并开始代码的修改工作。

第二节 添加一个控制器

MVC的全称为model-view-controller(模型-视图-控制器)。MVC是一种开发应用程序的模式,这个模式已经具有了很好的框架架构,并且十分容易维护。使用MVC开发出来的应用程序一般包括以下几块内容:

 控制器(Controller):控制器类处理客户端向Web应用程序发出的请求,获取数据,并指定返回给客户端,用来显示处理结果的视图。

 模型(Model):模型类代表了应用程序的数据,这些数据通常具有一个数据验证逻辑,用来使得这些数据必须符合业务逻辑。

 视图(View):视图类是Web应用程序中用来生成并显示HTML格式的服务器端对客户端请求的响应结果的模板文件。

在本教程中,将全面介绍这些概念,并且向你展示如何利用它们来搭建一个应用程序。

首先,让我们来创建一个控制器(controller)类。在解决方案资源管理器中,鼠标右击Controllers文件夹,并且点击添加->控制器,如图2-1所示。

图2-1 添加控制器

在弹出的“添加控制器”对话框中,将控制器命名为“HelloWorldController”,然后点击添加按钮,如图2-2所示。

图2-2 命名控制器

观察解决方案资源管理器中新增加了一个文件,名字为,并且该文件呈打开状态,如图2-3所示。

图2-3 控制器代码

修改打开的文件,在HelloWorldController类中,创建如代码清单2-1中所示的两个方法,控制器将返回一个HTML格式的字符串。

代码2-1 控制器中创建方法

public class HelloWorldController : Controller

{

//

// GET: /HelloWorld/

public string Index()

{

return "这是我的默认

}

//

// GET: /HelloWorld/Welcome/

public string WelCome()

{

return "这是我的Welcome方法...";

}

}

在这个修改后的HelloWorldController控制器中,第一个方法名为Index。现在让我们从浏览器中调用该方法。运行应用程序(按F5键或Ctrl+F5键),在打开的浏览器中的地址栏后面,添加“HelloWorld”路径(譬如,在我的计算机上,浏览器中地址为localhost:4423/HelloWorld),画面显示如图2-4所示。由于在Index方法中,直接返回了一个HTML格式的字符串,所以在浏览器中将该字符串显示出来。

图2-4 HelloWorldController控制器中Index方法的运行结果

在 MVC中,可以根据浏览器中的输入地址来调用不同的控制器或控制七种不同的方法。 MVC的默认的映射逻辑使用如下所示的格式来决定应该调用什么控制器或控制器中的什么方法。

/[Controller]/[ActionName]/[Parameters]

URL地址的第一部分决定调用哪个控制器类,所以“/HelloWorld”映射到HelloWorldController控制器类。第二部分决定调用控制器中的哪个方法。所以“/HelloWorld/Index”将会调用HelloWorldController控制器类的Index方法。由于Index方法是控制器类的默认方法(可以另外指定控制器类的默认方法),所以也可只输入“/HelloWorld”来调用该方法。

在浏览器的地址栏中,输入“localhost:xxxx/HelloWorld/Welcome”,将会调用HelloWorldController控制器类的Welcome方法,该方法返回“这是我的Welcome方法...”文字,所以浏览器中显示该文字,如图2-5所示。

图2-5 HelloWorldController控制器中Welcome方法的运行结果

接下来,让我们修改Welcome方法,以便在URL地址栏中可以传递一些参数给该方法(例如:/HelloWorld/Welcome?name=Scott&numtimes=4)。修改后的代码如下所示。注意这里我们使用了C#的可选参数,当URL地址中没有使用numtimes参数时,该参数被默认设定为1。

public string Welcome(string name, int numTimes=1)

{

return code("Hello " + name + ",NumTimes is:" + numTimes);

}

运行该应用程序,在浏览器中输入“localhost:xxxx/HelloWorld/Welcome?

name=Scott&numtimes=4”,运行结果显示如图2-6所示。浏览器自动将URL地址栏中的参数映射成Welcome方法中的传入参数。

图2-6 在Welcome方法中使用参数

到现在为止,我们展示了MVC中的“VC”(视图与控制器)部分的工作机制,控制器返回HTML字符串。很显然大多数情况下你不想让控制器直接返回HTML字符串,因为那样的话编码起来就太麻烦了。所以我们需要使用不同的视图模板文件来帮助生成HTML格式的页面文件,在下一节中让我们来看一下如何在 MVC3中使用视图。

第三节 添加一个视图

3.1 添加一个视图

在本节中我们修改HelloWorldController类,以便使用视图来向客户端展示HTML格式的响应结果。

我们使用 MVC3中新增的Razor视图引擎来创建视图。Razor视图模板文件的后缀名为.cshtml,它提供了一种简洁的方式来创建HTML输出流。Razor视图大大减少了在书写视图模板文件时所需要输入的字符,提供了一个最快捷,最简便的编码方式。

这里,我们在HelloWorldController类的Index方法中添加使用一个视图。在修改前的Index方法中返回一个字符串,我们修改这个方法来使它返回一个视图,代码如下所示。

public ActionResult Index()

{

return View();

}

这段代码表示Index方法使用一个视图模板来在浏览器中生成HTML格式的页面文件。接着,让我们来添加一个Index方法所使用的视图模板。在Index方法中点击鼠标右键,然后点击“添加视图”,将会弹出一个“添加视图”对话框。

图3-1 添加视图

图3-2 添加视图对话框

在该对话框中,不做任何修改,直接点击添加按钮,观察解决方案资源管理器中,在MvcMovie项目下的Views文件夹下创建了一个HelloWorld文件夹,并且在该文件夹中创建了一个文件,同时该文件呈打开状态,如图3-3所示。

图3-3 视图模板文件被创建并呈打开状态

让我们在该文件中追加一些文字,代码如代码清单3-1所示。

代码3-1 视图模板文件

@{

= "首页";

}

首页

这是我的第一个视图模板

运行应用程序,输入地址“localhost:xxxx/HelloWorld”。由于在Index方法中并没有做任何事情,只是简单地一行代码“return View()”,该行代码表示我们使用一个视图模板文件来在浏览器中展示响应结果。因为我们并没有显式指定使用哪个视图模板文件,所以使用了默认的Views文件夹下的HelloWorld文件夹下的视图模板文件。该视图模板文件中只有简单的两行文字,在浏览器中的显示结果如图3-4所示。

图3-4

在浏览器中显示视图

看上去还不错,但是请注意,该网页的标题为“首页”,但是网页中的大标题文字却为“我的MVC应用程序”,需要修改一下。

3.2 修改视图--修改应用程序的页面布局

首先,让我们修改页面大标题中的“我的MVC应用程序”文字。这段文字是所有页面中的公共大标题,在这个应用程序中,虽然所有页面中都显示了这个共同的大标题,但只有一处地方对其进行了设置。打开解决方案资源管理器中Views文件夹下的Shared文件夹下的_文件。该文件被称为布局页面,位于公有文件夹Shared下,被所有其他网页所共用。

图3-5

公有布局页面

布局模板页允许你统一在一个地方指定整个Web应用程序或Web网站的所有HTML页面的布局方法。请注意文件底部的“@RenderBody()”代码行。@RenderBody()是一个占位符,代表了所有你创建出来的实际应用的视图页面,在这里统一指定。将布局模板文件中的“我的 MVC 应用程序”修改为“我的 MVCMovie 应用程序”。代码如下所示。

我的

MVCMovie

应用程序

运行应用程序,注意网页中的大标题被修改为“我的 MVCMovie 应用程序”。点击“关于”链接,你可以看见“关于”页面中的大标题也被修改为“我的 MVCMovie 应用程序”。由此可以看出一旦修改了布局页面中的某处地方,该修改将会被应用到所有页面中。

图3-6 在布局页面中修改了网页中显示的大标题

完整的_文件中的代码如代码清单3-2所示。

代码清单3-2 _文件中的完整代码

@

type="text/css" />

@RenderBody()

现在,让我们修改Index视图页面的标题。

打开Views文件夹下的HelloWorld文件夹下的文件。这里我们修改两处地方:首先,修改浏览器中的标题,然后修改

标签中的小标题文字。修改后代码如代码清单3-3所示。

代码清单3-3 修改后的视图模板文件

@{

= "电影清单";

}

我的电影清单

这是我的第一个视图模板

ViewBag对象的Title属性代表了显示该页面时的浏览器中的标题文字。让我们回头看一下布局模板文件,在该文件的区段中的标签中使用了这个值来作为浏览器中的网页标题。同时,通过这种方法,你可以很容易地在你的视图模板文件与布局模板文件之间进行参数的传递。 </p><p style="text-indent: 2em;";>运行应用程序,在地址栏中输入“localhost:xxxx/HelloWorld”,注意浏览器中的网页标题,页面中的小标题文字都变为修改后的标题文字(如果没有发生变化的话,则可能你的网页被缓存住了,可以按Ctrl+F5键来在重新刷新页面时取消缓存)。 </p><p style="text-indent: 2em;";>同时也请注意_文件中的占位符中的内容被替换成了视图模板中的内容,所以浏览器中展示的是一个单一的HTML文件。浏览器中的运行结果如图3-7所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图3-7 修改了标题后的Index视图模板文件 </p><p style="text-indent: 2em;";>此处,我们的数据(“这是我的第一个视图模板”文字)是被直接书写在文件中的,也就是说我们使用到了MVC应用程序的“V”(视图View)与“C”(控制器Controller)。接下来,我们讲解一下如何创建一个数据库并从该数据库中获取模型数据。 </p><p style="text-indent: 2em;";>3.3 将控制器中的数据传递给视图 </p><p style="text-indent: 2em;";>在我们使用数据库并介绍模型之前,首先我们介绍一下如何将控制器中的信息传递给视图。浏览器接收到一个URL请求后,将会调用控制器类来进行响应。你可以在控制器类中进行对接收到的页面参数进行处理的代码,你可以在控制器类中书写从数据库中获取数据的代码,你也可以在控制器类中书写代码来决定返回给客户端什么格式的响应文件。控制器可以利用视图模板文件来生成HTML格式的响应文件并显示在浏览器中。 </p><p style="text-indent: 2em;";> 控制器类负责提供视图模板文件在生成HTML格式的响应文件时所需要的任何数据或对象。一个视图模板文件不应该执行任何业务逻辑,也不应该直接和数据库进行交互。它只能和控制器类进行交互,获取控制器类所提供给它的数据,这样可以使你的代码更加清晰,容易维护。 </p><p style="text-indent: 2em;";>现在在我们的应用程序中,HelloWorldController控制器类中的Welcome方法带有两个参数—name与numTimes,Welcome方法直接向浏览器输出这两个参数的参数值。这里,我们修改该方法使其不再直接输出数据,而是使用一个视图模板。该视图模板将生成一个动态的响应流,这意味着我们需要将数据从控制器类传递给视图以便利用该数据来生成该响应流。我们在该控制器类中将视图模板所需要的数据送入一个ViewBag对象中,该对象可以被视图模板直接接收。 </p><p style="text-indent: 2em;";>打开文件,修改Welcome方法,在该方法中为ViewBag对象添加一个Message属性与NumTimes属性,并且将属性值分别设定为经过处理后的name参数值与numTimes参数值。ViewBag对象是一个动态对象,你可以为它添加任何属性并赋上属性值。在未赋值之前该属性是不生效的,直到你赋值为止。修改后的文件中的代码如代码清单3-4所示。 </p><p style="text-indent: 2em;";>代码清单3-4 修改后的文件 </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>namespace llers </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> public class HelloWorldController : Controller </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> // </p><p style="text-indent: 2em;";> // GET: /HelloWorld/ </p><p style="text-indent: 2em;";> public ActionResult Index() </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> return View(); </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";> // </p><p style="text-indent: 2em;";> // GET: /HelloWorld/Welcome/ </p><p style="text-indent: 2em;";> public ActionResult Welcome(string name, int numTimes = 1) </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> e = "Hello " + name; </p><p style="text-indent: 2em;";> es = numTimes; </p><p style="text-indent: 2em;";> return View(); </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>现在ViewBag对象中已经包含了数据,它将被自动传递给视图。 </p><p style="text-indent: 2em;";>接下来,我们需要创建一个Welcome视图模板。在“调试”菜单中,点击“生成 MvcMovie”将应用程序进行编译,如图3-8所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图3-8 </p><p style="text-indent: 2em;";>编译应用程序 </p><p style="text-indent: 2em;";>接下来,在Welcome方法中点击鼠标右键,然后点击“添加视图”,弹出对话框如图3-9所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图3-9 为Welcome方法添加视图 </p><p style="text-indent: 2em;";>在该对话框中不做任何修改,直接点击添加按钮, View文件夹下的HelloWorld文件夹中自动被创建了一个文件,打开该文件,在<h2>元素下添加代码,让浏览器显示URL地址中传入的name参数中设定的文字,显示次数等于URL地址中传入的numTimes参数中设定的次数。修改后的文件中的代码如代码清单3-5所示。 </p><p style="text-indent: 2em;";>代码清单3-5 修改后的文件 </p><p style="text-indent: 2em;";>@{ </p><p style="text-indent: 2em;";> = "Welcome"; </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";><h2>Welcome</h2> </p><p style="text-indent: 2em;";><ul> </p><p style="text-indent: 2em;";>@for (int i = 0; i < es; i++) </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> <li>@e</li> </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";></ul> </p><p style="text-indent: 2em;";>运行应用程序,并且在地址栏中输入“localhost:xx/HelloWorld/Welcome?name= </p><p style="text-indent: 2em;";>Scott&numtimes=4”,该地址栏中的页面参数将会自动传递给控制器。控制器将会把这些参数值放入ViewBag对象中并且传递给视图。视图再在浏览器中显示这些数据。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图3-10 视图中显示从控制器类中传递过来的数据 </p><p style="text-indent: 2em;";>这里,我们使用了模型“M”的一种方式,但是不是数据库的方式。在下一节中,我们将创建一个数据库,并且介绍如何对该数据库中的数据进行处理。 </p><p style="text-indent: 2em;";>第四节 添加一个模型 </p><p style="text-indent: 2em;";>在本节中我们将追加一些类来管理数据库中的电影。这些类将成为我们的MVC应用程序中的“模型”部分。 </p><p style="text-indent: 2em;";> 我们将使用一个.NET Framework的被称之为“Entity Framework”的数据访问技术来定义这些模型类,并使用这些类来进行操作。Entity Framework(通常被简称为“EF”)支持一个被称之为“code-first”的开发范例。Code-first允许你通过书写一些简单的类来创建模型对象。你可以通过访问这些类的方式来访问数据库,这是一种非常方便快捷的开发模式。 </p><p style="text-indent: 2em;";>4.1 利用NuGet来安装EFCodeFirst </p><p style="text-indent: 2em;";>我们可以利用NuGet包管理器(安装 MVC3时会自动安装)来把EFCodeFirst类库添加到我们的MvcMovie工程中。这个类库使得我们可以直接使用code-first。点击“工具”菜单下的“Library Package Manager”子菜单下的“Add Library Package Reference”菜单选项,如图4-1所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-1 使用NuGet包管理器 </p><p style="text-indent: 2em;";>点击“Add Library Package Reference”菜单选项后,将会弹出一个对话框,标题为“Add </p><p style="text-indent: 2em;";>Library Package Reference”,如图4-2所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-2 </p><p style="text-indent: 2em;";>“Add Library Package Reference”对话框 </p><p style="text-indent: 2em;";>默认状态下,左边的“All”选项处于选择状态。因为还没有安装任何包,所以右边面板中显示“找不到任何项”。点击左边面板中的“online”选项,NuGet包管理器将会在服务器上检索所有当前能够获取的包,如图4-3所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-3 NuGet包管理器正在检索包信息 </p><p style="text-indent: 2em;";>服务器上有几百个当前能够获取的包,现在我们只关注EFCodeFirst包。在右上角的搜索输入框中输入“EFCode”。在检索结果中,选择EFCodeFirst包,并且点击Install按钮安装包,如图4-4所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-4 选择EFCodeFirst包并安装 </p><p style="text-indent: 2em;";>点击了install按钮后,会弹出一个接受许可证窗口,如图4-5所示,在这个窗口中必须要点击“I Accept”按钮,接受许可证条款,安装才能继续进行。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-5 接受许可证窗口 </p><p style="text-indent: 2em;";>安装完毕后,点击close按钮。我们的MvcMovie工程中会自动加载EntityFramework程序集,其中包含了EFCodeFirst类库。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-6 </p><p style="text-indent: 2em;";>安装完毕后EntityFramework程序集被自动加载 </p><p style="text-indent: 2em;";>4.2 添加模型类 </p><p style="text-indent: 2em;";>在解决方案资源管理器中,鼠标右击Models文件夹,点击“添加”菜单下的“类”,如图4-7所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-7 添加模型类 </p><p style="text-indent: 2em;";>点击“类”菜单项后,会弹出“添加新项”对话框,在该对话框中将类名命名为“Movie”,如图4-8所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-8 在“添加新项”对话框中为类命名 </p><p style="text-indent: 2em;";>然后点击添加按钮,观察解决方案资源管理器中,Models文件夹下添加了一个类定义文件,并且该文件呈打开状态,如图4-9所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图4-9 类定义文件已被添加并呈打开状态 </p><p style="text-indent: 2em;";>在文件中追加如下所示的五个属性。 </p><p style="text-indent: 2em;";>public class Movie </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> public int ID { get; set; } </p><p style="text-indent: 2em;";> public string Title { get; set; } </p><p style="text-indent: 2em;";> public DateTime ReleaseDate { get; set; } </p><p style="text-indent: 2em;";> public string Genre { get; set; } </p><p style="text-indent: 2em;";> public decimal Price { get; set; } </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>我们将利用Movie类来代表数据库中的movie(电影)。每一个Movie对象的实例对应于数据表中的一行,Movie类中的每一个属性被映射到数据表的每一列。 </p><p style="text-indent: 2em;";>在同一个文件中,追加如下所示的MovieDBContext类。 </p><p style="text-indent: 2em;";>public class MovieDBContext : DbContext </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> public DbSet<Movie> Movies { get; set; } </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>MovieDBContext类代表了Entity Framework中的movie数据库的上下文对象,用来处理数据的存取与更新。MovieDBContext对象继承了Entity Framework中的DbContext基础类。为了能够引用DbContext类,你需要在文件的头部追加如下所示的using语句。 </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>完整的文件中的代码如代码清单4-1所示。 </p><p style="text-indent: 2em;";>代码清单4-1 完整的文件 </p><p style="text-indent: 2em;";>using System; </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>namespace </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> public class Movie </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> public int ID { get; set; } </p><p style="text-indent: 2em;";> public string Title { get; set; } </p><p style="text-indent: 2em;";> public DateTime ReleaseDate { get; set; } </p><p style="text-indent: 2em;";> public string Genre { get; set; } </p><p style="text-indent: 2em;";> public decimal Price { get; set; } </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";> public class MovieDBContext : DbContext </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> public DbSet<Movie> Movies { get; set; } </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>如果要从数据库中存取数据,类似以上所示的代码是必须要写的。在下一节中,我们将要创建一个新的MoviesController类,用来显示数据库中的数据,并且允许用户创建一个新的movie(电影)的列表。 </p><p style="text-indent: 2em;";>第五节 从控制器访问模型中的数据 </p><p style="text-indent: 2em;";>5.1 从控制器访问模型中的数据 </p><p style="text-indent: 2em;";>在本节中,我们将要创建一个新的MoviesController类,并且书写代码来获取数据库中的数据,并通过视图模板来显示在浏览器中。 </p><p style="text-indent: 2em;";>鼠标右击Controllers文件夹,点击“添加”菜单下的“控制器”菜单项,将会弹出一个“添加控制器”对话框,如图5-1所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-1 添加控制器 </p><p style="text-indent: 2em;";>在该对话框中将控制其命名为MoviesController,然后点击添加按钮,该对话框被关闭。观察解决方案资源管理器中,Controllers文件夹下增加了一个名为的文件,并且呈打开状态。让我们更新MoviesController类中的Index方法,以便获取movie(电影)清单。 </p><p style="text-indent: 2em;";>这里需要注意的是,为了引用我们前面创建的MovieDBContext类,你需要在文件头部追加如下所示的两个using语句。 </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>修改MoviesController类中的代码为代码清单5-1中所示代码。 </p><p style="text-indent: 2em;";>代码清单5-1 MoviesController类中的完整代码 </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>using System; </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>namespace llers </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> public class MoviesController : Controller </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> MovieDBContext db = new MovieDBContext(); </p><p style="text-indent: 2em;";> public ActionResult Index() </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> var movies=from m in </p><p style="text-indent: 2em;";> where eDate>new DateTime(1984,6,1) </p><p style="text-indent: 2em;";> select m; </p><p style="text-indent: 2em;";> return View(()); </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>这段代码实施了一个LINQ查询来获取1984年夏天之后发行的所有电影。我们还需要一个视图模板来显示这个电影清单,所以在Index方法内点击鼠标右键,然后点击“添加视图”来添加一个视图。 </p><p style="text-indent: 2em;";>由于这里我们需要将一个Movie类传递给视图,所以在“添加视图”对话框中,与本教程中前几次在该对话框中之行的操作有所不同,前几次我们都是直接点击添加按钮来创建一个空白的视图模板,但是这一次我们想让Visual Web Developer为我们自动创建一个具有一些默认处理的强类型的视图,所以我们勾选“创建强类型视图”复选框,在模型类下拉框中选择“Movie()”(如果模型类中不存在这个类,请先点击调试菜单下的“生成MvcMovie”生成该类),在支架模板下拉框中选择“List”,最后勾选“引用脚本”复选框,如图5-2所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-2 添加强类型视图 </p><p style="text-indent: 2em;";>点击添加按钮,Visual Web Developer自动生成一个视图,并且自动在视图文件中添加显示电影清单所需要的代码。这里,我们首先用与前面修改HelloWorld控制器所用的视图中的标题同样的方法来修改这个Movies控制器所用视图中的标题。 </p><p style="text-indent: 2em;";>代码清单5-2为修改后的这个视图中的完整代码。在这段代码中,我们将releaseDate(发行日期)属性的格式化字符串从原来的“{0:g}”修改为“{0:d}”(长日期修改为短日期),将Price(票价)属性的格式化字符串从原来的“{0:F}”修改为“{0:c}”(float类型修改为货币类型)。 </p><p style="text-indent: 2em;";>另外,将列表标题中的文字全部修改为中文名称。 </p><p style="text-indent: 2em;";>代码清单5-2 Movies控制器所用视图中的完整代码 </p><p style="text-indent: 2em;";>@model IEnumerable<> </p><p style="text-indent: 2em;";>@{ </p><p style="text-indent: 2em;";> = "电影清单"; </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";><h2>我的电影清单</h2> </p><p style="text-indent: 2em;";><p> </p><p style="text-indent: 2em;";> @Link("追加", "Create") </p><p style="text-indent: 2em;";></p> </p><p style="text-indent: 2em;";><table> </p><p style="text-indent: 2em;";> <tr> </p><p style="text-indent: 2em;";> <th></th> </p><p style="text-indent: 2em;";> <th> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>电影名称 </p><p style="text-indent: 2em;";> </th> </p><p style="text-indent: 2em;";> <th> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>发行日期 </p><p style="text-indent: 2em;";> </th> </p><p style="text-indent: 2em;";> <th> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>种类 </p><p style="text-indent: 2em;";> </th> </p><p style="text-indent: 2em;";> <th> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>票价 </p><p style="text-indent: 2em;";> </th> </p><p style="text-indent: 2em;";> </tr> </p><p style="text-indent: 2em;";>@foreach (var item in Model) { </p><p style="text-indent: 2em;";> <tr> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @Link("编辑", "Edit", new { id= }) | </p><p style="text-indent: 2em;";> @Link("查看明细", "Details", new { id= }) | </p><p style="text-indent: 2em;";> @Link("删除", "Delete", new { id= }) </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @ </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @("{0:d}", eDate) </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @ </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @("{0:c2}", ) </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> </tr> </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";></table> </p><p style="text-indent: 2em;";>5.2 强类型模型与@model关键字 </p><p style="text-indent: 2em;";>在本教程的前文中,我们介绍了一个控制器可以使用ViewBag对象来将数据或对象传递到视图模板中。ViewBag是一个动态对象,它提供了一种便利的,后期绑定的方法来将信息从控制器传递到视图中。 </p><p style="text-indent: 2em;";> MVC也提供了一种利用强类型的方法来将数据或对象传递到视图模板中。这种强类型的方法为你的编码过程提供了很丰富的编辑时的智能输入提示信息与非常好的编译时的检查。接下来我们将结合这种方法与我们的Movies控制器(MoviesController)与视图模板()一起使用。 </p><p style="text-indent: 2em;";>请注意在我们的MoviesController控制器的Index方法中,我们在调用View()方法时传入了一个参数,代码如下所示。 </p><p style="text-indent: 2em;";>public class MoviesController : Controller </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> MovieDBContext db = new MovieDBContext(); </p><p style="text-indent: 2em;";> public ActionResult Index() </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> var movies = from m in </p><p style="text-indent: 2em;";> where eDate > new DateTime(1984, 6, 1) </p><p style="text-indent: 2em;";> select m; </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> return View(()); </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>请注意如下这一行代码表示将一个movies列表从控制器传递到了视图中。 </p><p style="text-indent: 2em;";>return View(()); </p><p style="text-indent: 2em;";>通过在视图模板文件的头部使用@model语句,视图模板可以识别传入的参数中的对象类型是否该视图模板所需要的对象类型。请记住当我们在创建这个Movies控制器所使用的模板时,我们在“添加视图”对话框中勾选了“创建强类型视图”复选框,在模型类下拉框中选择了“Movie()”, 在支架模板下拉框中选择了“List”。所以Visual Web </p><p style="text-indent: 2em;";>Developer自动在我们的视图模板文件的第一行中添加了如下所示的语句。 </p><p style="text-indent: 2em;";>@model IEnumerable<> </p><p style="text-indent: 2em;";>@model关键字允许我们在视图模板中直接访问在控制器类中通过使用强类型的“模型”而传递过来的Movie类的列表。例如,在我们的视图模板中,我们可以通过foreach语句来遍历这个强类型的模型,访问其中的每一个Movie对象。代码如下所示。 </p><p style="text-indent: 2em;";>@foreach (var item in Model) { </p><p style="text-indent: 2em;";> <tr> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @Link("编辑", "Edit", new { id= }) | </p><p style="text-indent: 2em;";> @Link("查看明细", "Details", new { id= }) | </p><p style="text-indent: 2em;";> @Link("删除", "Delete", new { id= }) </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @ </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @("{0:d}", eDate) </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @ </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> <td> </p><p style="text-indent: 2em;";> @("{0:c2}", ) </p><p style="text-indent: 2em;";> </td> </p><p style="text-indent: 2em;";> </tr> </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>因为这里的“模型”是强类型的(IEnumerable<Movie>),所以在循环遍历时“模型”中的每一个项目(“item”)也是一个强类型的Movie对象,可以直接访问该对象的每一个属性。同时这也意味着我们可以在编译时检查我们的代码,同时在书写代码时也可以使用代码编辑器提供的智能输入提示信息,如图5-3所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-3 可以使用强类型“模型”所带来的智能输入提示信息 </p><p style="text-indent: 2em;";>5.3 与SQL Server Express结合使用 </p><p style="text-indent: 2em;";>我们在本节前面创建了一个MovieDBContext类,用来连接数据库,并将数据库中的记录映射到Movie对象。你也许会问一个问题,怎样定义数据库连接?接下来我们通过在文件中增加一些连接信息来定义一个数据库的连接。 </p><p style="text-indent: 2em;";>打开应用程序根目录下的文件(请注意不是Views文件夹下的文件),如图5-4所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-4 打开应用程序根目录下的文件 </p><p style="text-indent: 2em;";>在文件的<connectionStrings>元素中追加类似如下所示的连接字符串。 </p><p style="text-indent: 2em;";><configuration> </p><p style="text-indent: 2em;";> <connectionStrings> </p><p style="text-indent: 2em;";> <add name="ApplicationServices" </p><p style="text-indent: 2em;";> connectionString="data source=.SQLEXPRESS;Integrated </p><p style="text-indent: 2em;";> Security=SSPI;AttachDBFilename=|DataDirectory|; </p><p style="text-indent: 2em;";>User Instance=true" </p><p style="text-indent: 2em;";> providerName="ent" /> </p><p style="text-indent: 2em;";> <add name="MovieDBContext" </p><p style="text-indent: 2em;";> connectionString=" </p><p style="text-indent: 2em;";>Data Source=.SQLEXPRESS; </p><p style="text-indent: 2em;";>Initial Catalog=Movies;Persist Security Info=True; </p><p style="text-indent: 2em;";>User ID=aaa;Password=aaaaaaa " </p><p style="text-indent: 2em;";> providerName="ent" /> </p><p style="text-indent: 2em;";> </connectionStrings> </p><p style="text-indent: 2em;";>connectionString属性的值表示我们想要使用SQL Server Express的一个本地实例中的Movies数据库。当你安装Visual Web Developer Express的时候,安装过程中也会同时自动在你的计算机中安装SQL Server Express,你可以利用它来进行有关数据库的管理工作。 </p><p style="text-indent: 2em;";>运行应用程序,在浏览器中输入“localhost:xxxx/Movies”,浏览器中将会显示一张空的电影列表,如图5-5所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-5 数据库中没有数据时将默认显示空的列表 </p><p style="text-indent: 2em;";>EF code-first如果发现使用我们提供的连接字符串而连接到的数据库中没有“Movies”数据库,它将自动为我们创建一个。你可以在类似“C:Program FilesMicrosoft SQL </p><p style="text-indent: 2em;";>RESSMSSQLDATA”这样的SQL Server的安装目录下去查看是否该数据库已被创建。 </p><p style="text-indent: 2em;";>另外注意,在本教程的前面部分中,我们采用如下所示的代码创建了一个Movie模型。 </p><p style="text-indent: 2em;";>using System; </p><p style="text-indent: 2em;";>using ; </p><p style="text-indent: 2em;";>namespace </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> public class Movie </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> public int ID { get; set; } </p><p style="text-indent: 2em;";> public string Title { get; set; } </p><p style="text-indent: 2em;";> public DateTime ReleaseDate { get; set; } </p><p style="text-indent: 2em;";> public string Genre { get; set; } </p><p style="text-indent: 2em;";> public decimal Price { get; set; } </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";> public class MovieDBContext : DbContext </p><p style="text-indent: 2em;";> { </p><p style="text-indent: 2em;";> public DbSet<Movie> Movies { get; set; } </p><p style="text-indent: 2em;";> } </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>如您所见,当我们第一次使用MoviesController控制器类来访问MovieDBContext所指向的实例时,Entity Framework可以自动为你创建一个新的Movies数据库,并且将MovieDBContext类的Movies属性映射到一个新的Movies表,并且自动将它创建。这个表中的每一行被映射到一个新的Movie类的实例,Movies表的每一列被映射到Movie类的一个属性。 </p><p style="text-indent: 2em;";>你可以使用SQL Server Management Studio来查看使用模型创建出来的数据库与数据表。 </p><p style="text-indent: 2em;";>在Windows的开始菜单中打开SQL Server Management Studio,并且连接到中所配置的数据库,如图5-6所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-6 </p><p style="text-indent: 2em;";>使用SQL Server Management Studio连接数据库 </p><p style="text-indent: 2em;";>点击“连接”按钮进行连接,查看数据库,可以看见Movies数据库与数据表已被创建,如图5-7所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-7 Movies数据库与数据表已被创建 </p><p style="text-indent: 2em;";>鼠标右击Movies数据表,并且点击“设计”,如图5-8所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-8 点击“设计”查看Movies表的属性 </p><p style="text-indent: 2em;";>你可以看见Movies表中各字段的属性,其中ID字段被自动设定为自增长主键,如图5-9中所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图5-9 查看Movies表中各字段属性 </p><p style="text-indent: 2em;";>这里请注意Movies表中各字段是如何映射到Movie类中各属性上的。Entity Framework </p><p style="text-indent: 2em;";>code-fist自动在你创建的Movie类的基础上创建了这张Movies数据表。 </p><p style="text-indent: 2em;";>你现在已经可以访问数据库中的Movies数据表,并且有了一个简单的页面来显示这个表中的内容。在下一节,我们将增加一个追加数据的方法和一个追加数据的视图,并且向数据库中追加一些数据。 </p><p style="text-indent: 2em;";>第六节 增加追加数据的方法和视图 </p><p style="text-indent: 2em;";>在本节中我们将要在数据库中追加并保存一些数据。我们将要创建一个表单以及一些表单输入控件,用来输入数据信息。当用户提交表单时将把这些用户输入的信息保存在数据库中。我们可以通过在浏览器中输入“localhost:xx/Movies/Create”这个URL地址来访问这个表单。 </p><p style="text-indent: 2em;";>6.1 显示追加信息时所用表单 </p><p style="text-indent: 2em;";>首先,我们需要在我们的MoviesController类中追加一个Create方法,该方法返回一个视图,该视图中包含了用户输入信息时所要用到的表单。 </p><p style="text-indent: 2em;";>public ActionResult Create() </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>{ </p><p style="text-indent: 2em;";> return View(); </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";>现在让我们来实现这个Create方法中所要返回的视图,我们将在这个视图中向用户显示追加数据时所需要用到的表单。在Create方法中点击鼠标右键,并点击上下文菜单中的“添加视图”。 </p><p style="text-indent: 2em;";>在“添加视图”对话框中选择“创建强类型视图”,将模型类指定为“Movie”,在支架模板中选择Create,如图6-1所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图6-1 </p><p style="text-indent: 2em;";>添加追加数据时所用视图 </p><p style="text-indent: 2em;";>点击添加按钮,Views文件夹下的Movies文件夹中将会自动添加一个名为“”的视图模板文件。因为你在支架模板中选择了“Create”,所以支架模板会在该视图模板文件中自动生成一些默认代码。打开该文件进行查看,在该文件中已经自动创建了一个HTML表单,以及一段用来显示校验时错误信息的文字。Visual Web Developer检查Movies类,并自动创建与该类中每个属性相对应的<label>元素以及<input>元素。支架模板自动生成的创建数据所用视图中的代码如代码清单6-1所示。 </p><p style="text-indent: 2em;";>代码清单6-1 </p><p style="text-indent: 2em;";>支架模板自动生成的创建数据所用视图中的代码 </p><p style="text-indent: 2em;";>@model </p><p style="text-indent: 2em;";>@{ </p><p style="text-indent: 2em;";> = "Create"; </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";><h2>Create</h2> </p><p style="text-indent: 2em;";><script src="@t("~/Scripts/")" </p><p style="text-indent: 2em;";>type="text/javascript"></script> </p><p style="text-indent: 2em;";><script src="@t("~/Scripts/")" </p><p style="text-indent: 2em;";>type="text/javascript"></script> </p><p style="text-indent: 2em;";>@using (orm()) { </p><p style="text-indent: 2em;";> @tionSummary(true) </p><p style="text-indent: 2em;";> <fieldset> </p><p style="text-indent: 2em;";> <legend>Movie</legend> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> @or(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => ) </p><p style="text-indent: 2em;";> @tionMessageFor(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> @or(model => eDate) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => eDate) </p><p style="text-indent: 2em;";> @tionMessageFor(model => eDate) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> @or(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => ) </p><p style="text-indent: 2em;";> @tionMessageFor(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> @or(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => ) </p><p style="text-indent: 2em;";> @tionMessageFor(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <p> </p><p style="text-indent: 2em;";> <input type="submit" value="Create" /> </p><p style="text-indent: 2em;";> </p> </p><p style="text-indent: 2em;";> </fieldset> </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";><div> </p><p style="text-indent: 2em;";> @Link("Back to List", "Index") </p><p style="text-indent: 2em;";></div> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>这段代码中使用了几个HTML帮助器的方法来帮助简化HTML标签的书写方法。or帮助器用于显示字段名(”Title”,”ReleaseDate”,”Genre”或者”Price”)。For帮助器用于显示一个提供给用户输入信息的HTML的<input>元素。tionMessageFor帮助器用于显示一个针对属性的校验信息。请注意我们的视图模板的顶部有一个“@model ”的声明,该声明将我们的视图模板中的“模型”强类型化成一个Movie类。 </p><p style="text-indent: 2em;";>运行应用程序,在浏览器中输入“localhost:xx/Movies/Create”,浏览器中显示如图6-2所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图6-2 支架模板自动生成的视图 </p><p style="text-indent: 2em;";>在书写中文网站或中文Web应用程序的时候,可以将代码清单6-1中的代码修改为代码清单6-2中所示代码。 </p><p style="text-indent: 2em;";>代码清单6-2 将支架模板自动生成的代码进行汉化 </p><p style="text-indent: 2em;";>@model </p><p style="text-indent: 2em;";>@{ </p><p style="text-indent: 2em;";> = "追加电影信息"; </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";><h2>追加电影信息</h2> </p><p style="text-indent: 2em;";><script src="@t("~/Scripts/")" </p><p style="text-indent: 2em;";>type="text/javascript"></script> </p><p style="text-indent: 2em;";><script src="@t("~/Scripts/")" </p><p style="text-indent: 2em;";>type="text/javascript"></script> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>@using (orm()) { </p><p style="text-indent: 2em;";> @tionSummary(true) </p><p style="text-indent: 2em;";> <fieldset> </p><p style="text-indent: 2em;";> <legend>电影</legend> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>标题 </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => ) </p><p style="text-indent: 2em;";> @tionMessageFor(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>发行日期 </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => eDate) </p><p style="text-indent: 2em;";> @tionMessageFor(model => eDate) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>种类 </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => ) </p><p style="text-indent: 2em;";> @tionMessageFor(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-label"> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>票价 </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <div class="editor-field"> </p><p style="text-indent: 2em;";> @For(model => ) </p><p style="text-indent: 2em;";> @tionMessageFor(model => ) </p><p style="text-indent: 2em;";> </div> </p><p style="text-indent: 2em;";> <p> </p><p style="text-indent: 2em;";> <input type="submit" value="追加" /> </p><p style="text-indent: 2em;";> </p> </p><p style="text-indent: 2em;";> </fieldset> </p><p style="text-indent: 2em;";>} </p><p style="text-indent: 2em;";><div> </p><p style="text-indent: 2em;";> @Link("返回电影列表", "Index") </p><p style="text-indent: 2em;";></div> </p><p style="text-indent: 2em;";>修改完毕后重新运行程序,然后访问“localhost:xx/Movies/Create”这个地址,浏览器中显示如图6-3所示。 </p><p style="text-indent: 2em;";> </p><p style="text-indent: 2em;";>图6-3 中文化后的追加电影信息画面 </p><p style="text-indent: 2em;";>鼠标右击浏览器中显示的该页面,点击“显示源代码”,显示出来的源代码如代码清单6-3所示。(为了突出本节内容,只显示与本节中相关部分)。 </p><p style="text-indent: 2em;";>代码清单6-3 追加电影信息画面在浏览器中的HTML代码 </p><p style="text-indent: 2em;";><!DOCTYPE html> </p><p style="text-indent: 2em;";><html> </p><p style="text-indent: 2em;";><head> </p><p style="text-indent: 2em;";> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> </p><p style="text-indent: 2em;";> <title>追加电影信息

追加电影信息

电影

标题

type="text" value="" />

data-valmsg-replace="true">

发行日期

data-val-required="The ReleaseDate field is required."

id="ReleaseDate" name="ReleaseDate" type="text" value="" />

data-valmsg-for="ReleaseDate"

data-valmsg-replace="true">

种类

type="text" value="" />

data-valmsg-replace="true"/>

票价

data-val-number="The field Price must be a number."

data-val-required="The Price field is required." id="Price"

name="Price" type="text" value="" />

data-valmsg-replace="true">

从这段代码中可以看出,表单的action属性被设置为“/Movies/Create”,当点击追加按钮时会把表单中各文本框中的数据提交到服务器端进行保存。

6.2 处理HTTP-POST

到此为止,我们已经实现了显示追加数据所用表单的所需代码。我们的下一步是编写代码来进行表单提交到服务器后的处理。我们将要获取用户在数据库中输入的信息并且将它们作为一个新的Movie保存到数据库中。

为了实现这一处理,我们需要在MoviesController类中追加第二个Create方法。这个Create方法具有一个[HttpPost]属性,它意味着我们将要用它来处理提交到“/Movies/Create”这个URL地址的请求。另外,所有提交到“/Movies/Create”这个URL地址的非POST的请求(即GET请求)将被第一个Create方法进行处理,即简单地返回一个空的表单。

代码清单6-4中所示代码为MoviesController类中的两个Create方法的全部代码。

代码清单6-4 MoviesController类中的两个Create方法的全部代码

public ActionResult Create()

{

return View();

}

[HttpPost]

public ActionResult Create(Movie newMovie)

{

if (d)

{

(newMovie);

anges();

return RedirectToAction("Index");

}

else

return View(newMovie);

}

之前我们介绍了 MVC可以自动地将一个URL地址中的查询字符串中的参数(例如:传递到“/HelloWorld/Welcome?name=Scott&numTimes=5”)作为一个方法的参数传递到方法中。同样地,除了传递查询字符串中的参数之外, MVC也可以用这种方法来传递提交后的表单参数。

提交后的表单参数可以作为一个独立的参数传递到一个方法中。例如, MVC

framework可以将我们提交的表单中的控件值作为参数传递到具有HttpPost属性的Create方法中,如下所示。

[HttpPost]

public ActionResult Create(string title, DateTime releaseDate, string genre,

decimal price)

{

提交的表单值也可以被映射到一个复合的,具有属性的对象(譬如我们的Movie类),并且作为一个单一的参数传递到一个方法中。在代码清单6-4中我们使用的就是这个方法。请注意Create方法是怎样作为一个参数来接收Movie对象的。

[HttpPost]

public ActionResult Create(Movie newMovie)

{

if (d)

{

(newMovie);

anges();

return RedirectToAction("Index");

}

else

return View(newMovie);

}

d属性用来检查提交的表单中的数据是否能够被用来创建一个Movie对象。如果数据是有效的,我们的代码将把提交上来的这个Movie类追加在MoviesDBContext对象的实例中的Movies集合中。调用我们的MoviesDBContext对象实例的SaveChanges方法将把这个Movie对象保存在数据库中。保存数据完毕后,代码把画面重定向到MoviesController类的Index方法中,浏览器中将会打开电影清单显示画面,并且在电影清单中显示刚才追加的这条数据。

如果提交的值是无效的,将会返回到电影信息追加画面中,并且在表单的各输入控件中显示各自的提交的值。各输入控件的tionMessageFor帮助器将会显示对应的出错信息。

6.3 追加一条电影信息

运行应用程序,在浏览器中输入“localhost:xx/Movies/Create”,在表单中输入一条电影信息,然后点击追加按钮,如图6-4所示。

图6-4 追加电影信息

点击追加按钮进行提交,表单中输入的这条电影信息将会保存到数据库中,保存后浏览器中将打开电影清单画面,并且将这条追加的电影显示在清单中,如图6-5所示。

图6-5 追加后电影将显示在电影清单中

你可能已经注意到了在这个电影清单画面中将刚才追加的电影票价显示成了10元,而不是用户输入的9.99元,这是因为当前该数据表中Decimal类型的默认精度只能识别与处理整数值,并且自动将小数部分四舍五入。关于如何解决这个问题,我们将在下一节中对模型进行一些调整的时候会同时进行介绍。

现在我们已经有了一个Web应用程序的雏形,我们可以在数据库中追加数据,显示数据。代码清单6-5是现在这个MoviesController类的完整代码。

代码清单6-5 MoviesController类的完整代码

using ;

using ;

using System;

using ;

namespace llers

{

public class MoviesController : Controller

{

MovieDBContext db = new MovieDBContext();

public ActionResult Index()

{

var movies=from m in

where eDate>new DateTime(1984,6,1)

select m;

return View(());

}

public ActionResult Create()

{

return View();

}

[HttpPost]

public ActionResult Create(Movie newMovie)

{

if (d)

{

(newMovie);

anges();

return RedirectToAction("Index");

}

else

return View(newMovie);

}

}

}

在下一节,我们将介绍如何为我们的模型添加附加的属性,如何在映射后的数据库中定制我们的票价列的精度。

第七节 在Movie(电影)模型与数据表中添加字段

在本节中我们将要对我们的模型类进行修改,同时介绍如何在 MVC3中根据这些修改来调整我们数据表的结构。

7.1 在我们的Movie模型中添加一个Rating(电影等级)属性

首先,我们在现存的Movie类中添加一个附加的“Rating”属性。打开文件,在Movie类中添加一个Rating属性,如下所示。

public string Rating { get; set; }

现在完整的Movie类的代码如代码清单7-1所示。

代码清单7-1 完整的Movie类的代码

public class Movie

{

public int ID { get; set; }

public string Title { get; set; }

public DateTime ReleaseDate { get; set; }

public string Genre { get; set; }

public decimal Price { get; set; }

public string Rating { get; set; }

}

点击“调试”菜单下的“生成MvcMovie”,重新编译应用程序。

现在我们已经将我们的模型进行了更新,让我们同样地修改我们的Views文件夹下的Movies文件夹下的文件与这两个视图模板文件,在视图中添加这个Rating属性。

首先打开文件,在内容为“票价(”对应Price属性)的元素后面追加“电影等级”列标题(对应Rating属性)。在显示Price属性内容的td元素后面追加一个元素,用来显示Rating属性的内容。进行了这两个修改后的文件中的主要内容如下所示。

@foreach (var item in Model) {

}

电影名称

发行日期

种类

票价

电影等级

@Link("编辑", "Edit", new { id= }) |

@Link("查看明细", "Details", new { id= }) |

@Link("删除", "Delete", new { id= })

@

@("{0:d}", eDate)

@

@("{0:c2}", )

@

接下来打开文件,在表单底部追加如下所示的标签。它将显示为一个文本框,用来输入Rating属性的内容。

电影等级

@For(model => )

@tionMessageFor(model => )

7.2 维护模型与数据库结构之间的差别

现在我们已经将应用程序修改完毕,在Movie模型中添加了一个Rating属性。

现在让我们重新运行应用程序,打开“localhost:xx/Movies”这个URL地址,这时,浏览器会显示一个应用程序出错画面。如图7-1所示。

图7-1 应用程序出错画面

导致这个问题发生的原因是因为在我们的应用程序中,更新后的Movie模型类与我们实际连接的数据库的结构并不统一(Movies数据表中并没有Rating列)。

在默认情况下,当你使用EF code-first自动创建数据库时(就好像本教程中前面所介绍过的那样),EF code-first会自动在数据库中追加数据表来使得数据库的结构与它自动生成的模型类保持同步。如果不同步,EF将会抛出一个错误。这使得在开发程序时对于错误的跟踪会变得更加容易,否则你只能在运行时发现这个错误。同步检查特性正是引起以上显示的错误的原因。

有两种方法可以解决这个错误:

 让Entity Framework自动删除当前数据库,并在新的模型类的基础上重新创建该数据库。这种方法在使用一个测试数据库时对于开发来说是十分方便的,因为它允许你快速地同步修改模型与数据库。但缺点是你将丢失现存库中的数据(所以请不要将这个方法使用在实际使用中的数据库上)。

 修改数据库中的数据表的结构来使之与模型相匹配。这个方法的好处是可以让你保留表中的数据。你可以手工实现这一操作,或创建一个数据表修改脚本来实现这一操作。

在本教程中,我们使用第一种方法,在任何模型发生了改变的情况下让EF code-first自动重建数据库。

7.3 当模型改变时自动重建数据库

现在我们来修改我们的应用程序,使得我们的应用程序中如果任何模型发生了改变,都将自动删除与重建当前模型所使用的数据库。(请使用一个开发测试用的数据库来实践这一操作。用在实际使用的数据库中将造成库中数据的丢失)。

在解决方案资源管理器中,鼠标右击Modes文件夹,选择“添加”,然后点击“类”,如图7-2所示。

图7-2 添加一个新类

在“添加新项”对话框中,将类名定义为“MovieIntializer”,然后点击添加按钮添加该类。书写该类的代码如代码清单7-2所示。

代码清单7-2 MovieIntializer类的完整代码

using System;

using c;

using se;

namespace

{

public class MovieIntializer :

DropCreateDatabaseIfModelChanges

{

protected override void Seed(MovieDBContext context)

{

var movies = new List {

new Movie { Title = "非诚勿扰

2",

ReleaseDate=("2011-1-11"),

Genre="爱情",

Rating="R",

Price=7.00M},

new Movie { Title = "赵氏孤儿",

ReleaseDate=("2011-2-23"),

Genre="历史",

Rating="R",

Price=9.00M},

};

h(d => (d));

}

}

}

使用这个MovieInitializer类之后,一旦我们的模型类发生改变后,我们的模型类所映射的数据库都会被自动重建。代码中使用了Seed方法来指定任何重建数据库的时候想要默认追加到某张数据表中的数据。这为将一些示例数据添加到数据表中的操作提供了一个有用的方法,而不需要重建了数据库之后再手工到数据表中添加示例数据。

现在我们已经定义好了我们的MovieInitializer类,接下来我们想在整个工程中使用这个类,这样每次在运行我们的应用程序的时候会自动检查当前我们的模型类结构是否与数据库结构不一致,如果不一致的时候就自动重建该数据库,并且追加MovieInitializer类中所指定的默认数据。

打开我们的MvcMovies工程的根目录下的文件,如图7-3所示。

图7-3 文件

文件中定义了当前工程所使用到的Application(应用程序)主类,包含了一个Application_Start()事件处理器,当第一次运行我们的应用程序时会触发这个事件。

让我们在文件头部追加两个有用的声明。第一个声明引用Entity Framework命名空间,第二个声明引用我们的MovieInitializer类所存在的命名空间。这两句声明的代码如下所示。

using se; // tialize

using ; // MovieInitializer

接下来寻找到Application_Start方法,在该方法的开头追加一个tializer()方法,代码如下所示。

protected void Application_Start()

{

tializer(new MovieInitializer());

erAllAreas();

RegisterGlobalFilters(s);

RegisterRoutes();

}

我们追加的tializer方法将会在实际使用的数据库中的结构与我们的Movie模型类所映射的数据库结构不匹配时自动重建该数据库,并且自动添加MovieInitializer类中所指定的默认数据。

关闭文件。

重新运行我们的应用程序,并在浏览器中输入“localhost:xx/Movies”。当我们的应用程序启动的时候,会自动觉察出我们的模型类结构与数据库的结构不再匹配,于是重建该数据库使之相匹配,并且自动追加默认数据,浏览器中显示结果如图7-4所示。

图7-4 修改了模型类结构并追加默认数据后浏览器中的显示结果

点击追加按钮进行数据的追加,如图7-5所示。

图7-5 追加数据

点击追加按钮后,新追加的包括Rating(电影等级)字段的数据能正常追加并在电影清单画面中正常显示,如图7-6所示。

图7-6 包括Rating(电影等级)字段的数据能被正常追加与显示


本文标签: 视图 数据 数据库 文件 模板