上一课我们已经能够做出简单的HTML显示页面,并懂得了MVC的工作模式,这一课我们讲解一些动态的数据交互。

在MVC中,控制器的工作是构造某些数据,而视图的工作是把它渲染成HTML。数据是从控制器传递给视图的。

把数据从控制器传递给视图的一种方式是使用ViewBag(视图包)对象,这是Controller基类的一个成员。ViewBag是一种动态对象,开发者可以给它指定任意属性,让这些属性的值在随后渲染的视图中可用。如下图所示,演示了一些简单的动态数据。

  1. using System.Web.Mvc;
  2.  
  3. namespace PartyInvites.Controllers
  4. {
  5. public class HomeController : Controller
  6. {
  7. public ViewResult Index()
  8. {
  9. int hour = DateTime.Now.Hour;
  10. ViewBag.TempVar = hour < ? "早上好!" : "下午好!";
  11. return View();
  12. }
  13. }
  14. }

我们为视图提供数据的语句以黑体显示。外了在视图中显示这个数据,需要对视图做一些修改,如下所示

@{
   Layout = null;

}

<!DOCTYPE html>

<html>

<head>

<title>Index</title>

</head>

<body>

<div>

@ViewBag.TempVar,O(∩_∩)O哈哈~(来自视图)

</div>

</body>

</html>

上面的代码中是一个Razor代码块,它接受ViewBagTempVar属性所持有的值。对属性名TempVar没有特别的要求,可以用任意自定义的属性名来代替它,它会一样工作。当然,也可以用同样的方法从控制器把多个值传递给视图。

执行这个项目可以看到如图所示的结果。我们第一个动态的MVC输出。

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

  • 设置场景

趁着要开学的节奏,咱设想某个学校发放录取通知书给新生,现在要求收到录取通知书的新生,到学校的网站上登记确认以确认收到了录取通知书。这个网站有四个特性;

  • 一个显示学校信息的主页
  • 一个可以用来进行确认已经收到录取通知书的表单
  • 表单验证,它将显示一个“谢谢你确认”的页面
  • 当完成以上动作时发送一份电子邮件告诉学校

可以利用前面的已经设计的内容,来完成上述列表中的第一项。把一些HTML添加到现在的视图上。

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <!DOCTYPE html>
  6.  
  7. <html>
  8. <head>
  9. <title>Index</title>
  10. </head>
  11. <body>
  12. <div>
  13. @ViewBag.TempVar,某某同学!
  14. <p>欢迎来到某某学校,首先恭喜您被我校录取!</p>
  15. </div>
  16. </body>
  17. </html>

更多的细节问题我们这里就暂时不考虑了。

  • 设计一个数据模型

MVC中的M代表模型,它是应用程序最重要的部分。模型是应用程序主体(称为),所定义的现实对象、过程以及规则的表示。模型,通常被称为域模型,含有应用程序中要建立的C#对象(域对象),以及操纵这些对象的方法。然后,视图和控制器以一致的方式把这个域展示给客户端。一个设计良好的MVC应用程序必须从设计良好的模型开始,它是最后我们添加控制器和视图的焦点。

对于我们PartyInvites应用程序,我们不需要一个复杂的模型,但有一个将要用到的域类,叫做StudentResponse(名字随便起)。这个对象将负责存储、验证和确认表单信息。

  • 添加模型类

MVC约定是把所建立的模型类放在~/Models文件夹内。在“解决方案资源管理器”窗口中右击“Models”,并从弹出菜单中选择“添加类”,把文件名设置为“StudentResponse.cs”,并点击“添加”按钮来创建这个类。把这个类的内容编辑为如下所示

  1. namespace PartyInvites.Models
  2. {
  3. public class StudentResponse
  4. {
  5. public string Name { get; set; }
  6. public string Mobile { get; set; }
  7. public string Email { get; set; }
  8. public bool? HavingGet { get; set; }
  9. }
  10. }
  • 链接动作方法

该应用程序的目标之一是包含一个录入表单,因此需要在Index.cshtml视图中添加一个指向它的链接,如下所示

  1. @{
  2. Layout = null;
  3. }
  4.  
  5. <!DOCTYPE html>
  6.  
  7. <html>
  8. <head>
  9. <title>Index</title>
  10. </head>
  11. <body>
  12. <div>
  13. @ViewBag.TempVar,某某同学!
  14. <p>欢迎来到某某学校,首先恭喜您被我校录取!</p>
  15. @Html.ActionLink("点击这个确认!","RsvpForm");
  16. </div>
  17. </body>
  18. </html>

