第一个 MVC 应用程序(下半部分)
2.4 创建一个简单的数据录入应用程序
本章的其余部分将通过一个简单的数据录入应用程序来考查 MVC 的更多基本特性。本小节打算分步进行,目的是演示 MVC 的运用。
B1、设计一个数据模型
在 MVC 中,M 代表模型(Model),它是应用程序最重要的部分。
模型是定义应用程序主题的现实对象、过程以及规则的表示,称为域。
模型,通常称为域模型,包含应用程序域中要建立的 C#对象,称为域对象。这些域对象构成了应用程序的全部事物以及操纵这些
对象的方法。
视图和控制器以一致的方式将域暴露给客户端。
一个设计良好的 MVC 应用程序,必须从设计良好的模型开始,它是随后添加控制器和视图的焦点。
(对于 “晚会邀请”应用程序,不需要复杂的模型。因为这是一个简单的应用程序,只需要创建一个域类(可以称为 GuestResponse),由它负责存储、验证并确认“回复邀请”)
添加模型类
MVC 的约定是将建立模型的类放在 “Models”文件夹中,该文件夹是 Visual Studio 最初建立项目时创建的。
1、右击 “Models”文件夹——“添加”——“类”
2、将文件名设置为 “GuestResponse.cs”
3、单击“添加”按钮。(创建完成后修改文件内容——为模型对象类添加属性)
(可以通过问号“?” 将 “int”、“bool” 等类型的属性设置为可空的类型)
B2、★ 链接动作方法
该应用程序的目标之一是要包括一个回复邀请的表单,因此需要在 Index.cshtml 视图中添加一个指向它(动作方法)的链接。
……
@Html.ActionLink("现在回复", "RsvpForm")
……
Html.ActionLink 是一个 HTML 的辅助器方法(Helper Method)
MVC 框架附带了一组内置的辅助器方法,它们可以方便地用来渲染 HTML 的链接、文本输入框、复选框 以及其他种类的内容。
这个 ActionLink 方法有两个参数:第一个是该链接的显示文本,第二个是用户单击该链接时将要执行的动作。
(第21~23章将解释完整的 HTML 辅助器方法集合)
Html.ActionLink 方法已经检测了应用程序的 URL 路由配置,并得出 /Home/RsvpForm 是一个指向 HomeController 控制器
上 RsvpForm 动作的 URL。
(与传统的 ASP.NET 应用程序不同,MVC 的 URL 并不对应物理文件。每个动作方法有它自己的 URL,而 MVC 使用 ASP.NET
的路由系统将这些 URL 转换成动作)
创建动作方法:
此时,可以在 HomeController 类中添加一个名称为 “RsvpForm” 的方法来完成这一工作。
public ViewResult RsvpForm()
{
return View();
}
添加强类型视图:
这里打算为 RsvpForm 动作方法添加一个视图,但采取了稍有不同的方式——创建一个强类型视图。
强类型视图意在渲染一个特定的域类型,而且,如果指定了想使用的类型(本例是 GuestResponse),MVC 将能够提供一些
便于使用这个类型的便捷方法,从而可以在视图中方便地使用这个类型对象。
(在做进一步工作之前,要确保已编译了 MVC 项目。如果已经创建了 GuestResponse 类,但未进行编译,MVC 将不能为这个
类型创建强类型视图。 要编译应用程序,可以 “生成”——“生成解决方案”,或简单地按快捷键 F6)
1、在代码编辑器中右击 ResvForm 方法,然后选择 “添加视图”
2、确保将 “视图名”设置为 “ResvForm”,将“模板”设置为 “空模板”,并从“类模板”字段的下拉列表中
选择“GuestResponse(PartyInvites.Models)”,让(视图)选项中的复选框处于未选状态。
3、单击 “添加”按钮。(这是另一种结构的 HTML 文件,它包含了一个 @model 的 Razor 表达式。过一会儿就会明白,这是
强类型视图,并是为视图提供便利的关键——@model PartyInvites.Models.GuestResponse)
(在创建视图时,所选择和勾选的选项决定了视图文件的初始内容(跟别的文件没有关系),其他没什么作用。例如,
你可以将常规视图修改成强类型视图,只需在代码编辑器中添加或去除 @model 指示符 即可)
B3、建立表单
现在已经创建了强类型视图,可以扩建这个 RsvpForm.cshtml 的内容(在 RsvpForm.cshtml 文件中创建表单视图)
@using (Html.BeginForm())
{
<p>姓名:@Html.TextBoxFor(x=>x.Name) </p>
<p>邮箱:@Html.TextBoxFor(x=>x.Email) </p>
<p>手机:@Html.TextBoxFor(x=>x.Phone) </p>
<p>是否参加?@Html.DropDownListFor(x=>x.WillAttend, new[ ] {
new SelectListItem() { Text="是,我参加", value=bool.TrueString },
new SelectListItem() { Text="否,不参加", value=bool.FalseString }
}, “请选择”)
</p>
<input type="submit" value="回复邀请" />
}
这里对 GuestResponse 模型类的每一个属性都使用了一个 HTML 辅助器方法,以便渲染一个适当的 HTML 的 input 控件。
这些辅助器方法都能够用一个 lambda 表达式来选择与 input 元素有关的属性。(如:@Html.TextBoxFor(x=>x.Phone))
这个 TextBoxFor 辅助器方法会生成一个 input 元素的 HTML,将该元素的 type 参数设置为“text”,id 和 name 标签属性设置
为“Phone”,Phone 是所选域类的属性名。于是为模型属性 Phone 生成了一个文本输入框的 HTML 标记,如下所示:
<input id="Phone" name="Phone" type="text" value="" />
这种灵活的特性是能够起作用的,因为 RsvpForm 视图是强类型的,而且已经告诉 MVC,GuestResponse 是希望用该视图
渲染的类型。——这为 HTML 辅助器方法提供了所需的信息,使其能够理解从 @mldel 表达式所读取的属性是哪一种数据类型。
替代运用 lambda 表达式的另一种方法是将模型类型的属性名指定为一个字符串,如:@Html.TextBox("Email")
另一个便利的辅助器方法是 Html.BeginForm,它生成一个回递给动作方法的 HTML 表单元素(<form>元素)
这里未给辅助器方法传递任何参数,于是它假设要回递的目标是请求此 HTML 文档的同一个 URL。
一个整洁的技巧是将它封装在一个 C# 的 using 语句中,如:@using (Html.BeginForm()) { }。
正常情况下,像这样运用 using 语句,会在对象超出范围时确保收回对象所占用的资源。例如,它通常用于数据库连接。
但这里并不是清理对象,而是 Html.BeginForm 辅助器在它超出范围时关闭 HTML 的 form 元素。——这意味着,
Html.BeginForm 辅助器方法会创建 form 元素的两部分(<form>元素的开标签和闭标签),如下所示:
<form action="/Home/RsvpForm" method="post">
…这里是表单内容…
</form>
这里的关键是演示如何用 HTML 辅助器方法创建一个表单。
B4、处理表单
这里尚未告诉 MVC,将表单递交给服务器时要做什么。(此时,单击“恢复邀请”按钮只会清除掉表单中已经输入的值。这是因为
该表单会回递给 Home 控制器中的 RsvpForm 动作方法,这只是告诉 MVC 再次渲染该视图——视图被再次渲染时,输入的数据会消失)
为了接收并处理表单所递交的数据,这里打算使用一个聪明的特性——添加第二个 RsvpForm 动作方法,以形成如下作用:
一种方法用于响应 HTTP 的 GET 请求:GET 请求是某人单击一个链接时,浏览器正常发出的请求。当有人第一次访问/Home
/RsvpForm 时,这个动作负责显示最初的空白表单。
一种方法用于响应 HTTP 的 POST 请求:默认情况下,用 Html.BeginForm() 渲染的表单是由浏览器作为一个 POST 请求
递交的。这个动作负责接收所递交的数据,并决定用它做什么。
以独立的 C#方法分别处理 GET 和 POST 请求,有助于保持控制器代码整洁,因为这两种方法有不同的职责。
这两种方法都由相同的 URL 进行调用,但 MVC 确保会根据所处理的是 GET 请求或 POST 请求,来调用合适的方法。
在 HomeController.cs 文件中添加一个支持 POST 请求的动作方法:
……
using PartyInvites.Models;
……
[ HttpGet ]
public ViewResult RsvpForm() { return View(); }
[ HttpPost ]
public ViewResult RsvpForm(GuestResponse gr)
{
return View("Thanks", gr);
}
这里在已有的 RsvpForm 动作方法上添加了 HttpGet 注解属性。这是告诉 MVC,该方法应该仅用于 GET 请求。
然后添加了一个重载版的 RsvpForm 方法,它带有一个 GuestResponse 参数,并运用了 HttpPost 注解属性。(该注解属性告诉 MVC ,这个新方法将处理 POST 请求)
这里已经引入了 PartyInvites.Models 命名空间,这样便可以直接使用 GuestResponse 模型类型,而不需要使用这个类的限定名。
B5、添加验证
验证是为了防止用户输入无意义的数据,甚至是递交空白的表单。
在 MVC 应用程序中,验证典型地运用于域模型,而不是用户界面。这意味着可以在一个地方(模型类中)定义验证条件,而在运用模型类的任何地方生效。
ASP.NET MVC 支持验证规则声明,这是以 System.ComponentModel.DataAnnotations 命名空间中的注解属性进行定义的 —— 意即,验证约束是使用标准的 C# 注解属性特性来表示的。
如下演示如何将这些注解属性运用于 GuestResponse 模型类:
using System.ComponentModel.DataAnnotation;
[ Required( ErrorMessage = "Please enter your name" )] // 意思是运用 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; }
MVC 会自动地侦测这些验证注解属性,并在模型绑定过程中将它们用于验证数据。
一个可空的 bool 型(bool?)有3个可能的值:true、false 和 null。 如果用户尚未选择,系统会默认用 null 来表示,这会让 Required 注解属性能够报告一个验证错误。这是 MVC 框架如何优雅地将 C# 特性与 HTML 和 HTTP 相融合的一个很好的示例。
可以在控制器中使用 ModelState.IsValid 属性来检查是否有验证问题。(如下所示,在 HOME 控制器类的启用 POST 的 RsvpForm 动作方法中的实现)
[ HttpPost ]
public ViewResult RsvpForm( GuestResponse guestResponse)
{
if( ModelState.IsValid)
{
return View("Thanks", guestResponse) ; // 第一个参数是视图名
}
else
return View() ;
}
如果没有验证错误,便让 MVC 渲染 Thanks 视图。 如果有验证错误,则通过调用不带参数的 View 方法重新渲染 RsvpForm 视图。
在有错误时,仅显示表单并不十分有用,还需要给用户提供一些指示,告诉他们有什么问题,以及为什么不能接受他们所递交的表单。其实现办法是在 RsvpForm 视图中使用 Html.ValidationSummary(验证摘要)辅助器方法。
注意,在表单中输入的数据是被保留的,而且在带有验证摘要的视图被重新渲染时,这些数据会被再次显示出来。这是模型绑定特性的另一个好处,它简化了表单数据的工作。
高亮显示无效字段:
当模型类的某个属性验证失败时(前提是对应的属性运用了 Required 注解属性),HTML 辅助器方法会生成稍有不同的 HTML(在 input 标签内产生了一个值为 "input-validation-error" 的 class 标签属性)——通过创建样式表便可以利用这一特性,该样式表可以为这个 class 以及其他 HTML 辅助器方法所生成的 class 设置一些不同的 CSS 样式(这样就可以对不同的 class 值设置一些不同的显示效果)
MVC 项目的约定是:将静态内容(如 CSS 样式表等)放在名称为 Content 的文件夹中(可能要自己新建)
第一个 MVC 应用程序(下半部分)的更多相关文章
- 【MVC 4】1.第一个 MVC 应用程序
作者:[美]Adam Freeman 来源:<精通ASP.NET MVC 4> ASP.NET MVC 是微软的一个 Web开发框架,它整合了“模型—视图—控制器(MVC)”架构 ...
- 创建第一个MVC应用程序
整个国庆期假,Insus.NET没有出门,在家静心修炼MVC.这意味着Insus.NET将来的日子里会以MVC为学习,开发,应用作为重点,不过现在才开始踏出第一步...... 路慢慢...... 下载 ...
- 第一个 MVC 应用程序(上半部分)(《精通 ASP.NET MVC5》 的第二章)
本章将使用 ASP.NET MVC 框架创建一个简单的数据录入应用程序. 笔者会将过程分解成一个个的步骤,以便能够看出如何构造 ASP.NET MVC 应用程序.(对于一些未进行解释的内容,笔者提供了 ...
- 《精通ASP.NET MVC5》第2章 第一个MVC应用程序
控制器 public class NewHomeController : Controller { // GET: /NewHome/ public ...
- 跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)
作者:陈希章 发表于 2017年6月25日 谈一谈.NET 的跨平台 终于要写到这一篇了.跨平台的支持可以说是 Office 365 平台在设计伊始就考虑的目标.我在前面的文章已经提到过了,Micro ...
- 将最小的OWIN身份验证添加到现有的ASP.NET MVC应用程序
https://weblog.west-wind.com/posts/2015/Apr/29/Adding-minimal-OWIN-Identity-Authentication-to-an-Exi ...
- Entity Framework Core系列之实战(ASP.NET Core MVC应用程序)
本示例演示在ASP.NET 应用程序中使用EF CORE创建数据库并对其做基本的增删改查操作.当然我们默认你的机器上已经安装了.NET CORE SDK以及合适的IDE.本例使用的是Visual St ...
- MVC应用程序使用Entity Framework
创建空的MVC应用程序,为了想使用Entity Framework的类库,发现即无法正常引用.如下图,Insus.NET已经明确引了System.Data.Entity(下图Highlight的代码) ...
- ASP.NET + MVC5 入门完整教程三 (上) ---第一个MVC项目
https://blog.csdn.net/qq_21419015/article/details/80420815 第一个MVC应用程序 1创建MVC项目 打开VS ,File--新建--项目,选择 ...
随机推荐
- MySQL数据库----IDE工具介绍及数据备份
一.IDE工具介绍 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具 下载链接:https://pan.baidu.com/s/1bpo5mqj 二.MySQL数据备份 # ...
- 联合体union的详解
1.概述 联合体union的定义方式与结构体一样,但是二者有根本区别. 在结构中各成员有各自的内存空间,一个结构变量的总长度是各成员长度之和.而在“联合”中,各成员共享一段内存空间,一个联合变量的长度 ...
- 冒泡排序法原理讲解及PHP代码示例
冒泡排序原理 冒泡排序对一个数组里的数字进行排序,把数组里两个相邻的数比较大小,将值小的数放在前面,把大的数往后面放,当然这种排序是升序,即从小到大.举例说明$array = [64, 56, 31, ...
- Js删除字符串中的指定字符串
案例一. 比如:原字符串 var StringFirst = "12:30:08"; 现在要删掉冒号,变成123008 就可以先split var splitFirst = Str ...
- Js中String转int
Js中String转int 方案一代码: Number(str) 方案二代码: //parseInt 方法都有两个参数, 第一个参数就是要转换的对象, 第二个参数是进制基数, 可以是 2, 8, 10 ...
- 用Nodejs连接MySQL(原文链接)
原文链接:http://blog.fens.me/nodejs-mysql-intro/
- 20145101《Java程序设计》第三周学习总结
20145101 <Java程序设计>第3周学习总结 教材学习内容总结 本周进行的是第四章和第五章的学习.本阶段的学习难度有所提升,无论是在知识的量还是深度都开始增加,内容很丰富,也很有趣 ...
- 20145315《网络对抗》——注入shellcode以及 Return-to-libc攻击实验
shellcode 准备一段Shellcode 我用的老师的shellcode:\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3 ...
- 关于STM32 MDK中USE_STDPERIPH_DRIVER问题的解释
初学STM32,在RealView MDK 环境中使用STM32固件库建立工程时,初学者可能会遇到编译不通过的问题.出现如下警告或错误提示: warning: #223-D: function &qu ...
- USACO 1.3 Wormholes - 搜索
Wormholes Farmer John's hobby of conducting high-energy physics experiments on weekends has backfire ...