| 
                                             摘要 
      本文将完成我们“MVC公告发布系统”的公告发布功能,以此展示在ASP.NET MVC中如何传递处理表单的数据。 
 
前言 
      通过前几篇文章,我们已经能比较自如的使用ASP.NET MVC来呈现页面和数据了。但是,有一个大问题没有解决: 
如何处理表单数据。例如,我们将要实现的公告发布功能,用户肯定是在某个表单页面输入标题、正文等内容,而后提交, 
然后表单数据要被传递到相应的地方交由业务逻辑组件处理。 
      在传统的ASP.NET下,使用的是Model1模式,每个aspx页面有一个同名的aspx.cs文件,当提交表单时, 
默认数据被提交到这个同名aspx.cs文件中某个方法下处理。但是,在ASP.NET MVC中,这种方法不能用了, 
因为我们换用了Model2模式,不能再用同名代码文件来处理aspx的提交请求(但是这不表明同名代码文 
件就没有用了,实际上,它依然会被执行,但是我们不提倡在里面处理任何逻辑,但是,有时会利用它 
进行一些初始化操作。),那么应该怎么做呢?不多讲,我们以例子说明问题。 
      下面我们一步一步完成“MVC公告发布系统”的公告发布功能,等做完这个功能,上面的问题就明了了。 
 
先修改一个错误... 
      这里,首先要像大家道歉,因为在第一篇里,我犯了一个错误。就是在公告的实体类AnnounceInfo中少 
了一个属性。现在,我们在AnnounceInfo中添加一个叫Category的属性,类型为int,它用来指明这个公告 
属于哪个分类。    对于这个错误,我十分抱歉。 
 
建立输入信息页面 
      下面,正式开始我们的工作。首先,我要建立一个页面,用来让用户输入公告信息。 
而我们知道,在ASP.NET MVC中不能直接请求aspx文件,任何请求都要通过Controller, 
所以,我们首先在Controllers目录下建立一个新的Controller类,名叫AnnounceController。 
删除其中自动生成的Index方法,新建一个名叫Release的Action方法,具体代码如下。 
AnnounceController.cs: 
 1 using System; 
 2 using System.Collections.Generic; 
 3 using System.Linq; 
 4 using System.Web; 
 5 using System.Web.Mvc; 
 6 using System.Web.Mvc.Ajax; 
 7 using MVCDemo.Models; 
 8 using MVCDemo.Models.Interfaces; 
 9 using MVCDemo.Models.Entities; 
10  
11 namespace MVCDemo.Controllers 
12   { 
13     public class AnnounceController : Controller 
14       { 
15         public ActionResult Release() 
16           { 
17             ICategoryService cServ = ServiceBuilder.BuildCategoryService(); 
18             List<CategoryInfo> categories = cServ.GetAll(); 
19             ViewData["Categories"] = new SelectList(categories, "ID", "Name"); 
20             return View("Release"); 
21         } 
22     } 
23 }
 
 
      这个就是要呈现表单页的Action方法,看看它做了什么:它首先取出所有的分类, 
然后将它们转成SelectList类型存入ViewData,最后呈现Release视图。 
      为什么要取出所有分类呢?因为我们在发布公告时希望有个下拉列表框列出所有公告名称, 
让用户可以选择要发布的公告属于哪个分类。而SelectList是ASP.NET MVC中用于绑定到下 
拉列表的类型。它有很多重载的构造方法,其中我使用的是三个参数的,它们分别表示: 
生成数据的枚举,绑定到value的字段名,绑定到列表名称的字段名。这里,将把所有分 
类实体集合绑定到下拉列表,而ID属性作为值,Name属性作为显示在列表框中的名字。 
      如果我们不需要下拉列表框来显示所有分类,那么Release方法只需一行 
return View("Release");就可以了。 
 
      Action方法做完了,我们还需要视图。在Views目录下建立Announce目录, 
再在这个Announce目录下建立Release.aspx视图。代码如下。 
Release.aspx: 
 1  <% @ Page Language="C#" AutoEventWireup="true" CodeBehind="Release.aspx.cs"  
Inherits="MVCDemo.Views.Announce.Release" %> 
 2  <% @ Import Namespace="MVCDemo.Models.Entities" %> 
 3  
 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
 5  
 6 <html xmlns="http://www.w3.org/1999/xhtml" > 
 7 <head runat="server"> 
 8     <title></title> 
 9 </head> 
10 <body> 
11      <%  SelectList categories = ViewData["Categories"] as SelectList; %> 
12     <div> 
13         <h1>MVC公告发布系统——发布公告</h1> 
14          <%  Html.BeginForm("DoRelease","Announce",FormMethod.Post); %> 
15         <dl> 
16             <dt>标题:</dt> 
17             <dd><%= Html.TextBox("Title") %></dd> 
18             <dt>分类:</dt> 
19             <dd><%= Html.DropDownList("Category",categories) %></dd> 
20             <dt>内容:</dt> 
21             <dd><%= Html.TextArea("Content") %></dd> 
22         </dl> 
23         <input type="submit" value="发布" /> 
24          <%  Html.EndForm(); %> 
25     </div> 
26 </body> 
27 </html>
 
 
      代码不复杂,但是要注意几个地方。categories不多说了,这是刚才我们传递过来的所有 
分类组成的列表项。我觉得大家迷惑的可能是那些Html.***的东西,其实,Html是ViewPage的 
中的一个对象(ViewPage是所有视图的基类),它主要的左右就是产生各种表单项(先这 
么认为吧,其实它还有其他功能),例如Html.BeginForm就是说这里开始一个form标签, 
而Html.EndForm当然是form标签结束。其他几个,看名字相信大家也猜出来了。 
      至于为什么这么做,也不直接使用原始的HTML标签,我先不多说,以后大家做多了 