Html.ActionLink 是一个HTML辅助器方法。MVC框架随带了一组内建的辅助器方法,可以很方便地用来渲染HTML的链接、文本输入框、复选框、选择甚至自定义控件等。这个ActionLink方法需要两个参数:第一个是这个链接的显示文本,第二个是当用户点击这个链接时将要执行的动作。后面我们还会学习其他的辅助器方法。你可以看到如下所示的链接

如果在浏览器中把鼠标移到这个链接上,可以看到这个链接指向。Html.ActionLink已经检测了应用程序的URL路由配置。注意,与传统ASP.NET 应用程序不同,MVC的URL并不对应于物理文件。每个动作方法有它自己的URL,而MVC使用ASP.NET的路由系统把这些URL转换成动作。

如果这时你点击这个链接你会看到一个“404-未找到”的一个错误,这是因为还没有创建于这个/Home/RsvpForm地址所对应的方法,可以把一个名为“RsvpForm”的方法添加到HomeController类,如下所示给控制器添加一个新的动作方法

  1. namespace PartyInvites.Controllers
  2. {
  3. public class HomeController : Controller
  4. {
  5. public ViewResult Index()
  6. {
  7. int hour = DateTime.Now.Hour;
  8. ViewBag.TempVar = hour < ? "早上好!" : "下午好!";
  9. return View();
  10. }
  11. public ViewResult RsvpForm()
  12. {
  13. return View();
  14. }
  15. }
  16. }

要注意,此时新添加的动作方法时没有对应的视图的,所以若此时你运行程序,会报没有找到相对应的视图的错误!

  • 添加一个强类型视图

强类型视图意在渲染一个特定的域类型,而且,如果指定了要用来进行工作的这个类型(本列是StudentResponse),MVC将能够创建便于使用这个类型的便捷手段(指MVC提供了一些辅助器方法,在视图中可以方便使用这个类型对象)

为RsvpForm动作方法添加一个视图,如下所示

点击添加按钮创建这个视图,VS打开它所创建的这个RvspForm.cshtml文件。你将看到这是一个带有Razor的@model快的Html骨架文件。正如稍后将看到的,@model快是强类型视图,是为了视图处理提供方便的关键。

  • 建立表单

  1. @model PartyInvites.Models.StudentResponse
  2. @{
  3. Layout = null;
  4. }
  5.  
  6. <!DOCTYPE html>
  7.  
  8. <html>
  9. <head>
  10. <title>RsvpForm</title>
  11. </head>
  12. <body>
  13. @using (Html.BeginForm())
  14. {
  15. <p>您的名字:@Html.TextBoxFor(m => m.Name)</p>
  16. <p>您的邮箱:@Html.TextBoxFor(m => m.Email)</p>
  17. <p>您的手机号:@Html.TextBoxFor(m => m.Mobile)</p>
  18. <p>
  19. 您已经收到录取通知书吗?
  20. @Html.DropDownListFor(m => m.HavingGet, new[]{
  21. new SelectListItem(){Text="已经收到",Value=bool.TrueString},
  22. new SelectListItem(){Text="没有收到",Value=bool.FalseString} }, "==请选择==")
  23. </p>
  24. <input type="submit" value="提交表单" />
  25. }
  26. </body>
  27. </html>

对于StudentResponse模型类的每一个属性,我们使用一个HTML辅助器方法类渲染一个适当的HTML输入控件。这些方法允许我们用lamada表达式类选择输入元素所涉及的属性,代码如下:

@Html.TextBoxFor(m=>m.Mobile)

这个HTML辅助器生成HTML的inout 元素,将其type参数设置为text,并把id和name标签属性设置为Mobile,Moibile是所选类的属性名。我们从查看源代码中可以看出

  1. <!DOCTYPE html>
  2.  
  3. <html>
  4. <head>
  5. <title>RsvpForm</title>
  6. </head>
  7. <body>
  8. <form action="/Home/RsvpForm" method="post"> <p>您的名字:<input id="Name" name="Name" type="text" value="" /></p>
  9. <p>您的邮箱:<input id="Email" name="Email" type="text" value="" /></p>
  10. <p>您的手机号:<input id="Mobile" name="Mobile" type="text" value="" /></p>
  11. <p>
  12. 您已经收到录取通知书吗?
  13. <select id="HavingGet" name="HavingGet"><option value="">==请选择==</option>
  14. <option value="True">已经收到</option>
  15. <option value="False">没有收到</option>
  16. </select>
  17. </p>
  18. <input type="submit" value="提交表单" />
  19. </form></body>
  20. </html>

