ASP.NETMVC3 pro系列翻译
asp.netMVC的出现,让前台和后台都得到了一种回归,编程基础扎实的同学学MVC或许要比webform要轻松N倍,你不在为麻烦的控件配置而焦虑,这里只有纯净的前后台代码。刚刚开始学习MVC,所以就加上自己的理解,翻译一些比较好的书籍和同学们一起来分享MVC3的精彩内容。如果有不合适的地方,大家可以指正和指导下我,我会马上修改。英文的资料看起来很容易但是要是用来写成文字,发现远远超过了读前三章的时间,今天我几乎写了3.5个小时的博客到后面有点小浮躁,不知道翻译有没有出入,如有不妥大家都可以指正。
你的第一个MVC应用程序
领悟一个软件开发框架的最佳方式是深入内部并使用它。在这本章中,您将使用ASP.NET MVC框架创建一个简单的数据输入应用程序。我们要一步步的让你看到如何构建一个ASP.NET MVC应用程序。为了简单易懂,我们将跳过一些技术细节的时刻,但不要担心,如果你是初识MVC,你会发现很多让你感兴趣的。在这里我们应用但没有过多的解释(这章的重点不是原理),在后面我们提供各个参考的章节,在这里你可以找到所有的细节。
创建一个新的ASP.NET MVC项目
我们将开始在Visual Studio中创建一个新的MVC项目。从“文件”中选择“新建项目”菜单打开“新建项目”对话框。如果您选择的网页模板,你会看到MVC 3安装程序ASP.NET MVC 3 Web应用程序创建一个新的项目,如图3-1所示。
图3-1。在Visual Studio中的MVC 3项目模板
设置的新项目P名称为artyInvites,并单击“确定”按钮继续。你会看到一个对话框,如图3-2所示,要求您选择三种不同类型的MVC项目模板。
如果仅仅是最低要求的文件和文件夹的MVC 3 应用程序你可以选择创建一个 Empty项目。Internet应用程序“选项创建一个小的示例应用程序,您可以在他的基础上修改和建立自己的应用程序。它包括用户注册和认证,导航和一致的视觉风格。 Intranet应用程序选项是类似于Internet应用程序,但其设计中使用了对用户进行身份验证域/ Active Directory基础结构的环境。在本章中,我们将让事情变得简单易懂。选择“Empty”选项,取消选中的HTML5语义标记选项,并单击“确定”以创建新的项目。
注意:在图3-2中的模板选项中,你可以看到一个下拉菜单,在这里你可以指定需要的视图引擎。正如我们在第1章,MVC 3包含一个新的Razor视图引擎和改进的ASPX视图引擎,这是我们将在本书中群不全部使用Rozor。我们建议你和我们一样这么选择。但是,如果你想使用常规的ASP.NET视图引擎(又称为ASPX引擎),您也可以选择它。
一旦在Visual Studio创建的项目,你会在VS的“解决方案资源管理器”窗口看到一些文件和文件夹结构。这是默认的MVC 3项目的结构。您可以尝试运行
现在应用程序从“调试”菜单中选择“开始调试”(如果提示您启用调试时,只要按一下“确定”按钮)。您可以看到图3-3中的结果。应为我们开始使用了Empty项目模板,应用程序不包含任何内容,所以我们可以看到一个404 Not Found错误。
图3-3。试图运行一个空项目
当你完成后,一定要停止调试,关闭显示错误浏览器窗口(当然也可以不关闭下次生成项目后刷新浏览器),回到Visual Studio,并从“调试”菜单中选择“停止调试。在MVC架构中添加一个控制器,由控制器处理传入的请求。在ASP.NET MVC中,控制器简单的C#类(通常继承自System.Web.Mvc.Controller的,这是asp.netMVC内置控制器基类)。每个公共方法被称为控制器的action方法,这意味着你可以通过一些URL从Web调用和执行一项操作(action)。 MVC约定是把
所有的控制器放在名为Controllers的文件夹中,这是我们创建项目时,由Visual Studio创建的控制器。你并不需要遵循本约定或其他大多数MVC约定,但我们建议你这样操作,并不是简单的因为这将有助于你理解这本书中的例子。
右键单击Controllers文件夹中的Visual Studio解决方案资源管理器窗口,并从弹出的菜单中选择“添加”,然后控制器,添加一个控制器到我们的项目中,如图3-4所示。
图3-4。添加控制器的MVC项目
当出现“添加控制器”对话框时,将名称设置为HomeController的,如图3-5所示。这又是一个约定:我们给控制器的名称应该是描述性和以Controller结尾。
图3-5。设置为控制器的名称
Scaffolding options中给我们预制了控制器使用常见功能的模板。我们不打算使用此功能,因此要确保在“模板”菜单中选择Empty controller,如图所示。 注意:如果你没有看到,因为它是在图3-5所示的“添加控制器”对话框中,你可能忘了安装工具更新MVC 3。有关详细信息,请参阅第2章。
单击“添加”按钮,创建一个控制器。Visual Studio将在Controller文件夹中创建一个新的名为HomeController.cs的C#代码文件,打开它进行编辑时,你可以看到,这个被称为HomeController的类,它是在System.Web.Mvc命名空间下定义的。编辑这个文件中的代码,如下3-1。
Listing 3-1. 修改 HomeController 类
using System.Web.Mvc; namespace PartyInvites.Controllers { public class HomeController : Controller { public string Index() { return "Hello, world"; } } }
当然这不足以令人兴奋的,但对刚刚学习MVC的童鞋,这是一个很好的开端。我们创建了一个名为为Index的action方法,它会返回字符串“Hello,world”。再次运行该项目(由从Visual Studio的“调试”菜单中选择“启动调试)。浏览器将显示的结果。如图3-6所示。
图3-6 浏览器输出结果
了解路由
除了模型,视图和控制器,MVC应用程序也使用ASP.NET路由系统,决定如何将URL映射到特定的控制器和action中。
当Visual Studio创建的MVC项目,它会添加一些默认路由,您可以使用下面的任何一个URL请求,他们将被引导到了HomeController的Index action:
• /
• /Home
• /Home/Index
当浏览器请求http://yoursite/的或http://yoursite/Home,将调用HomeController的Index方法。输出字符串“Hello,world”。这是一个很好的遵循MVC约定的例子。在这种情况下,我们将有一个名叫HomeController的控制器,这将是我们的MVC应用程序的起点。有一个名叫HomeController的,这将是我们的MVC应用程序的起点。假设我们遵循了这一约定Visual Studio会创建一个新的项目的缺省路由,我们的URLS前面的列表中得到支持。如果我们没有依循惯例,我们将需要手动修改的路由指向需要的控制器。对于这个简单的例子中,默认的配置就够了。
提示:您可以通过打开的Global.asax.cs文件查看和编辑您的路由配置。在第7章中,您将设置自定义路由表项,并在第11章中,你会学到更多关于路由可以做什么。
渲染网页
前面的例子不是输出HTML而是简单的字符串“Hello,world”。我们需要创建一个视图浏览器请求,响应HTML。
创建和渲染视图
我们需要做的第一件事情就是修改我们的索引中的操作方法,如清单3-2所示。
清单3-2。修改控制器渲染视图
using System.Web.Mvc; namespace PartyInvites.Controllers { public class HomeController : Controller { public ViewResult Index() { return View(); } } }
在清单3-2以粗体显示。当我们返回一个ViewResult对象从一个action方法,我们我们通过调用视图的方法创建的ViewResult
(不带任何参数)发出指令让MVC渲染视图。这将使MVC为该action呈现的默认视图。如果您运行的应用程序,你可以看到MVC框架试图找到一个默认的视图显示的错误信息如图3-7中所示。
如图3-7所示。 MVC框架试图找到一个默认的视图
错误消息是最有帮助的。它不仅解释无法为某个action方法找到一个MVC视图,这又是一个很好的MVC约定“:view与action方法的命名约定。我们的action方法称为Index,你可以从图3-7中看到的MVC正试图在“视图”文件夹中找到不同的文件所有相同名称。
创建一个视图,用鼠标右键单击在HomeController.cs代码文件的操作方法(无论是在方法的名称或内部的方法体),从弹出的菜单中选择“添加视图”。这将打开添加视图“对话框,如图3-8所示。
取消选中“使用布局或母版页。我们不使用布局,在这个例子中,但我们会看到他们在第5章中使用。点击“添加”按钮,Visual Studio将在 View/ Home创建一个新的视图文件Index.cshtml。如果你回头看看图3-7中的错误信息,你会看到,被搜查的路径之一与我们刚创建的文件相匹配。
提示:CSHTML的文件扩展名表明他是一个由Razor视图引擎处理的。老版本的MVC依靠ASPX视图引擎,视图文件.aspx扩展名。
打开Index.cshtml文件进行编辑。这个文件主要包含HTML。 其中有一段代码块如下:
@{ Layout = null; }
这是一个将被Razor视图引擎解释的代码块。它只是告诉Razor视图引擎,我们选择不使用母版页。
如图Index.cshtml文件在清单3-3中所示
@{ Layout = null; } <!DOCTYPE html> <html> <head> <title>Index</title> </head> <body> <div> Hello, world (from the view) </div> </body> </html>
添加一些简单的信息。选择“开始”,从“调试”菜单中进行调试运行并测试应用程序。您应该会看到类似图3-9。
当我们第一次创建Index的action方法,他除了输出简单的字符串返回给浏览器什么都没干。现在,该方法返回一个ViewResult类型的对象,指示MVC渲染视图,并返回HTML。我们没有并没有指定MVC视图应该怎么做,所以它使用的命名约定自动匹配。相应的View具有和controller文件夹中的action方法一样的名称——~/Views/Home/Index.cshtml.我们可以让action方法返回其他结果(除了字符串的ViewResult对象)。例如,如果我们返回RedirectResult,浏览器重定向到另一个URL。如果我们返回HttpUnauthorizedResult,我们强制用户登录。他们都继承自ActionResult类。action result 体系让我们封装和复用常见的相应操作更加方便。我们将通过这本书告诉你更多关于他们复杂的使用。
添加动态输出
当然,对于整个Web应用程序平台的构建和动态显示输出来看,在MVC,准备响应数据是控制器的工作,呈现HTML则是视图的工作。数据从控制器传递到视图。
数据从控制器传递到视图的方法之一是通过使用ViewBag对象。这是一个Controller基类的成员。 ViewBag是一个动态对象,你可以指定任意的属性,并使这些值呈现在任何视图中。清单3-4演示
以这种方式通过一些简单的动态数据。
Listing 3-4. Setting Some View Data using System; 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(); } } }
以粗体显示的语句我们提供的数据的视图。如清单3-5所示。
Listing 3-5. Retrieving a ViewBag Data Value @{ Layout = null; } <!DOCTYPE html> <html> <head> <title>Index</title> </head> <body> <div> @ViewBag.Greeting, world (from the view) </div> </body> </html>
清单3-5是一个Razor代码块,检索保存在的ViewBag的greeting属性。该属性名称没有什么特别的之处,你可以更换任何自定义属性名称(它的作用是相同的)。当然,你可以在视图中以相同的方式获取多个数据值的。
提示:我们并不需要终止Razor代码块。我们以@字符开始,然后添加我们的C#代码。这是Razor一个很好的特性。这样更具可读性,我们不在需要使用烦人的<%和%>标记。
如果我们再次运行该项目,我们可以看到我们的第一个动态的MVC输出,如图3-10所示。
创建一个简单的数据录入应用程序
在本章的剩余部分,我们将通过建立一个简单的数据输入应用程序探讨更基本的MVC功能。在本节我们将加快进度。我们的目标是展示MVC的应用, 所以我们跳过一些的解释是后台是如何工作的的话题。但是不要担心,在后面的章节中,我们将再次深入这些话题。
设置场景
我们会想象,一个朋友已经决定举办一个除夕派对,她要我们创建了一个网站,让她受邀者使用电子邮件回复。她要求四个主要特点:
- 显示有关晚会的一个主页
- 提交RSVP的表单
- 验证RSVP的格式,之后将显示一个感谢页面
- 完成后回函电子邮件
在下面的章节中,我们将建立在已经创建的MVC项目中,我们在本章开始添加这些功能。通过运用我们在前面的内容中,我们可以添加一些HTML到我们现有的视图来描述party的细节,如清单3-6所示。
Listing 3-6. Displaying Details of the Party @{ Layout = null; } <!DOCTYPE html> <html> <head> <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>
您运行的应用程序,你会看到party的细节,如图3-11所示。
设计一个数据模型
在MVC中,M代表的是模型,它是应用程序最重要的的一部分。该模型是将真实世界的对象,过程和规则抽象的定义在程序域中,通常被称为一个域模型,该模型包含了C#对象已知的域对象),使我们可以在应用程序和方法中对它们进行操作,并通过一些方式可以将其信息回馈给客户端。一个精心设计的模型是一个设计良好的MVC应用程序的开始,现在我们把重点放在添加控制器和视图。我们并不需要为PartyInvites应用程序添加一个复杂的模型,这里我们只是用一个简单的名为GuestResponse域模型我们将使用用于负责存储,验证,并确认RSVP。
添加一个模型类
MVC的约定是,一个模型的类被放置在〜/ Models文件夹。在“解决方案资源管理器”窗口中右键单击“模型,并选择”添加类从弹出的菜单。设置文件名GuestResponse.cs,并单击“添加”按钮来创建类。按照清单3-7编辑类的内容。
提示 您可能已经注意到,WillAttend属性是一个可为空的布尔值,这意味着它可能是true,false,或者为null。“添加验证”我们将在后面的章节中解释“添加验证”的理由。
链接操作方法
我们的应用程序包括了RSVP表单,所以我们需要添加一个链接到它从我们的Index.cshtml视图,如清单3-8所示。
Listing 3-8. Adding a Link to the RSVP Form @{ Layout = null; } <!DOCTYPE html> <html> <head> <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辅助方法。MVC框架集中方便的选择辅助方法的渲染HTML链接,文本输入框,复选框,甚至是自定义的控件。 ActionLink方法有两个参数:第一个是要显示的文本的链接,第二个是要执行的action。当用户点击的链接,您可以看到在图3-12中添加的链接效果。我们将在第15和第16章中讲解HTML辅助方法。
当你的鼠标放在浏览器中的链接上时,你会看到该链接指向ttp://yourserver/Home/RsvpForm。 Html.ActionLink方法检查我们的应用程序的URL
路由配置和执行HomeControls中的名为ResvpForm的action。注意,不同于传统的ASP.NET应用程序,MVC的URL不对应于物理的文件。每个action方法都有其自己的URL,MVC使用ASP.NET路由系统把这些urls指向创建的action方法.如果您单击的链接,你会看到一个404 Not Found错误.因为我们还没有创建的action方法
对应的/Home/RsvpForm中的URL。为此,我们要给HomeController类添加一个名为RsvpForm的方法,如清单3-9所示。
Listing 3-9. Adding a New Action Method to the Controller using System; using System.Web.Mvc; namespace PartyInvites.Controllers { public class HomeController : Controller { public ViewResult Index() { int hour = DateTime.Now.Hour; ViewData["greeting"] = hour < 12 ? "Good morning" : "Good afternoon"; return View(); } public ViewResult RsvpForm() { return View(); } } }
添加一个强类型的视图
我们给RsvpForm方法添加的视图,但我们会做一些调整,我们要创建一个强类型的视图。一个强类型的视图的目的是渲染一个特定的域类型,如果我们指定的类型,我们使用(在这个例子中是GuestResponse),MVC可以提供一些有用的快捷方式,使其更容易。
注意 在做其他事情之前,请确保您的MVC项目被编译。如果您已经创建了GuestResponse类,但没有编译,MVC将无法创建一个强类型的视图对应这种类型。
从Visual Studio生成“菜单中选择”生成解决方案编译您的应用程序。
右键单击里面的RsvpForm方法,并从弹出的菜单中选择“添加视图”。在“添加视图”对话框中,选中“创建一个强类型的视图选项,并从下拉菜单中选择GuestResponse。取消选中“使用布局或母版页,并确保选择Razor引擎布局模板“选项设置为空,如图如图3-13所示。
单击“添加”按钮,创建新的视图。Visual Studio将打开RvspForm.cshtml文件,你会看到,它是一个一个@ modelRoazr格式开头的HTML文件。正如你将看到
当前这已经是一个强类型的视图,它提供的很多的便利。
建立表格
现在,我们已经创建了强类型的视图,我们可以在RsvpForm.cshtml文件中编写一个HTML表单用于编辑GuestResponse对象。如下清单3-10。
Listing 3-10. Creating a Form View
@model PartyInvites.Models.GuestResponse
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<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标签。这些方法会让你选择输入元素的属性,涉及到
使用lambda表达式,例如:
@ Html.TextBoxFor(X => x.Phone)
不要担心,如果你不熟悉C#lambda表达式。我们在第5章中提供了一个概述。
HTML辅助方法生成的HTML生成一个input 元素,设置它的type为text,并设置id和name属性为Phone,而这些都是以的域模型的属性名为准,如下
属性,如下所示:
<input id="Phone" name="Phone" type="text" value=""
这个方便的特性依赖于此处的RsvpForom方法对象的视图是强类型的,我们已经告诉过MVC,操作的是GuestResponse类型,我们要渲染这个View。
另一种替换lambda表达式的方法是使用一个名称相同的字符串类型的属性,例如:
@ Html.TextBox(“电子邮件”)
我们发现,我们的lambda表达式技术可以防止输错的模型名称和相应的属性。Visual Studio会弹出智能提示让我们挑选的合适的并自动完成关联,如图3-14所示。
另一种方便的辅助方法是Html.BeginForm,生成一个HTML表单元素并配置回发的操作方法。因为我们还没有传递任何参数给该方法,它会认为我们要回发到相同的URL。一个使用它的绝招是用C#using 声明包装它,例如:
@using (Html.BeginForm())
{
...form contents go here...
}
通常情况下,这样的应用时,使用的语句确保一个 超出范围对象被及时释放。它常用于数据库操作中,例如,在完成一个查询以确保他们 尽快关闭,(这里的using关键字不同于讲一个外部类用一个命名空间引入到一个类的作用域中的using),而不是丢弃对象, HtmlBeginForm helper在HTML表单元素超出的范围自动将其释放。这意味着该 Html.BeginForm辅助方法创建的表格元素,像这样两个部分:
<form action="/Home/RsvpForm" method="post">
形式内容到这里...
</ FORM>
不要担心,如果你不熟悉C#对象的处理。这里的关键是演示如何创建使用HTML辅助方法的一种形式。
提示 ASP.NET WebForm只支持一个服务器端的控件,通常注明为<form runat="server">,这是一个视图状态数据和回传逻辑的容器。MVC则不需要这种的形式。我们只需要使用使用普通的HTML标签,你可以在一个视图中素心所欲的使用。而不必担心没有视图状态(ViewState)或其他隐藏的表单元素的id值分配错位。当您运行的应用程序,然后单击“现在的RSVP链接,你可以看到的形式在RsvpForm视图。图3-15显示了结果。
请注意:这不是一本关于CSS网页设计。在大多数情况下,我们将要创建的例子,它的外观可以被描述为乡巴佬(虽然我们喜欢这个词的经典之作,但不是轻蔑)。MVC视图生成非常干净和纯洁的HTML,你可以完全控制他们被分配到的布局元素和类,所以你可以使用设计工具或现成的模板,让你的MVC项目漂亮。
我们将创建另外一个强类型的视图,因此在“添加视图”对话框中,我们选择的视图模型必须与传递给视图中使用的View方法的类一致,所以必须从Modles class下拉列表中选择GuestResponse。确保选择母版页“选项没有被选中,视图内容设置为空。单击“添加”创建新的视图。MVC创建了一个新的视图文件,~/Views/Home/Thanks.cshtml.编辑新的视图,如Listing 3-12。
Listing 3-12. The Thanks View @model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <title>Thanks</title> </head> <body> <div> <h1>Thank you, @Model.Name!</h1> @if (Model.WillAttend == true) { @:It's great that you're coming. The drinks are already in the fridge! } else { @:Sorry to hear that you can't make it, but thanks for letting us know. } </div> </body> </html>
Thanks View使用Razor显示基于GuestResponse类的属性值的内容,通过RsvpForm的action方法访问视图。@model运算符指定View的域模型的是强类型的类型。要访问域对象的属性值,我们使用Model.PropertyName。例如,得到的Name属性的值,我们使用,Model.Name。不要担心,如果的Razor语法不熟悉 - 我们将在第5章解释它现在,我们已经创建了Thanks View启动应用程序Visual Studio中,单击“RSVP”链接,之后添加一些数据,并单击“SubmitRSVP“按钮。你会
看到如图3-17所示的结果(虽然它可能会有所不同,如果你的名字是不是Joe,或者你选择不能参加)。
添加验证
现在我们为应用程序添加验证。如果我们不这样做,我们的用户可以输入垃圾数据,甚至提交一个空的表单。在MVC应用程序中,验证通常应用在域模型中,而不是在用户接口。这意味着,我们在同一个地方定义我们的验证标准,它在任何地方生效。ASP.NET MVC支持声明System.ComponentModel.DataAnnotations命名空间的属性定义的验证规则。
清单3-13显示了如何将这些特性应用于到的GuestResponse的模型类。
上面用粗体显示了验证规则。 MVC检测验证属性,并使用它们来来验证数据模型的绑定过程。请注意,我们导入了包含验证类的命名空间。
提示如前所述,我们使用了一个可为空的布尔的WillAttend属性。所以我们可以应用必要的验证属性。如果我们用一个普通的布尔值,该值可能是我们通过模型绑定唯一的true或false的,我们将不用去告诉如果用户怎么样选择一个值。可空布尔有三个可能的值:true,false和null。空值将被使用,如果用户还没有选择的一个值,这所需的属性来报告验证错误。我们在我们的控制器类可以使用ModelState.IsValid属性检查验证状态。
清单3-14显示了如何做到这一点
如果没有验证错误,我们告诉MVC渲染Thanks视图。如果有验证错误,我们重新呈现的RsvpForm之前的视图,并将错误显示给用户我们需要显示给用户,验证错误,我们可以使用Html.ValidationSummary辅助方法,如清单3-15所示。
如果有没有错误,Html.ValidationSummary的方法创建一个隐藏的 MVC的占位符,并添加验证属性定义错误消息。你可以看到这显示在图3-18。
注意:如果您使用过ASP.NET WebForm,你就会知道,“服务器控件,WebForm通过序列化到__VIEWSTATE的隐藏的表单字段的值保持状态。 ASP.NET MVC模型绑定
不同于WebForm的服务器控件,回发,视图状态的概念。 ASP.NET MVC不注入隐藏的__VIEWSTATE字段到您的渲染HTML页面。
高亮显示验证
HTML helper方法是创建文本框,下拉框和其他元素的HTML的辅助方法,它有一个非常方便的功能,可用于与模型绑定。同样的机制,可以保留的数据表单中输入的用户也可以用于突出显示个别字段失败验证检查。
当一个模型类的属性未通过验证,HTML辅助方法会产生轻微不同的HTML。举个例子,这里的HTML是调用Html.TextBoxFor(X => x.Name的)产生的
如果没有验证错误将是如下代码:
<input data-val="true" data-val-required="Please enter your name" id="Name" name="Name" type="text" value="" />
当用户没有提供一个值(这是一个验证错误,因为我们调用了GuestResponse模型类Name属性的Required验证约束)你会看到代码略有不同:
<input class="input-validation-error" data-val="true" data-val-required="Please enter your name" id="Name" name="Name" type="text" value="" />
我们加粗以突出显示的不同之处。这个helper方法添加一个CSS类,称为input-validation-error。不同的辅助方法适用于不同的CSS类,但它们都可以在~/Content/Site.css的样式表中找到。怎么引入该样式表,是这样的:
<link rel="Stylesheet" href="@Href("~/Content/Site.css")" type="text/css"/>
提示:如果你已经使用了ASPX视图引擎,您可以使用指定路径直接使用符号(〜)(如:HREF=“〜/内容/的Site.css的”),并依靠视图引擎转换到一个URL,浏览器可以按照(如 href="~/Content/Site.css")。 Razor视图引擎采用不同的方法。它要求使用HREF运算符将URL(如:HREF href="@Href("~/Content/Site.css")")。在第5章中,你可以找到更详细的介绍。
现在,当用户提交数据,将导致验证错误,他会看到一个更加明显方式展示问题的根源,如图3-19所示。
完成示例
我们的应用程序中的最后一个要求是我们的朋友,使用电子邮件完成给组织者的回函。我们可以通过添加action方法并使用.NET框架中e-mail类来创建和发送电子邮件的信息做到这些,不过这里,我们将使用webmail的辅助方法。这不是MVC框架的一部分,但它确实让我们完成这个例子中的细节,而不用设立其他的发送电子邮件形式。
请注意 我们使用了webmail的辅助方法,因为它让我们发送电子邮件消息的变得不费吹灰自理。然而,通常情况下,我们宁愿把这个功能的放在一个action方法中。在第4章中描述了MVC架构模式时,我们将解释为什么。
清单3-16 Using the WebMail Helper
@model PartyInvites.Models.GuestResponse @{ Layout = null; } <!DOCTYPE html> <html> <head> <title>Thanks</title> </head> <body> @{ try { WebMail.SmtpServer = "smtp.example.com"; WebMail.SmtpPort = 587; WebMail.EnableSsl = true; WebMail.UserName = "mySmtpUsername"; WebMail.Password = "mySmtpPassword"; WebMail.From = "rsvps@example.com"; WebMail.Send("party-host@example.com", "RSVP Notification", Model.Name + " is " + ((Model.WillAttend ?? false) ? "" : "not") + "attending"); } catch (Exception) { @:<b>Sorry - we couldn't send the email to confirm your RSVP.</b> } } <div> <h1>Thank you, @Model.Name!</h1> @if (Model.WillAttend == true) { @:It's great that you're coming. The drinks are already in the fridge! } else { @:Sorry to hear that you can't make it, but thanks for letting us know. } </div> </body> </html>
我们增加了一个Razor代码块,使用WebMail的辅助方法配置电子邮件服务器,包括服务器名称,服务器是否需要SSL连接,和帐户详细信息。
一旦我们配置了所有的细节,我们就可以使用WebMail.Send的方法来发送电子邮件。这里我们使用在try ... catch块,如果不发送电子邮件不成功也可以提醒用户。一个更好的方法是如果不能发送的电子邮件消息将显示一个单独的错误视图而不是在同一个View中显示各用户,但我们希望保持我们的第一个MVC应用程序中的简单易懂(所以暂时不这么做)。
总结
在本章中,我们创建了一个新的MVC项目,并用它来构建一个简单的MVC数据输入应用程序,让你一睹MVC框架结构和方法的魅力。我们跳过了一些关键的功能(包括Razor语法,路由和自动测试),但在后面的章节中,我们会回头来深入这些主题。在下一章中,我们将探讨的MVC架构,设计模式和技术,并贯穿全书。