《精通 ASP.NET MVC 4》----2.4 创建一个简单的数据录入应用程序

简介: 本章的其余部分将通过建立一个简单的数据录入应用程序,来考察MVC的更多基本特性。本节将分步进行,目的是演示MVC的运转,因此会跳过对幕后工作原理的一些解释。不用担心——在后面的章节中还会重新深入地讨论这些论题

本节书摘来自异步社区《精通 ASP.NET MVC 4》一书中的第2章,第2.4节,作者: 【美】Adam Freeman ,译者: 李萍 , 徐燕萍 , 林逸 , 更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.4 创建一个简单的数据录入应用程序

精通 ASP.NET MVC 4
本章的其余部分将通过建立一个简单的数据录入应用程序,来考察MVC的更多基本特性。本节将分步进行,目的是演示MVC的运转,因此会跳过对幕后工作原理的一些解释。不用担心——在后面的章节中还会重新深入地讨论这些论题。

2.4.1 设置场景

设想一个朋友要主办一个“新年除夕晚会”,需要创建一个Web网站,以便让被邀请人进行RSVP(电子回复)。这个网站需要以下四个关键特性:

一个显示此晚会信息的主页;

一个可以用来进行RSVP(电子回复)的表单;

对RSVP表单的验证,它将显示一个“谢谢你”的页面;

当完成RSVP时,给晚会的主人发送一份电子邮件。

以下小节将增强本章开始已经创建的MVC项目,并实现上述这些特性。读者可以利用前面已经涉及的内容来完成上述列表中的第一项——将一些HTML添加到现在的视图上,以给出晚会的细节。清单2-7显示了对Views/Home/Index.cshtml文件所添加的内容。

清单2-7 显示晚会的细节


f1377f26db7af60100d7b5d81c6215924248f6ea

开发已经开始了。如果运行该应用程序,就会看到晚会的详情——没错,这只是一个详情占位符,但可以从中获得思路(指这个页面只是一些简单的消息,在实际应用中,读者可以用丰富的内容来替换这里的消息,故将其说成是占位符——译者注),如图2-12所示。


42f29c6a52d0804048ceb101de2af1773136252f

2.4.2 设计一个数据模型

在MVC中,M代表模型(Model)是应用程序最重要的部分。模型是应用程序主体(称为域,Domain)所定义的现实对象、过程以及规则的表示。模型,通常称为域模型(Domain Model),含有应用程序域中要建立的C#对象,称为域对象(Domain Object)。这些域对象构成了整个应用程序的体系,以及操纵这些对象的方法。视图和控制器以一致的方式把这个域暴露给客户端。一个设计良好的MVC应用程序,必须从设计良好的模型开始,它是随后添加控制器和视图的焦点(现在国内流行将这里的“域”称为“领域”,译者认为这种术语不妥,但如果读者不习惯这里的“域”术语,可以将本书的“域”理解为“领域”——译者注)。

对于这个PartyInvites(晚会邀请)应用程序,不需要复杂的模型,因此将创建一个域类,叫作GuestResponse。这种对象将负责存储、验证并确认RSVP。

添加模型类
MVC的约定是把建立模型的类放在“Models”文件夹内。在“Solution Explorer(解决方案资源管理器)”窗口中右击“Models”,从弹出菜单中选择“Add(添加)”→“Class(类)”,将文件名设置为“GuestResponse.cs”,点击“Add(添加)”按钮,创建这个类。编辑该类的内容,使其与清单2-8吻合。

提示:如果没有“Class(类)”菜单项,那么可能仍在运行Visual Studio的调试器。调试器正在运行应用程序期间,VisualStudio会限制用户对项目进行修改。
清单2-8 GuestResponse域类

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属性是一个nullable(可空的)的bool型,这意味着它可以是true、false或null。本章的2.4.6节将解释这一原理。

2.4.3 链接动作方法

该应用程序的目标之一是要包括一个RSVP的表单,因此需要在Index.cshtml视图中添加一个指向它的链接,如清单2-9所示。

清单2-9**添加一个指向RSVP表单的链接


0d36c1428af0d699f6e069de4d78bd3e5afc7ec5