这种灵活的特性会起作用,是因为RsvpForm视图是强类型的,并且我们已经告诉了MVC,用这个视图来渲染的类型是StudentResponse。

运用lamabda表达式的另一种方法时,以一个字符串来引用模型类型的属性名,像这样:

@Html.TextBox(“Enail”)

另一方便的辅助器方法时Html.BeginForm,它生成一个回递给动作方法的HTML表单元素。由于我们没给这个辅助器任何参数,于是它假设开发者想回递给同样的URL。一个整洁的技巧是把它封装在一个C#的using 语句中,代码如下:

@using (Html.BeginForm()){

…这里是表单的内容…

}

(ASP.NET Web表单在一个Web页面中仅支持一个服务器表单,通常表示成<form runat=”server”>,它是视图状态数据和回递逻辑的一个容器。MVC并不使用服务器表单。所有表单都表示成规则的HTML,在一个视图中可以使用任意多个表单。没有视图状态和其他隐藏的表单元素,而且赋给ID的值不会被混淆。)

运行这个程序,并点击“确认连接”,我们可以看到如下所示的表单

  • 处理表单

前面的列子没有告诉MVC把表单递交给服务器时,我们要做什么。此刻,点击”提交表单”按钮只是清除了表单已输入的值。这是因为回递给Home控制器的RsvpForm动作方法,只是告诉MVC再次渲染这个视图。

(注意:视图被再次渲染时,如果输入的数据丢失了,你可能会对此感到奇怪。如果是这样,你可能是因为一直使用ASP.NET Web Form 开发应用程序,Web Form 在这种情况下数据时自动保留的。下面的内容将很快演示如何使用MVC取得同样的效果)

为了接受并处理表单所递交的数据,我们打算做一件聪明的事。添加第二个RsvpForm动作方法,以形成如下作用:

  • 一个响应HTTP GET 请求的方法:Get请求时某人点一个连接时浏览器正常发出的请求。当有人第一次访问/Home/RsvpForm时,这个动作版本负责显示空白表单。
  • 一个响应HTTP POST 请求的方法:默认情况下,用Html.BeginForm()渲染的表单由浏个览器作为一个POST请求递交的。这个动作版本负责接收递交的数据,并决定用它做什么。

(注:Get请求和POST请求的区别很简单:Get请求时获取(GET)一个页面,而POST请求时递交(POST)一个页面(当然是递交表单中输入的数据)。即GET请求的目的是希望从服务器获取信息,而POST请求的目的是希望把表单中输入的数据递交给服务器去处理。)

以独立的C#方法分别处理GET和POST请求,有助于保持代码的整洁,因此这两种方法有不同的职责。两种方法都是由同样的URL进行调用,但MVC确保会根据我们是处理GET请求还是POST请求来调用合适的方法。下面是我们要对HomeController进行的修改。

  1. using System.Web.Mvc;
  2. using PartyInvites.Models;
  3. namespace PartyInvites.Controllers
  4. {
  5. public class HomeController : Controller
  6. {
  7. public ViewResult Index()
  8. {
  9. int hour = DateTime.Now.Hour;
  10. ViewBag.TempVar = hour < ? "早上好!" : "下午好!";
  11. return View();
  12. }
  13. [HttpGet]
  14. public ViewResult RsvpForm()
  15. {
  16. return View();
  17. }
  18. [HttpPost]
  19. public ViewResult RsvpForm(StudentResponse studentResponse)
  20. {
  21. //TODO:发送studentResponse 邮件给学校
  22. return View("Thanks", studentResponse);
  23. }
  24. }
  25. }

以上代码已经把HttpGet注解属性加到了现在的RsvpForm动作上。这告诉MVC,这个方法应该仅用户Get请求。然后添加了一个重载的RsvpForm方法,它带有一个StudentResponse参数,并运用HttpPost注解属性。该属性告诉MVC,这个方法将处理Post请求。

