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 应用程序(下半部分)的更多相关文章

  1. 【MVC 4】1.第一个 MVC 应用程序

    作者:[美]Adam Freeman      来源:<精通ASP.NET MVC 4> ASP.NET MVC 是微软的一个 Web开发框架,它整合了“模型—视图—控制器(MVC)”架构 ...

  2. 创建第一个MVC应用程序

    整个国庆期假,Insus.NET没有出门,在家静心修炼MVC.这意味着Insus.NET将来的日子里会以MVC为学习,开发,应用作为重点,不过现在才开始踏出第一步...... 路慢慢...... 下载 ...

  3. 第一个 MVC 应用程序(上半部分)(《精通 ASP.NET MVC5》 的第二章)

    本章将使用 ASP.NET MVC 框架创建一个简单的数据录入应用程序. 笔者会将过程分解成一个个的步骤,以便能够看出如何构造 ASP.NET MVC 应用程序.(对于一些未进行解释的内容,笔者提供了 ...

  4. 《精通ASP.NET MVC5》第2章 第一个MVC应用程序

      控制器     public class NewHomeController : Controller     {         // GET: /NewHome/         public ...

  5. 跨平台应用集成(在ASP.NET Core MVC 应用程序中集成 Microsoft Graph)

    作者:陈希章 发表于 2017年6月25日 谈一谈.NET 的跨平台 终于要写到这一篇了.跨平台的支持可以说是 Office 365 平台在设计伊始就考虑的目标.我在前面的文章已经提到过了,Micro ...

  6. 将最小的OWIN身份验证添加到现有的ASP.NET MVC应用程序

    https://weblog.west-wind.com/posts/2015/Apr/29/Adding-minimal-OWIN-Identity-Authentication-to-an-Exi ...

  7. Entity Framework Core系列之实战(ASP.NET Core MVC应用程序)

    本示例演示在ASP.NET 应用程序中使用EF CORE创建数据库并对其做基本的增删改查操作.当然我们默认你的机器上已经安装了.NET CORE SDK以及合适的IDE.本例使用的是Visual St ...

  8. MVC应用程序使用Entity Framework

    创建空的MVC应用程序,为了想使用Entity Framework的类库,发现即无法正常引用.如下图,Insus.NET已经明确引了System.Data.Entity(下图Highlight的代码) ...

  9. ASP.NET + MVC5 入门完整教程三 (上) ---第一个MVC项目

    https://blog.csdn.net/qq_21419015/article/details/80420815 第一个MVC应用程序 1创建MVC项目 打开VS ,File--新建--项目,选择 ...

随机推荐

  1. MySQL数据库----IDE工具介绍及数据备份

    一.IDE工具介绍 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具 下载链接:https://pan.baidu.com/s/1bpo5mqj 二.MySQL数据备份 # ...

  2. 联合体union的详解

    1.概述 联合体union的定义方式与结构体一样,但是二者有根本区别. 在结构中各成员有各自的内存空间,一个结构变量的总长度是各成员长度之和.而在“联合”中,各成员共享一段内存空间,一个联合变量的长度 ...

  3. 冒泡排序法原理讲解及PHP代码示例

    冒泡排序原理 冒泡排序对一个数组里的数字进行排序,把数组里两个相邻的数比较大小,将值小的数放在前面,把大的数往后面放,当然这种排序是升序,即从小到大.举例说明$array = [64, 56, 31, ...

  4. Js删除字符串中的指定字符串

    案例一. 比如:原字符串 var StringFirst = "12:30:08"; 现在要删掉冒号,变成123008 就可以先split var splitFirst = Str ...

  5. Js中String转int

    Js中String转int 方案一代码: Number(str) 方案二代码: //parseInt 方法都有两个参数, 第一个参数就是要转换的对象, 第二个参数是进制基数, 可以是 2, 8, 10 ...

  6. 用Nodejs连接MySQL(原文链接)

    原文链接:http://blog.fens.me/nodejs-mysql-intro/

  7. 20145101《Java程序设计》第三周学习总结

    20145101 <Java程序设计>第3周学习总结 教材学习内容总结 本周进行的是第四章和第五章的学习.本阶段的学习难度有所提升,无论是在知识的量还是深度都开始增加,内容很丰富,也很有趣 ...

  8. 20145315《网络对抗》——注入shellcode以及 Return-to-libc攻击实验

    shellcode 准备一段Shellcode 我用的老师的shellcode:\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3 ...

  9. 关于STM32 MDK中USE_STDPERIPH_DRIVER问题的解释

    初学STM32,在RealView MDK 环境中使用STM32固件库建立工程时,初学者可能会遇到编译不通过的问题.出现如下警告或错误提示: warning: #223-D: function &qu ...

  10. USACO 1.3 Wormholes - 搜索

    Wormholes Farmer John's hobby of conducting high-energy physics experiments on weekends has backfire ...