Html.ActionLink是一个HTML辅助器方法(Helper Method),其作用是渲染一个超链接的HTML标记。MVC框架随带了一组内建的辅助器方法,它们可以方便地用来渲染HTML的链接、文本输入框、单选框、复选框,甚至自定义控件等。这个ActionLink方法需要两个参数:第一个是该链接的显示文本,第二个是当用户点击该链接时将要执行的动作。第19~21章将解释其余的HTML辅助器方法。读者可以在图2-13中看到添加的这个链接。


faa3e476eb8f486e8a486dc361e2767bd5d04edf

如果在浏览器中将鼠标指针移到这个链接上,可以看到这个链接指向http://<你的服务器>/Home/RsvpForm。Html.ActionLink方法已经检测了应用程序的URL路由配置,并得出/Home/RsvpForm是在一个叫作HomeController的控制器上调用RscpForm动作的URL。注意,与传统的ASP.NET应用程序不同,MVC的URL并不对应于物理文件。每个动作方法有它自己的URL,而MVC使用ASP.NET的路由系统把这些URL转换成动作。

创建动作方法
如果点击这个链接,就会看到一个“404—未找到”的错误,这是因为还没有创建与这个/Home/RsvpForm地址所对应的方法。可以把一个名为“RsvpForm”的方法添加到HomeController类,如清单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动作方法添加一个视图,但做法稍有不同——创建一个强类型视图(Strongly Typed View)。强类型视图意在渲染一个特定的域类型,而且,如果指定了想使用的类型(本例是GuestResponse),MVC将能够创建便于使用这个类型的便捷手段(指MVC提供了一些辅助器方法,在视图中可以方便是使用这个类型对象——译者注)。

注意:在做后面的事情之前,请确保已编译了MVC项目。如果已经创建了GuestResponse类,但未编译它,MVC将不能为这个类型创建强类型视图。要编译应用程序,可以从Visual Studio的“Build(生成)”菜单中选择“Build Solution(生成解决方案)”(或简单地按快捷键F6——译者注)。
在RsvpForm动作方法中单击鼠标右键,从弹出菜单中选择“Add View(添加视图)”,创建这个视图。在“Add View(添加视图)”对话框中选中“Create a strongly-typed view(创建强类型视图)”选项,并从下拉列表中选择GuestResponse,取消选中“Use a layout or master page(使用布局或母版页)”复选框,并确保选择了Razor作为视图引擎,在“Scaffold template(支架模板)”中选择“Empty(空模板)”,如图2-14所示。

点击“Add(添加)”按钮,Visual Studio将创建一个名为RvspForm.cshtml的新视图文件,并打开它以便编辑。清单2-11是它的最初内容。读者可能会注意到,这是另一种骨架形式的HTML文件,它含有Razor表达式@model。稍后会看到,这个@model是强类型视图的关键,也是为视图提供方便的关键。


e24ac7e87a19fb8d93bbca4f8bd739546444260e

清单2-11 RsvpForm.cshtml文件的最初内容


016edb57f4643b57ae8a3c36c656e9cf310aca8a

2.4.4 建立表单

现在,强类型视图已经创建了。可以扩建RsvpForm.cshtml的内容,将其制作成编辑GuestResponse对象的HTML表单。编辑该视图,使它如清单2-12所示。

清单2-12 创建一个表单视图


8654b31c9b2afba9d8a5c1cfbb5b61dea8348ce4

对于GuestResponse模型类的每一个属性,可使用一个HTML辅助器方法来渲染一个适当的HTML的input控件。这些方法让用户能够用lambda(读音同希腊字母λ的发音(拉姆达)——译者注)表达式来选择与input元素有关的属性,如下所示。

@Html.TextBoxFor(x => x.Phone)
这个HTML的TextBoxFor辅助器方法生成HTML的input元素,将其type参数设置为text,并把id和name标签属性设置为Phone,Phone是所选域类的属性名,如下所示(于是为模型属性Phone生成了一个文本框,该文本框是一个HTML的input元素——译者注)。

<input id="Phone" name="Phone" type="text" value="" />
这种灵活的特性是能够起作用的,因为这个RsvpForm视图是强类型的,而且已经告诉了MVC——GuestResponse是希望该视图所渲染的类型。因此,HTML辅助器方法能够通过@model表达式推断出用户想根据哪种数据类型来读取属性。