下节课将对表单的详细处理进行讲解。

MVC自学第三课的更多相关文章

  1. MVC自学第四课

    处理表单 前面的列子我们已经把表单提交给了HomeControllers类中的RsvpForm动作方法,只是在这个动作方法内,我们并没有做什么具体的逻辑处理,而是直接返回一个 “Thanks”的视图. ...

  2. 微信小程序自学第三课:文件作用域,模块化

    一.文件作用域 在 JavaScript 文件中声明的变量和函数只在该文件中有效:不同的文件中可以声明相同名字的变量和函数,不会互相影响. 通过全局函数 getApp() 可以获取全局的应用实例,如果 ...

  3. CodeIgniter框架入门教程——第三课 URL及ajax

    本文转载自:http://www.softeng.cn/?p=74 这节课讲一下CI框架的路由规则,以及如何在CI框架下实现ajax功能. 首先,先介绍CI框架的路由规则,因为CI框架是在PHP的基础 ...

  4. 【Linux探索之旅】第二部分第三课:文件和目录,组织不会亏待你

    内容简介 1.第二部分第三课:文件和目录,组织不会亏待你 2.第二部分第四课预告:文件操纵,鼓掌之中 文件和目录,组织不会亏待你 上一次课我们讲了命令行,这将成为伴随我们接下来整个Linux课程的一个 ...

  5. 【Linux探索之旅】第二部分第三课:文件和文件夹,组织不会亏待你

    wx_fmt=jpeg" alt="" style="max-width:100%; height:auto!important"> 内容简单介 ...

  6. ASP.NET MVC Model验证(三)

    ASP.NET MVC Model验证(三) 前言 上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的M ...

  7. ASP.NET MVC Model绑定(三)

    ASP.NET MVC Model绑定(三) 前言 看过前两篇的朋友想必对Model绑定有个大概的了解,然而MVC框架给我们提供了更高的可扩展性的提供程序编程模式,也就是本篇的主题了,会讲解一下Mod ...

  8. ASP.NET MVC Model元数据(三)

    ASP.NET MVC Model元数据(三) 前言 在上篇中我们大概的讲解了Model元数据的生成过程,并没有对Model元数据本身和详细的生成过程有所描述,本篇将会对详细的生成过程进行讲解,并且会 ...

  9. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

随机推荐

  1. 安装oneproxy实现数据库的读写分离

    领导就给了两台数据库,做主从,在从上搭建oneproxy插件,实现读写分离,一直就听说oneproxy,今天打算用一下 先下载最新的版本wget http://www.onexsoft.cn/soft ...

  2. sql远程连接卡死解决方法

    快捷键Win+R   输入CMD 回车  输入 netsh winsock reset 然后重启电脑  问题解决OK

  3. JSP(一)

    开宗明义:JSP本质上就是一个Servlet scriplet JSP 变量和函数的声明 局部变量 <% int a = 3;> 全局变量和函数 <%! int a = 3;> ...

  4. HTML5新属性

    1.contenteditable 属性指定元素内容是否可编辑. 注意: 当元素中没有设置 contenteditable 属性时,元素将从父元素继承. 所有主流浏览器都支持 contentedita ...

  5. PHP filter例子

    <?phpfunction convertSpace($str) { return str_replace(' ', '_', $str);} $str = 'i am a great guy! ...

  6. MySQL之字符串函数

    1. left函数, 对查询字段的字符串内容进行截取,用法select left(content,50) as summary from article; 在这里的意思是只查询content列内容的前 ...

  7. 学习笔记-menusript控件中条目权限设置使用

    在做一个小程序的时候,偶然发现了使用menusript控件做权限设置的方法,仅此标记,以供参考. 首先创建一个实例:testuseright.sln, 在项目文件里创建两个窗体:Form1.cs和us ...

  8. python 学习day5(模块)

    一.模块介绍 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能 ...

  9. Cidr计算

    项目上有个需求,要求计算cidr,网上perl和php,python很多,java的很少,呵呵,虽说懂点那个,毕竟还是会这个. 所以查了一下: https://foo.cs.ucsb.edu/cs56 ...

  10. Android studio gradle配置!!!【转】

    转自:http://www.open-open.com/lib/view/open1415793464648.html Gradle 基本概念 首先我们学习几个gradle 的脚本语法,掌握了这几个语 ...