ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第四篇:传递表单数据
摘要
本文将完成我们“MVC公告发布系统”的公告发布功能,以此展示在ASP.NET MVC中如何传递处理表单的数据。
前言
通过前几篇文章,我们已经能比较自如的使用ASP.NET
MVC来呈现页面和数据了。但是,有一个大问题没有解决:如何处理表单数据。例如,我们将要实现的公告发布功能,用户肯定是在某个表单页面输入标题、正文等内容,而后提交,然后表单数据要被传递到相应的地方交由业务逻辑组件处理。
在传统的ASP.NET下,使用的是Model1模式,每个aspx页面有一个同名的aspx.cs文件,当提交表单时,默认数据被提交到这个同名aspx.cs文件中某个方法下处理。但是,在ASP.NET
MVC中,这种方法不能用了,因为我们换用了Model2模式,不能再用同名代码文件来处理aspx的提交请求(但是这不表明同名代码文件就没有用了,实际上,它依然会被执行,但是我们不提倡在里面处理任何逻辑,但是,有时会利用它进行一些初始化操作。),那么应该怎么做呢?不多讲,我们以例子说明问题。
下面我们一步一步完成“MVC公告发布系统”的公告发布功能,等做完这个功能,上面的问题就明了了。
先修改一个错误...
这里,首先要像大家道歉,因为在第一篇里,我犯了一个错误。就是在公告的实体类AnnounceInfo中少了一个属性。现在,我们在AnnounceInfo中添加一个叫Cateogry的属性,类型为int,它用来指明这个公告属于哪个分类。
对于这个错误,我十分抱歉。
建立输入信息页面
下面,正式开始我们的工作。首先,我要建立一个页面,用来让用户输入公告信息。而我们知道,在ASP.NET
MVC中不能直接请求aspx文件,任何请求都要通过Controller,所以,我们首先在Controllers目录下建立一个新的Controller类,名叫AnnounceController。删除其中自动生成的Index方法,新建一个名叫Release的Action方法,具体代码如下。
AnnounceController.cs:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Web;
5using System.Web.Mvc;
6using System.Web.Mvc.Ajax;
7using MVCDemo.Models;
8using MVCDemo.Models.Interfaces;
9using MVCDemo.Models.Entities;
10
11namespace 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:
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Web;
5using System.Web.Mvc;
6using System.Web.Mvc.Ajax;
7using MVCDemo.Models;
8using MVCDemo.Models.Interfaces;
9using MVCDemo.Models.Entities;
10
11namespace 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>
小结
通过这四篇文章,我们已经了解了ASP.NET
MVC的基本原理,并且已经会呈现数据页面及传递表单数据处理了。会了这些,其实已经可以应付绝大多数主要开发了。从下篇开始,我们接触一些高级点的内容。下篇将说一下ASP.NET
MVC如何与ASP.NET AJAX及JQuery结合,再后面,会讲到拦截器及与Silverlight结合的内容。
ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第四篇:传递表单数据的更多相关文章
- 基于hi-nginx的web开发(python篇)——表单处理和文件上传
hi-nginx会自动处理表单,所以,在hi.py框架里,要做的就是直接使用这些数据. 表单数据一般用GET和POST方法提交.hi-nginx会把这些数据解析出来,放在form成员变量里.对pyth ...
- ASP.NET MVC案例教程(四)
ASP.NET MVC案例教程(四) 前言 通过前几篇文章,我们已经能比较自如的使用ASP.NET MVC来呈现页面和数据了.但是,有一个大问题没有解决:如何处理表单数据.例如,我们将要实现的公告发布 ...
- ASP.NET MVC案例教程(五)
ASP.NET MVC案例教程(四) 前言 通过前几篇文章,我们已经能比较自如的使用ASP.NET MVC来呈现页面和数据了.但是,有一个大问题没有解决:如何处理表单数据.例如,我们将要实现的公告发布 ...
- ASP.NET MVC案例教程(二)
ASP.NET MVC案例教程(二) 让第一个页面跑起来 现在,我们来实现公告系统中的第一个页面——首页.它非常简单,只包括所有公告分类的列表,并且每个列表项是一个超链接.其中分类数据是用我们的Moc ...
- ASP.NET MVC案例教程(三)
ASP.NET MVC案例教程(二) 让第一个页面跑起来 现在,我们来实现公告系统中的第一个页面——首页.它非常简单,只包括所有公告分类的列表,并且每个列表项是一个超链接.其中分类数据是用我们的Moc ...
- ASP.NET MVC案例教程(一) 准备
ASP.NET MVC案例教程(一) 前言 ASP.NET MVC作为微软官方的MVC解决方案,推出有一段时间了.可以说自动推出以来,一直广受关注.在经历了漫长的Preview之后,前几天终于推出了其 ...
- 【ASP.NET Web API教程】5.3 发送HTML表单数据:文件上传与多部分MIME
原文:[ASP.NET Web API教程]5.3 发送HTML表单数据:文件上传与多部分MIME 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面 ...
- 【ASP.NET Web API教程】5.2 发送HTML表单数据:URL编码的表单数据
原文:[ASP.NET Web API教程]5.2 发送HTML表单数据:URL编码的表单数据 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内 ...
- ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 基础教程总结 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基础教程总结 ASP.NET Core 基础教程总算是有了个简单 ...
随机推荐
- Ubuntu下通过Firefox Opera Chromium浏览器直接执行java应用程序(打开java jnlp文件)实现在服务器远程虚拟控制台完成远程管理的方法
远程虚拟控制台依赖于java运行环境(jre),在通过浏览器打开链接前,系统必须安装jre环境,远程管理控制台其实就是一个java程序,打开相应的网站会下载一个jnlp(java网络加载协议)的文件, ...
- while my time-- , will the meaning++?
// while my time--,will the meaning++? // However,what's the meaning of life ? while(tomorrow>0){ ...
- 推荐学习《算法之美:指导工作与生活的算法》中文PDF+英文PDF
我们所有人的生活都受到有限空间和有限时间的限制,因此常常面临一系列难以抉择的问题.在一天或者一生的时光里,哪些事是我们应该做的,哪些是应该放弃的?我们对杂乱无序的容忍底线是什么?新的活动与熟悉并喜爱的 ...
- 【Redis哨兵集群】
目录 开始配置主从复制 开始配置Redis Sentinel @ *** 在开始之前,我们先来看看Redis的主从复制 主从复制原理: 从服务器向主服务器发送SYNC命令. 主服务器接到SYNC命令后 ...
- OpenJDK源码研究笔记(十五):吐槽JDK中的10个富有争议的设计
前14篇文章,分享了JDK中值得学习和借鉴的编码和设计方法. 每个硬币都是有两面的.Every coin has two sides. 当然,JDK中也有很多值得改进或者说富有争议的设计. 本篇,就来 ...
- 启动和停止Service
activity_main <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...
- js---13 this call apply
//this:this可以写在js全剧环境中(全局环境中this是window对象),this可以写在函数中,可以写在对象中, function f(){ this.name = "asdf ...
- Python 面向对象 —— super 的使用(Python 2.x vs Python 3.x)
注意区分当前的 Python 版本是 2.X 还是 3.X,Python 3.X 在 super 的使用上较之 Python 2.X 有较大的变化: 1. Python 2.x class Conta ...
- js --- 递归结构图
// 用递归 来求 5 的阶乘 // n! = n * (n-1)! // 定义一个函数,用于求 n 的阶乘 function func(n) { ) { ; } // func(n-1) 因为传递的 ...
- 通过PXE安装Linux实况
通过PXE安装Linux实况 网卡引导操作系统的过程我们可以把它称为PXE(Pre-bootExecutionEnvironment),十几年前,在搞无盘NT时候,我们为了使网卡支持PXE引导要特意购 ...