如果不熟悉C#的lambda表达式,不用着急,本书将在第4章提供一个概览。不过,替代运用lambda表达式的另一种办法是,将模型类型的属性名指示为一个字符串,如下所示。

@Html.TextBox("Email")
可以发现,lambda表达式技术可以防止人们输错模型类型的属性名,因为Visaul Studio会弹出智能感应,并让人们自动地选取属性,如图2-15所示。

另一个方便的辅助器方法是Html.BeginForm,它生成一个回递给动作方法的HTML表单元素(

元素)。由于没有给这个辅助器方法传递任何参数,于是它假设用户是想回递给同样的URL。一个整洁的技巧是把它封装在一个C#的using语句中,如下所示。
@using (Html.BeginForm()) {
    ..._表单内容放在这儿_...
}

正常情况下,像这样运用using语句,会在对象超出范围时,确保对这个对象进行了清理(清理对象意指收回对象所占用的资源——译者注)。例如,这通常用于数据库连接,以确保查询完成后尽快关闭这个连接(此处的using关键词与在一个类中引用命名空间的那种using不同)。

这里并不是清理对象(上一段文字是指“正常情况下”——译者注),而是Html.BeginForm辅助器在它超出范围时关闭HTML的form元素。这意味着,Html.BeginForm辅助器方法会创建form元素的两部分(指

元素的开标签和闭标签——译者注),如下所示。

<form action="/Home/RsvpForm" method="post">
..._表单内容放在这儿_...
</form>
即使不熟悉C#的对象清理,也不必担心。这里的关键是演示如何用HTML辅助器方法创建一个表单。当运行这个应用程序并点击“RSVP Now(现在回复)”链接时,便可以看到RsvpForm视图中的这个表单,如图2-16所示。


f247199f8d4859e71c66a8f004573a590cc71dc2

注意:由于这不是一本关于CSS或Web设计的书,本书的大部分内容将把示例演示成流行的样式(虽然本书更喜欢把它说成“经典样式”,但感觉不太对)。MVC视图生成十分整洁且纯净的HTML,而且用户可以完全控制元素的布局,以及用表单进行赋值的类,因此,使用设计工具或现成的模板,让MVC项目美观是没有问题的。

2.4.5 处理表单

此时还没有告诉MVC,将表单递交给服务器时要做什么。此刻,点击“Submit RSVP”按钮只是清除了表单中已经输入的值。这是因为,该表单会回递给Home控制器中的RsvpForm动作方法,它只是告诉MVC再次渲染这个视图。

注意:读者可能会感到奇怪,视图被再次渲染时,输入的数据消失了。如果有这种感觉,可能是因为一直在使用ASP.NET Web Form开发应用程序,Web Form在这种情况下,数据是自动保留的。下面的内容将很快演示如何用MVC取得同样的效果。
为了接收并处理表单所递交的数据,本书打算做一件聪明的事情。添加第二个RsvpForm动作方法,以形成如下作用。

一个方法用于响应HTTP的GET请求:GET请求是某人点击一个链接时浏览器正常发出的请求。当有人第一次访问/Home/RsvpForm时,这个动作版本负责显示最初的空白表单。

一个方法用于响应HTTP的POST请求:默认情况下,用Html.BeginForm()渲染的表单是由浏览器作为一个POST请求递交的。这个动作版本负责接收所递交的数据,并决定用它做什么。

以独立的C#方法分别处理GET和POST请求,有助于保持代码整洁,因为这两种方法有不同的职责。两种方法都由同样的URL进行调用,但MVC确保会根据用户处理的是GET请求,还是POST请求,来调用合适的方法。清单2-13显示了需要对HomeController类所进行的修改。

清单2-13 添加一个支持POST请求的动作方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
**using PartyInvites.Models;**
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();
        }
[HttpGet]
        public ViewResult RsvpForm() {
            return View();
        }
 [HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse) {
// TODO: 对晚会的组织者发送Email响应
return View("Thanks", guestResponse);
}
    }
}

