本文地址http://www.cnblogs.com/outtamyhead/archive/2013/03/25/2980305.html,转载请保留本地址
说在前面:
1、由于是头次翻译整本书籍,所以错误难免,希望大家都提出来,翻译的不好还望大家少拍砖多鼓励。
2、该系列没有按照原文直译,而是加入了我的一些言语在里面(在没有改变原意的情况下),所以大家在看的时候希望有所对照。
3、该系列每周出一或二篇博客,因为我最近很忙,一直在加班,很累的说。
4、该系列不提供原版文字,希望看原版的可以自行下载Pdf。
5、该系列省去了前面的废话,单刀直入,讲主体内容。
首先很抱歉,原本打算是将剩下的部分全部翻译完的,但是发现后面的文字太多了,所以将剩下的部分又分成了三部分来发布。
第二章:第一个ASP.NET MVC4程序(下一)
创建一个简单的数据--实体应用程序
这一章剩下的部分我们将通过创建一个简单的数据--实体应用程序来探索更多MVC基础功能。在这一部分我们将加快速度。我们的目的是演示MVC,所以我们将跳过一些诸如幕后是如何工作的说明。但是不用担心---我们会在后面的章节深入的说明它们。
设置场景
我们假设有一个朋友她打算举办一个新年晚会,她要求我们设计一个网站来帮助她的访问者可以进行电子回复。网站一共有四个关键要素:
一个关于晚会信息的首页
一会可以RSVP的表单
RSVP表单验证,它将显示“谢谢你”的页面
当完成RSVPs时发送邮件给晚会的主人
在接下来的部分,我们将使用在这一章开始时创建的MVC项目然后添加上述功能。我们可以通过前面已经涉及到的内容来完成列表中的第一项--我们可以在已经存在的视图上通过添加一些HTML内容来展现晚会的内容。清单2-7列出了我们在Views/Home/Index.cshtml中添加的内容。
清单2-7 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @ViewBag.Greeting World (from the view) <p>We're going to have an exciting party.<br /> (To do: sell it better. Add pictures or something.) </p> </div> </body> </html>
我们的工作已经开始。如果你现在运行这个程序,你可以看到晚会的详情--当然,这是给详情预留的占位符,但是你已经知道该怎么去做了。如图2-12
设计一个数据模型
在MVC中,M代表着Model,并且它是应用程序中最重要的一部分。模型是对真实世界中的对象、过程及规则的描述。模型,通常称为域模型,包含形成我们应用程序世界的C#对象(域对象)和可以让我们维护这些对象的方法。视图和控制器以一致的方式将这个域暴露给客户端并且一个设计合理的MVC程序是从设计合理的模型开始的,这将是我们添加控制器和模型的重点。
在PartyInvites程序中不需要复杂的模型,但是我们将创建一个叫做GuestResponse的主域类。这个类将负责存储、验证和确认RSVP。
添加模型类
MVC约定所有的模型类都是放在Models文件夹里。右键【Models】文件夹然后选择【Add】--【Class】。将文件命名为GuestResponse.cs,然后点击【Add】按钮来创建这个类。编辑这个类使它和清单2-8一样。
提示:如果你没有找到Class菜单项,可能是Visual Studio处于调试状态。程序在运行状态时,Visual Studio会对项目的更改有约束。
清单:2-8
namespace PartyInvites.Models { public class GuestResponse { public string Name { get; set; } public string Email { get; set; } public string Phone { get; set; } public bool? WillAttend { get; set; } } }
提示:你可能注意到WillAttend属性是可为空的布尔类型,意味着它可以为true、false或者null。我们会在“Adding Validation”部分解释这一原理。
链接动作方法
我们程序的另一个需求是包含一个RSVP表单,所以我们需要在Index.cshtml上添加一个指向它的链接。清单2-9
清单2-9 @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @ViewBag.Greeting World (from the view) <p>We're going to have an exciting party.<br /> (To do: sell it better. Add pictures or something.) </p> @Html.ActionLink("RSVP Now", "RsvpForm") </div> </body> </html>
Html.ActionLink是HTML辅助方法(Helper method)。MVC框架自带有一个内置的辅助方法集合,它们可以方便的渲染HTML链接,文本框,复选框,下拉框和自定义控制。ActionLink方法需要两个参数:第一个是在链接上需要显示的文本内容,第二个是当用户点击链接时要执行的操作。我们将在第19-21章阐述HTML辅助方法。你可以看到在图2-13中我们的链接已经添加好了。
如果你在浏览器中滑动鼠标到这个链接上,你可以看到这个链接指向了http://yourserver/Home/RsvpForm。 HTML.ActionLink方法会检查我们程序中URL路由配置并得出/Home/RsvpForm是在一个叫做HomeController的控制器上调用RscpForm动作的URL。需要注意的是,不像传统的ASP.NET应用程序,MVC中的URL没有对应到物理文件。每个动作方法都有它自己的URL,并且MVC使用ASP.NET路由系统解析这些URL。
添加一个动作方法
如果你点击这个链接你会看到一个404错误页面。那是因为我们还没有添加与/Home/RsvpForm相对应的动作方法。在HomeController类中添加一个叫做RsvpForm的方法,如清单2-10所示。
清单2-10 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace PartyInvites.Controllers { public class HomeController : Controller { public ViewResult Index() { int hour = DateTime.Now.Hour; ViewBag.Greeting = hour < 12 ? "Good Morning" : "Good Afternoon"; return View(); } public ViewResult RsvpForm() { return View(); } } }
添加一个强类型视图
我们打算给RsvpForm动作方法添加一个视图,但是我们的做法有一些小小的不同---我们打算创建一个强类型视图。强类型视图意在渲染一个特定的主域类型,如果我们指定要使用的类型(在这个例子中是GuestResponse),MVC可以创造一些非常有帮助的快捷方式来使它变得简单。
注意:要确保在运行之前你的MVC项目已经生成。如果你添加了GuestResponse类但是没有生成它,MVC将不能为这个类型创建强类型视图。
在RsvpForm动作方法中右键选择【Add View】来创建视图。在【Add View】窗口中,选中Create a strongly-typed view项然后在下拉框中选择GuestResponse。不选择Use a layout or master page,确保选择的是Razor视图引擎并且Scaffole template选项中选择Empty。如图2-14。
点击【Add】按钮随后Visual Studio会创建一个叫做RsvpForm.cshtml并自动打开以便编辑。你可以在清单2-11中看到初始内容。你会注意到,这是另外一个HTML文件,但是它包含一个@model Razor表达式。这时候你会明白,这就是强类型视图的关键所在并且它提供了便捷。
清单2-11 @model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>RsvpForm</title> </head> <body> <div> </div> </body> </html>
建立表单
现在我们已经创建了强类型视图,为了编辑GuestResponse对象,我们在RsvpForm.cshtml中添加了一些内容。编辑你的视图使它和清单2-13一样。
清单2-13 @model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>RsvpForm</title> </head> <body> @using (Html.BeginForm()) { <p>Your name: @Html.TextBoxFor(x => x.Name) </p> <p>Your email: @Html.TextBoxFor(x => x.Email)</p> <p>Your phone: @Html.TextBoxFor(x => x.Phone)</p> <p> Will you attend? @Html.DropDownListFor(x => x.WillAttend, new[] { new SelectListItem() {Text = "Yes, I'll be there", Value = bool.TrueString}, new SelectListItem() {Text = "No, I can't come", Value = bool.FalseString} }, "Choose an option") </p> <input type="submit" value="Submit RSVP" /> } </body> </html>
对于GuestResponse模型类的每一个属性,我们用一个HTML辅助方法来使它渲染成合适的HTML input控件。这些方法可以让你通过使用拉姆达表达式使你选择的属性和input元素一一对应。例如:
@Html.TextBoxFor(x => x.Phone)
HTML TextBoxFor辅助方法为一个input元素生成HTML,type设为text,id和name设为Phone,phone是所选主域类属性的名字。例如:
<input id="Phone" name="Phone" type="text" value="" />
正是因为我们的RsvpForm视图是强类型所以我们才能这么方便的工作,并且我们已经告诉MVC ,GuestResponse是我们想要渲染到视图的类型,所以HTML辅助方法能够推断出通过@模型表达式我们要读取属性的数据类型。
如果你对C#拉姆达表达式不熟悉也不用担心。我们在第四章提供了一个总结---但是一种替代拉姆达表达式的做法是以字符串的形式提供模型类型属性的名称。例如:
@Html.TextBox("Email")
我们发现拉姆达表达式技术可以防止我们把模型类型属性写错,因为Visual Studio的智能提示会自动的让我们选择属性,如图2-15
另一个方便的辅助方法是Html.BeginForm,它可以产生一个HTML表单元素,它被配置用来回递给动作方法。因为我们没有给这个辅助方法提供任何参数,它就会认为我们要回递的是相同的URL。一个巧妙的方法就是把它包在C#的using语句中,例如:
@using (Html.BeginForm()) {
...form contents go here...
}
通常,像这样运用,using语句块可以确保当对象超出范围时对象可以被释放。它通常被用在数据库连接,例如,要确保当一个查询完成连接是关闭的。(这里的using关键字的用法不同于在类中引用命名空间的用法。)
与释放对象不同,HtmlBeginForm会关闭表单元素在它超出范围时。这也就意味着Html.BeginForm辅助方法生成了表单的两部分,例如:
<form action="/Home/RsvpForm" method="post">
...form contents go here...
</form>
如果你对释放C#对象不熟悉也没有关系。这里主要是为了说明怎样通过HTML辅助方法创建表单。当你运行程序时,你会看到在RsvpForm中的表单,如果你点击RSVP Now链接。如图2-16