自然就理解了,目前大家只要知道,这样做可以避免一个url问题以及让url更灵活就行了。^_^ 
      回到这个页面,BeginForm有三个参数,分别是提交请求的Action名,提交请求的 
Controller名和请求方式。所以,这个页面的意思就是使用post方法请求 
http://localhost/Announce/DoRelease这个Action来处理我们的请求。 
      页面中有三个输入表单和一个提交按钮。三个输入表单分别是:名叫Title的文本框, 
名叫Content的文本域和名叫Category的下拉列表框。注意下拉列表是怎么绑定的,只要将含 
有数据的SelectList作为第二个参数就行了。完成后,页面是这样子的: 
  
  
处理请求 
      现在我们可以输入信息了,但是如果你输入后点提交,你会发现产生了经典的404错误。 
刚才我们说了,表单提交到的Action是Announce下的DoRelease,但是现在没有这个Action, 
当然会404了。下面,我们来建立这个处理程序。 
      回到AnnounceController,新建Action方法DoRelease,具体代码如下。 
AnnounceController.cs: 
 1 using System; 
 2 using System.Collections.Generic; 
 3 using System.Linq; 
 4 using System.Web; 
 5 using System.Web.Mvc; 
 6 using System.Web.Mvc.Ajax; 
 7 using MVCDemo.Models; 
 8 using MVCDemo.Models.Interfaces; 
 9 using MVCDemo.Models.Entities; 
10  
11 namespace MVCDemo.Controllers 
12   { 
13     public class AnnounceController : Controller 
14       { 
15         public ActionResult Release() 
16           { 
17             ICategoryService cServ = ServiceBuilder.BuildCategoryService(); 
18             List<CategoryInfo> categories = cServ.GetAll(); 
19             ViewData["Categories"] = new SelectList(categories, "ID", "Name"); 
20             return View("Release"); 
21         } 
22  
23         public ActionResult DoRelease() 
24           { 
25             AnnounceInfo announce = new AnnounceInfo() 
26               { 
27                 ID = 1, 
28                 Title = Request.Form["Title"], 
29                 Category = Int32.Parse(Request.Form["Category"]), 
30                 Content = Request.Form["Content"], 
31             }; 
32  
33             IAnnounceService aServ = ServiceBuilder.BuildAnnounceService(); 
34             aServ.Release(announce); 
35  
36             ViewData["Announce"] = announce; 
37             return View("ReleaseSucceed"); 
38         } 
39     } 
40 }
 
 
 
      我们看,它首先新建一个AnnounceInfo类型的实体类,用来存贮这个新的公告的信息。 
注意它是怎么得到表单信息的,对了,用了Request.Form["表单名"],这就是获得表单信息的 
一种方法,当然还有其他方法,但是我推荐这一种。注意,这里的表单名就是我们 
使用Html.***方法生成表单时的名字。 
      OK,下面就是调用业务逻辑组件,完成发布公告功能。 
      但是这里有个问题,我们的业务逻辑组件是Mock的,也就是说其实什么都没做啊。 
如果是真的业务逻辑组件,我们可以去数据库看看有没有添加公告信息成功,可是这里没有, 
我们要怎么证明表单数据传递过来了呢?于是我想了一个办法,有新加了一个ReleaseSucceed视图, 
用来显示新发布公告的信息,以此证明我们确实把表单信息传过来了。ReleaseSucceed视图如下: 
ReleaseSucceed.aspx: 
 1  <% @ Page Language="C#" AutoEventWireup="true" CodeBehind="ReleaseSucceed.aspx.cs"  
Inherits="MVCDemo.Views.Announce.ReleaseSucceed" %> 
 2  <% @ Import Namespace="MVCDemo.Models.Entities" %> 
 3  
 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
 5  
 6 <html xmlns="http://www.w3.org/1999/xhtml" > 
 7 <head runat="server"> 
 8     <title></title> 
 9 </head> 
10 <body> 
11      <%  AnnounceInfo announce = ViewData["Announce"] as AnnounceInfo; %> 
12     <div> 
13         <h1>MVC公告发布系统——发布公告成功</h1> 
14         <dl> 
15             <dt>ID:</dt> 
16             <dd><%= announce.ID %></dd> 
17             <dt>标题:</dt> 
18             <dd><%= announce.Title %></dd> 
19             <dt>类别ID:</dt> 
20             <dd><%= announce.Category %></dd> 
21             <dt>内容:</dt> 
22             <dd><%= announce.Content %></dd> 
23         </dl> 
24     </div> 
25 </body> 
26 </html>
 
 
 
 
在这里大概说下 在Global 里面那个 
 
new {controller="Announce", 
action ="Release", 
id = "" }); 
 
在从浏览器查看就可以了 
 
      这些代码就不用我过多解释了。下面,我们输入一些信息,提交看看: 
  
      看到没有,我没有骗你们,表单数据真的传过来了!^_^||| 
 
小结 
      通过这四篇文章,我们已经了解了ASP.NET MVC的基本原理,并且已经会呈现数据页面及传递表单数据处理了。 
会了这些,其实已经可以应付绝大多数主要开发了。从下篇开始,我们接触一些高级点的内容。下篇将说一下 
ASP.NET MVC如何与ASP.NET AJAX及JQuery结合,再后面,会讲到拦截器及与Silverlight结合的内容。 
                                         |