此时,已经把HttpGet注解属性加到了现在的RsvpForm动作方法上。这告诉MVC,这个方法应该仅用于GET请求。然后添加了一个重载的RsvpForm方法,它带有一个GuestResponse参数,并运用了HttpPost注解属性。该注解属性告诉MVC,这个新方法将处理POST请求。注意,这里已经引入了PartyInvites.Models命名空间。这样,可以直接使用GuestResponse模型类型,而不需要使用这个类的限定名。在以下几节中,本书将解释对该清单所做的添加是如何工作的。

注:本书涉及一些不同含义的“属性”,这些属性在英文中有些称为Property,有些则称为Attribute,但中文均应当把它们称为属性。为了对这些属性加以区别,本书在翻译文字中对这些属性采用了相应的专门术语:① 把类或对象的Property称为属性;② 把[HttpGet]这样的Attribute称为注解属性(Annotation Attribute),注解属性有很多种,除这里的[HttpGet]和[HttpPost]外,本章稍后介绍的验证规则也是一种注解属性;③ 把HTML元素的Attributes称为标签属性(Attributes of HTML Tags),如<input id= "Phone" name="Phone" type="text" value="" />,其中id、name、type、value都称为标签属性——译者注
1.使用模型绑定
RsvpForm动作方法的第一个重载渲染和前面同样的视图,它生成图3-16所示的表单。第二个重载由于其参数变得更为有趣,但已给定该动作方法是响应HTTP的POST请求而被调用的,也已给定GuestResponse类型是一个C#类,那么,这两者是如何连接的呢?

答案是模型绑定(Model Binding),这是一个非常有用的MVC特性,凭借它可以解析输入数据,并用“键/值”对填充域模型类型的属性。这一过程与使用HTML辅助器方法是相反的。即,当创建发送给客户端的表单数据时,(HTML辅助器方法)生成了HTML的input元素,其中id和name标签属性的值来自于模型类的属性名。

与此相反,通过模型绑定,会用input元素名来设置模型类实例中属性的值(其实这句话说得不完全正确,应当是用input的元素名和值来设置模型类实例中的属性值,以便通过用户在表单的各个input元素中输入的值来构造一个模型类实例——译者注),然后该实例被传递给处理POST的动作方法(简单地说,辅助器的作用是用模型类的数据来创建HTML元素,而模型绑定是用表单中输入的数据创建模型对象。所以说,模型绑定与辅助器方法的作用是相反的——译者注)。

模型绑定是一个功能强大且可定制的特性,它消除了处理HTTP请求的烦琐,使开发者能够用C#对象进行工作,而不是处理Request.Form[]和Request.QuertyString[]的值。作为参数被传递给动作方法的GuestResponse对象自动地被填充了表单字段的数据。第22章将深入研究模型绑定,包括如何对它进行定制的细节。

2.渲染其他视图
RsvpForm动作方法的第二个重载也演示了如何才能告诉MVC去渲染一个对请求进行响应的特定视图。以下是相关语句。

return View("Thanks", guestResponse);
这个对View方法的调用告诉MVC,查找并渲染一个名为“Thanks”的视图,并把GuestResponse对象传递给这个视图。为了创建所指定的这个视图,右击HomeController中的一个方法,从弹出菜单中选择“添加视图”,将视图名设置为Thanks,如图2-17所示。


a7b82e14fe9b8b0cf84f9d1516f73bc905ddf94a

由于打算创建另一个强类型视图,因此,在“Add View(添加视图)”对话框中选中“Create a strongly-typed view(创建强类型视图)”复选框。为这个视图所选择的数据类必须与用View方法传递给这个视图的类相对应,故从下拉列表中选择GuestResponse。确保“Use a layout or master page(使用布局或母版页)”复选框未选中,“View engine(视图引擎)”设置为Razor。

点击“Add(添加)”按钮,创建这个新视图。因为该视图是与Home控制器相关联的,故MVC会将此视图创建为~/Views/Home/thanks.cshtml。编辑此新视图,使之与清单2-14匹配——本书已高亮了需要添加的标记。

清单2-14 Thanks视图


96b8d27e42c4e3ebeb04d99f34fa43dbdbc6c561

该Thanks视图使用Razor并根据GuestResponse属性的值来显示内容,GuestResponse是在RsvpForm动作方法中传递给View方法的。Razor的@model操作符指示了这个强类型视图的域模型类型。为了访问这个域对象中某个属性的值,要使用Model.PropertyName(即Model.<属性名>——译者注)。例如,要获得Name属性的值,调用Model.Name。如果对Razor语法尚不了解,不用担心——本书将在第5章解释Razor。

既然已经创建了Thanks视图,便有了一个以MVC处理表单的简单运行示例。

在Visual Studio中启动该应用程序,点击“RSVP Now(现在回复)”链接,对表单添加一些数据,然后点击“Submit RSVP(递交回复)”按钮。读者将看到图2-18所示的结果(如果姓名不是Joe,并且表明不出席,显示会有所不同)。


0fad7fe1a8b873c48f4c03b67ed702515da72e55

2.4.6 添加验证

现在,到了对应用程序添加验证的时候了。如果不做此事,用户可能会输入无意义的数据,甚至递交一个空白表单。

在MVC应用程序中,验证典型地运用于域模型而不是用户界面。这意味着,在一个地方定义验证条件,会在运用模型类的任何地方生效。ASP.NET MVC支持验证规则声明,验证规则是以System.ComponentModel.DataAnnotations命名空间中的注解属性进行定义的。清单2-15演示了如何把这些注解属性运用于GuestResponse模型类。

清单2-15 对GuestResponse模型类运用验证

using System.ComponentModel.DataAnnotations;
namespace PartyInvites.Models {
    public class GuestResponse {
[Required(ErrorMessage = "Please enter your name")]
        public string Name { get; set; }
[Required(ErrorMessage = "Please enter your email address")]
[RegularExpression(".+\\@.+\\..+",
ErrorMessage = "Please enter a valid email address")]
        public string Email { get; set; }
[Required(ErrorMessage = "Please enter your phone number")]
        public string Phone { get; set; }
[Required(ErrorMessage = "Please specify whether you'll attend")]
        public bool? WillAttend { get; set; }
    }
}

验证规则显示为黑体。MVC会侦测这些验证注解属性,并在模型绑定过程中用它们来验证数据。注意,这个清单已经引入了含有验证的命名空间,因此不需要用限定名来引用它们。

提示:正如之前说明的,本书对WillAttend属性使用了一个可空的(nullable)bool型。这样做是为了可以运用Required验证注解属性。如果使用一个常规的bool型,那么,通过模型绑定所接收的值只能是true或false,但不能判断用户是否已选择了一个值。一个可空的bool型有三个可能的值:true、false和null。如果用户尚未选择,系统会默认用null来表示,这会让Required注解属性能够报告一个验证错误。
读者可以在控制器类中用ModelState.IsValid属性来检查是否有验证问题。清单2-16演示了在处理POST的RsvpForm动作方法中,如何运用ModelState.IsValid。

清单2-16 检查表单验证错误

...
[HttpPost]
public ViewResult RsvpForm(GuestResponse guestResponse) {
if (ModelState.IsValid) {
        // TODO: 给晚会的组织者发送电子邮件
        return View("Thanks", guestResponse);
} else {
// 有验证错误
return View();
}
}
...

如果没有验证错误,便告诉MVC渲染Thanks视图,这就像先前所做的那样。如果有验证错误,则通过调用不带参数的View方法,来重新渲染RsvpForm视图。

在有错误时仅显示表单并不十分有用——需要给用户提供一些指示,告诉他们有什么问题以及为什么不能接受表单递交。通过在RsvpForm视图中使用Html.ValidationSummary(验证摘要)辅助器方法可以完成这种工作,如清单2-17所示。

清单2-17 使用Html.ValidationSummary辅助器方法


7fe8a5385b8671ba6e7dcfc6a46490ba9f312c06

如果没有错误,这个Html.ValidationSummary方法会在表单中创建一个隐藏的列表条目占位符;否则,MVC会使这个占位符成为可见,并添加由验证注解属性所定义的错误消息。读者可以在图2-19中看到这是如何显示的。


ff1e6b9f2020eb5e4c03d5b1e0b3141d12fa6302

直到运用于GuestResponse类的所有验证约束都得到满足,用户才会看到Thanks视图。注意,在表单中输入的数据是被保留的,并且,当带有验证摘要的视图被重新渲染时,这些数据会再次显示出来。这是通过模型绑定所得到的另一个好处。

注:曾经用过ASP.NET Web Form的读者,应该知道Web Form有一种“服务器控件”的概念。服务器控件通过把值序列化到一个叫作“__VIESTATE”的隐藏字段来保持状态。ASP.NET MVC模型绑定与Web Form的服务器控件、回递或视图状态等概念无关。ASP.NET MVC不会把隐含字段__VIEWSTATE注入到渲染的HTML页面中。
高亮无效字段
创建文本框、下拉列表,以及其他元素的HTML辅助器方法有一个十分灵活的特性,可以用来与模型绑定相关联。保留用户在表单中的输入数据的同样机制,也可以用来高亮验证检查失败的个别字段。

当模型类属性验证失败时,HTML辅助器方法可以生成稍有不同的HTML。例如,以下是Html.TextBoxFor(x => x.Name)在没有验证错误时生成的HTML。

<input data-val="true" data-val-required="Please enter your name" id="Name" name="Name"
type="text" value="" />
而当用户未提供一个值时(这是一个验证错误,因为对GuestResponse模型类中的Name属性运用了Required注解属性),以下是同样的调用所生成的HTML。

<input class="input-validation-error"** data-val="true" data-val-required="Please enter yourname" id="Name" name="Name" type="text" value="" />
上述代码已经以黑体高亮了其差异。辅助器方法添加了一个值为“input-validation-error”的class标签属性。通过创建样式表可以利用这一特性,该样式表可以为这个class以及其他HTML辅助器方法所生成的class设置一些不同的CSS样式(这样就可以对不同的class值设置一些不同的显示效果——译者注)。

MVC项目的约定是,静态内容(如CSS样式表等)要放入名为Content的文件夹中。在“Solution explorer(解决方案资源管理器)”中右击“PartyInvites”项目,从弹出菜单中选择“Add(添加)”→“New Folder(新文件夹)”,便可以创建Content文件夹。右击“Content”,选择“Add(添加)”→“New Item(新项)”,在“Add New Item(添加新项)”对话框中选取“Style Sheet(样式表)”,便可创建样式表。将样式表取名为Site.css,这是使用一个MVC模板但不是Empty创建项目时,Visual Studio会自动创建的一个网站样式表文件。读者可以在清单2-18中看到Content/Site.css文件的内容(该清单的内容需要读者输入或粘贴进去,并非是自动生成的——译者注)。

清单2-18 Content/Site.css文件的内容

.field-validation-error   {color: #f00;} 
.field-validation-valid   {display: none;}
.input-validation-error   {border: 1px solid #f00; background-color: #fee;}
.validation-summary-errors  {font-weight: bold; color: #f00;}
.validation-summary-valid   {display: none;}

为了使用该样式表,可以在RsvpForm视图的头部(

元素中——译者注)添加一个新的引用,如清单2-19所示。给视图添加link元素就像常规的静态HTML文件。

清单2-19 对RsvpForm视图添加链接元素


4eb3d6c6217e8d3d69d9e9358205a69bce73f7bb

提示:曾用过MVC 3的读者可能会料想到,本书会将href标签属性指定为@Href("~/Content/Site.css"),或@Url.Content("~/Content/Site.css"),使CSS文件添加到视图。但对于MVC 4,Razor自动地检测以~/开始的标签属性,并自动插入@Href或者@Url调用。
现在,当递交会引发验证错误的数据时,会显示更明显的验证错误,如图2-20所示。


59d47b5a2535381fdda4099ed96733e3886defc5

2.4.7 完成示例

这个示例应用程序的最后需求是,将完成了的RSVP用电子邮件发给邀请的宾客和晚会的组织者。可以添加一个动作方法,使用.NET框架的E-mail类来创建并发送一份邮件消息,以完成这一任务。但在这里,本书打算使用WebMail辅助器方法。这不是MVC框架的一部分,但它确实能完成这个例子,而不必建立另一个发送邮件的表单。

注:这里使用WebMail辅助器方法,是因为它可以轻松地演示发送一份邮件消息。然而,人们通常更喜欢把这个功能放在一个动作方法中。第3章将在描述MVC体系结构模式时,对此进行解释。
此处希望在渲染Thanks视图时发送这份邮件消息。清单2-20显示了需要进行的修改。

清单2-20 使用WebMail辅助器


1964f4cb9c8cd517f5a67ef0af48f833fbd20ab7

清单2-16添加了一段Razor代码块,它用WebMail辅助器来配置邮件服务器的细节,包括服务器名、服务器是否需要SSL连接,以及账号细节。一旦配置了所有这些细节,就可以用WebMail.Send方法来发送这封邮件了。

将所有关于e-mail的代码都封装在一个try...catch块中,于是,如果不能发送邮件,则可以向用户发出警告。做这件事的办法是,把一个文本块添加到Thanks视图的输出。一个更好的办法是,当不能发送邮件消息时,显示一个独立的错误视图,但这里希望这第一个MVC应用程序尽量简单。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

相关文章
|
9月前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
380 10
|
3月前
|
JSON 数据格式
【Azure Fabric Service】演示使用PowerShell命令部署SF应用程序(.NET)
本文详细介绍了在中国区微软云Azure上使用Service Fabrics服务时,通过PowerShell命令发布.NET应用的全过程。由于Visual Studio 2022无法直接发布应用,需借助PowerShell脚本完成部署。文章分三步讲解:首先在Visual Studio 2022中打包应用部署包,其次连接SF集群并上传部署包,最后注册应用类型、创建实例并启动服务。过程中涉及关键参数如服务器证书指纹和服务端证书指纹的获取,并附带图文说明,便于操作。参考官方文档,帮助用户成功部署并运行服务。
152 72
|
5月前
|
C# Android开发 iOS开发
2025年全面的.NET跨平台应用框架推荐
2025年全面的.NET跨平台应用框架推荐
204 23
|
7月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
114 5
|
7月前
|
JSON 算法 安全
JWT Bearer 认证在 .NET Core 中的应用
【10月更文挑战第30天】JWT(JSON Web Token)是一种开放标准,用于在各方之间安全传输信息。它由头部、载荷和签名三部分组成,用于在用户和服务器之间传递声明。JWT Bearer 认证是一种基于令牌的认证方式,客户端在请求头中包含 JWT 令牌,服务器验证令牌的有效性后授权用户访问资源。在 .NET Core 中,通过安装 `Microsoft.AspNetCore.Authentication.JwtBearer` 包并配置认证服务,可以实现 JWT Bearer 认证。具体步骤包括安装 NuGet 包、配置认证服务、启用认证中间件、生成 JWT 令牌以及在控制器中使用认证信息
287 2
|
8月前
|
SQL XML 关系型数据库
入门指南:利用NHibernate简化.NET应用程序的数据访问
【10月更文挑战第13天】NHibernate是一个面向.NET的开源对象关系映射(ORM)工具,它提供了从数据库表到应用程序中的对象之间的映射。通过使用NHibernate,开发者可以专注于业务逻辑和领域模型的设计,而无需直接编写复杂的SQL语句来处理数据持久化问题。NHibernate支持多种数据库,并且具有高度的灵活性和可扩展性。
121 2
|
8月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
160 9
|
9月前
|
数据采集 JSON API
.NET 3.5 中 HttpWebRequest 的核心用法及应用
【9月更文挑战第7天】在.NET 3.5环境下,HttpWebRequest 类是处理HTTP请求的一个核心组件,它封装了HTTP协议的细节,使得开发者可以方便地发送HTTP请求并接收响应。本文将详细介绍HttpWebRequest的核心用法及其实战应用。
368 6
|
9月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
158 7
|
10月前
|
前端开发 JavaScript 开发工具
跨域联姻:React.NET——.NET应用与React的完美融合,解锁前后端高效协作新姿势。
【8月更文挑战第28天】探索React.NET,这是将热门前端框架React与强大的.NET后端无缝集成的创新方案。React以其组件化和虚拟DOM技术著称,能构建高性能、可维护的用户界面;.NET则擅长企业级应用开发。React.NET作为桥梁,使.NET应用轻松采用React构建前端,并优化开发流程与性能。通过直接托管React组件,.NET应用简化了部署流程,同时支持服务器端渲染(SSR),提升首屏加载速度与SEO优化。
306 1