ASP.NET MVC 模式应用开发简易教程
本文提供了一个关于使用 MVC 模式开发 ASP.NET 应用程序的简单教程。
引言
本文提供了一个关于使用 MVC 模式开发 ASP.NET 应用程序的简单教程。
背景
ASP.NET 最新的发展之一就是 MVC(Model–View–Controller)设计模式。MVC 模式将用户界面的输入和表示(GUI)与应用程序逻辑隔离开来。
根据 Scott Guthrie 的说法,MVC 模式具有以下优点:
- 使用 MVC 方法论的好处之一是,它有助于在应用程序中强制实现模型、视图和控制器之间清晰的关注点分离。保持清晰的关注点分离使得应用程序的测试更加容易,因为不同应用程序组件之间的约定被更清晰地定义和阐述。
- MVC 模式还可以帮助实现红/绿测试驱动开发(TDD)——即你首先实现自动化单元测试,这些测试定义和验证新代码的要求,然后再编写代码本身。
下图摘自 Wikipedia,展示了 MVC 模式。

MVC 将应用程序分为三个关注点:
- 模型 - 封装核心应用程序数据和功能(领域逻辑)。
- 视图 - 从模型获取数据并将其呈现给用户。
- 控制器 - 接收输入并将其翻译成对模型或视图的请求。
Scott Guthrie 在他的 博客 中对如何将 MVC 模式应用于 ASP.NET 项目进行了非常精彩且详细的介绍。出于显而易见的原因,他的介绍非常全面且权威。对于想要理解 ASP.NET MVC 的应用程序开发人员来说,这应该是首要的参考资料。
本文旨在提供一个在 Microsoft Visual Studio 环境下开发 ASP.NET MVC 应用程序的更简单的教程,以帮助应用程序开发人员快速入门。
在处理 ASP.NET MVC 网站时,你首先会注意到访问网页的 URL 不再是熟悉的“https://codeproject.org.cn/info/search.aspx”样式。取而代之的是,URL 将看起来像 https:///VirtualDirectoryName/Controller/Action。
阅读完本文后,希望你能够快速在 Visual Studio 中开发自己的 ASP.NET MVC 网站。本文旨在回答以下问题:
- ASP.NET MVC 的 URL 如何与 Web 服务器上的资源关联?
- 在 ASP.NET 中,模型、视图和控制器分别是什么?它们是如何实现的?
- 模型、视图和控制器之间是如何传递信息的?
- 服务器上的应用程序代码如何访问浏览器通过 URL 参数和表单提交传递给服务器的数据?
- 如何在 ASP.NET MVC 中访问会话数据?
- 在实现视图时如何使用代码隐藏文件?
本教程应用程序是在 Visual Studio 2008 中开发的,使用的语言是 C#。如果你有 Visual Studio 2010,你的环境可能会有所不同。
本文附带了本教程的源代码。最好先下载源代码并在 Visual Studio 中运行它,然后再开始阅读本教程。这样你就能更好地了解本简单教程 ASP.NET MVC 应用程序中实现的功能。这将使你阅读本文更容易。如果你无法在 Visual Studio 中加载源代码,则可能需要先设置你的开发环境。
让我们从设置开发环境开始。
设置开发环境
为了开发 MVC ASP.NET 应用程序,你需要安装 Visual Studio ASP.NET MVC 插件。如果你还没有这样做,可以访问 Microsoft 网站 下载插件并将其安装到你的计算机上。
在 Visual Studio 中创建空的 ASP.NET MVC 项目
安装 ASP.NET MVC 插件后,我们就可以开始在 Visual Studio 中创建 ASP.NET MVC 项目了。

我们可以创建两种类型的 ASP.NET MVC 应用程序。在本教程中,我们将创建一个“ASP.NET MVC 2 空 Web 应用程序”。将项目命名为“ASPNetMVCTutorial
”,然后浏览一个你想要保存 Visual Studio 将要生成的文件所在的文件夹,并单击“OK”按钮。
项目创建后,解决方案资源管理器将包含以下内容:

为了更好地在本 ASP.NET 开发中关注 MVC 模式,我将限制使用 JavaScript 和 CSS 样式表。让我们删除与 MVC 无关的文件夹,并添加一个名为“Utilities”的文件夹。“Utilities”文件夹稍后将用于向项目中添加一些实用程序类。清理后,解决方案资源管理器将包含以下内容:

在此项目中,我们可以看到“ASP.NET MVC 2 空 Web 应用程序”模板生成的三个文件夹:
- 模型
- 视图
- 控制器
模型、视图和控制器(MVC)将在本教程稍后添加到相应的文件夹中。
你还会注意到项目中存在两个“Web.config”文件。大多数配置信息将位于根文件夹中的“Web.config”文件中,而“Views”文件夹中的那个文件用于阻止直接访问视图“aspx”页面。对于大多数 ASP.NET MVC 应用程序,我们不需要更改此“Web.config”文件。
向根目录的“Web.config”文件添加一些配置
在着手创建模型、视图和控制器之前,让我们先将根目录“Web.config”文件中的“<AppSettings />
”部分更改为以下内容:
<appSettings>
<add key="ApplicationName"
value="A Simple Tutorial on How to Develop ASP.NET
Web Projects in MVC Pattern"/>
<add key="Author" value="Song Li"/>
<add key="DevelopmentTime" value="5/4/2010"/>
<add key="DeploymentVirtualDirectory" value=""/>
</appSettings>
此配置信息将在 ASP.NET MVC 应用程序稍后使用。
将模型类添加到“Models”文件夹
MVC 模式中的模型代表应用程序数据。在本教程中,我们将开发一个用于管理学生列表的应用程序。该应用程序将允许用户显示、添加和删除学生。右键单击“Models”文件夹并选择添加类。将类文件命名为“StudentsModel.cs”。
添加类后,我们可以按以下方式实现该类:
using System;
using System.Data;
namespace ASPNetMVCTutorial.Models
{
public class StudentsModel
{
private DataTable Students;
public StudentsModel()
{
Students = new DataTable();
DataColumn IDColumn = Students.Columns.Add
("ID", Type.GetType("System.Int32"));
IDColumn.AutoIncrement = true;
IDColumn.AutoIncrementSeed = 1;
IDColumn.AutoIncrementStep = 1;
Students.Columns.Add("Name", Type.GetType("System.String"));
Students.Columns.Add("Score", Type.GetType("System.Int32"));
Students.Columns.Add("Time Added", Type.GetType("System.DateTime"));
DataColumn[] keys = new DataColumn[1];
keys[0] = IDColumn;
Students.PrimaryKey = keys;
Random rd = new Random();
for (int Idex = 1; Idex <= 5; Idex++)
{
DataRow row = Students.NewRow();
Students.Rows.Add(row);
row["Name"] = "Student Name No. " + Idex.ToString();
row["Score"] = 60 + rd.NextDouble() * 40;
row["Time Added"] = System.DateTime.Now;
}
}
public void AddStudent(string Name, int Score)
{
DataRow row = Students.NewRow();
Students.Rows.Add(row);
row["Name"] = Name;
row["Score"] = Score;
row["Time Added"] = System.DateTime.Now;
}
public void DeleteStudent(int ID)
{
DataRow RowToDelete = Students.Rows.Find(ID);
if (RowToDelete != null)
{
Students.Rows.Remove(RowToDelete);
}
}
public DataTable GetStudents()
{
return Students;
}
}
}
此类有一个 `private` 变量“Students
”。其数据类型为“DataTable
”。学生信息存储在此“DataTable
”中。除了构造函数外,它还公开了添加和删除学生的方法。“GetSudents
”方法返回包含所有学生信息的“DataTable
”给调用者。当此类的对象首次创建时,构造函数将初始化“DataTable
”并向其中插入 5 个随机生成的学生。
为了让此 ASP.NET MVC 应用程序能够使用我们添加到“Web.config”文件中的配置信息,我们将添加另一个名为“ApplicationInformation.cs”的模型类文件。
using System;
using System.Configuration;
namespace ASPNetMVCTutorial.Models
{
public class ApplicationInformation
{
private static ApplicationInformation _thisInstance = null;
private static object _threadLock = new Object();
public string ApplicationName { get; private set; }
public string Author { get; private set; }
public string DevelopmentTime { get; private set; }
public string DeploymentVirtualDirectory { get; private set; }
public ApplicationInformation()
{
ApplicationName = ConfigurationManager.AppSettings["ApplicationName"];
Author = ConfigurationManager.AppSettings["Author"];
DevelopmentTime = ConfigurationManager.AppSettings["DevelopmentTime"];
DeploymentVirtualDirectory =
ConfigurationManager.AppSettings["DeploymentVirtualDirectory"];
}
public static ApplicationInformation GetInstance()
{
lock (_threadLock)
{
if (_thisInstance == null)
{
_thisInstance = new ApplicationInformation();
}
}
return _thisInstance;
}
}
}
ASP.NET MVC 项目将使用“ApplicationInformation
”类来访问配置。
向“Utilities”文件夹添加一个实用程序类
为了使后续开发工作更轻松,我们将向“Utilities”文件夹添加一个名为“ApplicationUtility
”的类。右键单击“Utilities”文件夹,然后选择添加类。将类文件命名为“ApplicationUtility.cs”并按以下方式实现该类:
using System;
using System.Text;
using ASPNetMVCTutorial.Models;
namespace ASPNetMVCTutorial.Utilities
{
public static class ApplicationUtility
{
public static string FormatURL(string PathWithoutVirtualDirectoryName)
{
ApplicationInformation appInfomation
= ApplicationInformation.GetInstance();
string DeploymentVirtualDirectory
= appInfomation.DeploymentVirtualDirectory;
if (DeploymentVirtualDirectory == "")
{
return PathWithoutVirtualDirectoryName;
}
StringBuilder SB = new StringBuilder();
SB.Append("/");
SB.Append(appInfomation.DeploymentVirtualDirectory);
SB.Append("/");
SB.Append(PathWithoutVirtualDirectoryName);
return SB.ToString();
}
}
}
静态方法“FormatURL
”用于根据部署时的虚拟目录名称将 ASP.NET MVC 相对 URL 转换为绝对 URL。虚拟目录名称在“Web.config”文件中配置。在开发时,我们需要将其配置为空字符串。在部署时,我们必须在“Web.config”文件中放入正确的虚拟目录名称。
为 ASP.NET MVC 项目添加主页面
在添加视图之前,我们将先为这个 ASP.NET 项目添加一个主页面。默认情况下,ASP.NET MVC 应用程序会在 Visual Studio 中使用主页面,所以让我们先创建一个主页面。主页面将被添加到“Views\Shared”文件夹中。
右键单击“Views\Shared”文件夹并选择添加新项。

选择“Master Page”模板,将主页面命名为“Site.Master
”,然后单击“Add”按钮,主页面将被添加到项目中。
我们将按以下方式实现“Site.Master
”文件:
<%@ Master Language="C#"
CodeBehind="~/Views/Shared/Site.Master.cs"
Inherits="ASPNetMVCTutorial.Views.Shared.Site" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title><asp:Literal id="litAppTitle" runat="server" /></title>
<style type="text/css">
.ApplicationDefault {font-family: Verdana; font-size: 10px;}
.Title {text-align: center; font-size: 12px; color:Maroon; font-family:
Verdana; font-weight: bold;}
.AuthorInformation {text-align: center; color:green; margin-top: 5px}
.MainContent {margin-top: 10px; background-color: #F1FFFF; height: 600px;
overflow: auto; width: 95%; text-align: center;
margin-left:auto; margin-right:auto;}
.Copyright {margin-top: 10px; color: Gray; font-weight:bold; width: 100%;
float: left; text-align: center;}
.ErrorText {font-family: Verdana; font-weight: bold; color:Maroon;}
.BoldText {font-family: Verdana; font-weight: bold;}
</style>
</head>
<body class="ApplicationDefault">
<div class="Title">
<asp:Literal id="litApplicationName" runat="server" />
</div>
<div class="AuthorInformation">
<asp:Literal id="litAuthorInformation" runat="server" />
</div>
<div id="MainContent" class="MainContent">
<asp:ContentPlaceHolder id="ApplicationContent" runat="server" />
</div>
<div class="Copyright">Copy right: The Code Project Open License (CPOL)</div>
</body>
</html>
我们将按以下方式实现代码隐藏文件“Site.Master.cs”:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Web.UI.WebControls;
using ASPNetMVCTutorial.Models;
using ASPNetMVCTutorial.Utilities;
namespace ASPNetMVCTutorial.Views.Shared
{
public partial class Site : System.Web.Mvc.ViewMasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
ApplicationInformation appInfomation = ApplicationInformation.GetInstance();
litAppTitle.Text = appInfomation.ApplicationName;
litApplicationName.Text = appInfomation.ApplicationName;
StringBuilder SB = new StringBuilder();
SB.Append("Developed by ");
SB.Append(appInfomation.Author);
SB.Append(" on ");
SB.Append(appInfomation.DevelopmentTime);
litAuthorInformation.Text = SB.ToString();
}
}
}
主页面将用于整个项目,以控制显示样式并显示有关应用程序的一些通用信息。
将视图添加到“Views”文件夹
ASP.NET MVC 中的视图实际上是特殊的“aspx”页面。在此项目中,我们将添加三个视图:
- StudentList.aspx
- AddStudent.aspx
- Error.aspx
“StudentList.aspx”用于列出所有学生,并提供用户交互以导航到“AddStudent.aspx”视图来添加学生。它还提供删除学生的交互功能。“Error.aspx”视图用于显示操作过程中可能发生的任何错误。
“StudentList.aspx”和“AddStudent.aspx”视图将添加到“Views\Students”文件夹中,“Error.aspx”将添加到“Views\Shared”文件夹中。右键单击“Views”文件夹并向其中添加一个“Students”文件夹。然后我们可以添加“StudentList.aspx”视图。右键单击“Views\Students”文件夹并添加视图。

将视图命名为“StudentList
”,选择主页面“Site.Master
”,将 `ContentPlaceHolderID` 输入为“ApplicationContent
”,然后单击“Add”按钮。在解决方案资源管理器中,视图作为“StudentList.aspx”文件创建在“Views\Students”文件夹中。

你可能会惊讶地发现“StudentList.aspx”视图没有熟悉的代码隐藏文件。关于是否应该在 ASP.NET MVC 视图中使用代码隐藏文件,这是一个热门的讨论。有些人称在视图中使用代码隐藏文件是“邪恶的”,而另一些人则认为它“并非邪恶”。我不会深入讨论这个话题。我只是觉得如果应用程序开发人员选择使用代码隐藏文件,他们应该有使用的选项。我们将手动为“StudentList.aspx”添加代码隐藏文件。
右键单击“Views\Students”文件夹并添加一个名为“StudentList.aspx.cs”的类文件。“StudentList.aspx.cs”文件将自动实现一个名为“StudentList
”的类。使“SudentList
”类继承自“System.Web.Mvc.ViewPage
”。在“StudentList.aspx”文件中,添加指向“StudentList.aspx.cs”的“CodeBehind
”引用,并将“Inherits
”值更改为“StudentList
”类。通过这样做,代码隐藏文件将被手动添加到解决方案资源管理器中。

添加代码隐藏文件后,我们将按以下方式实现“StudentList.aspx”:
<%@ Page Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
CodeBehind="~/Views/Students/StudentList.aspx.cs"
Inherits="ASPNetMVCTutorial.Views.Students.StudentList" %>
<asp:Content id="IndexContent" ContentPlaceHolderID="ApplicationContent" runat="server">
<div style="float: right; margin-right: 10px">
<asp:HyperLink id="linkAddStudent" runat="server"
Text="Click to add a student to the list" />
</div>
<br />
<div style="margin-top: 5px">
<asp:Literal id="litStudentDetail" runat="server" />
</div>
</asp:Content>
代码隐藏文件“StudentList.aspx”将按以下方式实现:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Data;
using System.Web.UI.WebControls;
using ASPNetMVCTutorial.Models;
using ASPNetMVCTutorial.Utilities;
namespace ASPNetMVCTutorial.Views.Students
{
public class StudentList : System.Web.Mvc.ViewPage
{
protected Literal litStudentDetail;
protected HyperLink linkAddStudent;
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
linkAddStudent.NavigateUrl =
ApplicationUtility.FormatURL("/Students/AddStudent");
DataTable StudentsTable = (DataTable)ViewData["Students"];
DataView StudentsView = StudentsTable.DefaultView;
StudentsView.Sort = "ID Desc";
StringBuilder SB = new StringBuilder();
SB.Append("<table style=\"width: 99%;\" ");
SB.Append("rules=\"all\" border=\"1px\" ");
SB.Append("cellspacing=\"0px\" cellpadding=\"4px\">");
SB.Append("<tr style=\"background-color: Silver; color: white; ");
SB.Append("font-weight: bold\">");
foreach (DataColumn aColumn in StudentsTable.Columns)
{
SB.Append("<td>");
SB.Append(aColumn.ColumnName);
SB.Append("</td>");
}
SB.Append("<td> </td>");
SB.Append("</tr>");
foreach (DataRowView aRowView in StudentsView)
{
SB.Append("<tr>");
foreach (DataColumn aColumn in StudentsTable.Columns)
{
SB.Append("<td>");
SB.Append(aRowView[aColumn.ColumnName].ToString());
SB.Append("</td>");
}
string ID = aRowView["ID"].ToString();
SB.Append("<td>");
SB.Append("<a href=\"");
SB.Append(ApplicationUtility.FormatURL("/Students/DeleteStudent"));
SB.Append("?ID=");
SB.Append(ID);
SB.Append("\">Delete this student</a>");
SB.Append("</td>");
SB.Append("</tr>");
}
SB.Append("</table>");
litStudentDetail.Text = SB.ToString();
}
}
}
同样,我们将按以下方式将“AddStudent.aspx”实现到“Views\Students”文件夹中:
<%@ Page Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
CodeBehind="~/Views/Students/AddStudent.aspx.cs"
Inherits="ASPNetMVCTutorial.Views.Students.AddStudent" %>
<asp:Content ID="AddStudentContent"
ContentPlaceHolderID="ApplicationContent" runat="server">
<script language="javascript" type="text/javascript">
function SubmitForm() {
frmAddStudent.action = hidAddstudentActionURL.value;
frmAddStudent.submit();
}
</script>
<asp:Literal ID="litAddStudentActionHidden" runat="server" />
<form id="frmAddStudent" method="post" action="">
<div style="text-align: center">
<table cellspacing="5px" cellpadding="0px" style="text-align:
center; margin-left:auto; margin-right:auto;">
<tr>
<td class="BoldText" style="text-align: left">
Please provide the following information to add the student:
</td>
</tr>
<tr><td style="height: 10px"></td></tr>
<tr>
<td>
Name <input type="text" id="textName" name="textName" />
Score <input type="text" id="txtScore" name="txtScore" />
</td>
</tr>
<tr>
<td>
<asp:HyperLink ID="linkCancelAddStudent"
Text="Cancel add student and
return to the main page" runat="server" />
<input type="button" value="Add student" onclick="return SubmitForm()" />
</td>
</tr>
</table>
</div>
</form>
</asp:Content>
“AddStudent.aspx”视图的代码隐藏文件将按以下方式实现:
using System;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using ASPNetMVCTutorial.Models;
using ASPNetMVCTutorial.Utilities;
namespace ASPNetMVCTutorial.Views.Students
{
public class AddStudent : System.Web.Mvc.ViewPage
{
protected HyperLink linkCancelAddStudent;
protected Literal litAddStudentActionHidden;
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringBuilder SB = new StringBuilder();
SB.Append("<input type=\"hidden\" id=\"hidAddstudentActionURL\" value=\"");
SB.Append(ApplicationUtility.FormatURL("/Students/AddStudentAction"));
SB.Append("\" />");
linkCancelAddStudent.NavigateUrl
= ApplicationUtility.FormatURL("/Students/StudentList");
litAddStudentActionHidden.Text = SB.ToString();
}
}
}
“Error.aspx”视图将在“Views\Shared”文件夹中按以下方式实现:
<%@ Page Language="C#"
CodeBehind="~/Views/Shared/Error.aspx.cs"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="ASPNetMVCTutorial.Views.Shared.Error" %>
<asp:Content ID="ErrorContent" ContentPlaceHolderID="ApplicationContent" runat="server">
<div style="margin-top: 10px; text-align: center">
<table cellpadding="4px" cellspacing="4px" style="margin-left:auto;
margin-right:auto;">
<tr><td class="ErrorText"><asp:Literal ID="litErrorMessage"
runat="server" /></td></tr>
<tr><td style="text-align: right">
<asp:HyperLink ID="linkBackToMainPage" Text="Go back to main page"
runat="server" />
</td></tr>
</table>
</div>
</asp:Content>
“Error.aspx”的代码隐藏文件将按以下方式实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI.WebControls;
using ASPNetMVCTutorial.Models;
using ASPNetMVCTutorial.Utilities;
namespace ASPNetMVCTutorial.Views.Shared
{
public class Error : System.Web.Mvc.ViewPage
{
protected Literal litErrorMessage;
protected HyperLink linkBackToMainPage;
protected void Page_Load(object sender, EventArgs e)
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
linkBackToMainPage.NavigateUrl
= ApplicationUtility.FormatURL("/Students/StudentList");
string ErrorMessage = ViewData["ERROR"].ToString();
litErrorMessage.Text = ErrorMessage;
}
}
}
ASP.NET MVC 视图是专门的 ASP.NET 页面。“System.Web.Mvc.ViewPage”类是类继承层次结构中“System.Web.UI.Page”类的直接子类。在开发视图时,为了更好地遵循 MVC 方法论,避免对应用程序数据进行任何修改非常重要。
将控制器添加到“Controllers”文件夹
现在我们可以为这个 ASP.NET MVC 项目添加控制器了。右键单击“Controllers”文件夹以添加控制器类,并将类命名为“StudentsController
”,并按以下方式实现此 `controller` 类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ASPNetMVCTutorial.Models;
namespace ASPNetMVCTutorial.Controllers
{
public class StudentsController : Controller
{
private StudentsModel GetStudentModelFromSession()
{
StudentsModel theModel = (StudentsModel)Session["Students"];
if (theModel == null)
{
theModel = new StudentsModel();
Session["Students"] = theModel;
}
return theModel;
}
public ActionResult StudentList()
{
StudentsModel theModel = GetStudentModelFromSession();
ViewData["Students"] = theModel.GetStudents();
return View();
}
public ActionResult AddStudent()
{
return View();
}
public ActionResult AddStudentAction()
{
string Name = Request.Form["textName"];
string Score = Request.Form["txtScore"];
if ((Name == null) || (Name.Trim() == ""))
{
ViewData["ERROR"] = "Please provide a name for the student to add";
return View("../Shared/Error");
}
if (Name.Length < 6)
{
ViewData["ERROR"]
= "The student's name should not be less than 6 characters.";
return View("../Shared/Error");
}
int intScore;
if (!Int32.TryParse(Score, out intScore))
{
ViewData["ERROR"]
= "Please provide a valid score to the student to add.";
return View("../Shared/Error");
}
if ((intScore < 60) || (intScore > 100))
{
ViewData["ERROR"]
= "We only accept students with scores between 60 and 100.";
return View("../Shared/Error");
}
StudentsModel theModel = GetStudentModelFromSession();
theModel.AddStudent(Name, intScore);
ViewData["Students"] = theModel.GetStudents();
return View("StudentList");
}
public ActionResult DeleteStudent()
{
string ID = Request.QueryString["ID"];
int intID;
if (!Int32.TryParse(ID, out intID))
{
ViewData["ERROR"] = "Please provide a valid student ID";
return View("../Shared/Error");
}
StudentsModel theModel = GetStudentModelFromSession();
theModel.DeleteStudent(intID);
return RedirectToAction("StudentList");
}
}
}
此控制器名为“StudentsController
”。它实现了 5 个方法。
私有方法“GetStudentModelFromSession
”用于演示在此 ASP.NET MVC 项目中如何使用 Web 会话。它返回“StudentsModel
”类型的对象,该对象在“Models”文件夹中实现。该方法首先尝试从 Web 会话中获取此对象。如果无法获取,它将创建一个新对象并将其添加到 Web 会话中。此对象将用作本教程 Web 应用程序中的数据存储。
四个 `public` 方法在 ASP.NET MVC 术语中称为“`actions`”(操作):
StudentList
AddStudent
AddStudentAction
DeleteStudent
这些方法用于对 Web 会话中保存的应用程序数据执行某些操作。当应用程序数据操作完成后,每个方法将选择一个在“Views”文件夹中实现的视图来向用户显示数据。如果所选视图的名称与“action”的名称相同,则可以省略视图的名称。要访问用户从浏览器输入的输入,这些方法可以使用熟悉的“Request.QueryString”和“Request.Form”方法。
操作方法通过“ViewData”字典传递要显示给视图的数据。
"Global.asax" - 魔术发生的地方
当我们创建 ASP.NET MVC 项目时,Visual Studio 会为我们生成一个默认的“Global.asax”文件。现在我们将对此文件进行如下更改:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace ASPNetMVCTutorial
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Students",
action = "StudentList",
id = UrlParameter.Optional }
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
}
}
访问 ASP.NET MVC 项目中开发的网页的 URL 格式为“https:///VirtualDirectoryName/Controller/Action”。在“Global.asax”文件中调用“routes.MapRoute”方法确保了正确控制器和操作的定位。如果 URL 未指定控制器和操作,则将默认使用“Student
”控制器和“StudentList
”操作。
当 Web 应用程序接收到 URL 时,它首先会找到控制器。如果 URL 中的控制器是“Student
”,Web 应用程序将尝试在“Controllers”文件夹中查找名为“StudentController
”的类。在找到控制器类之后,将调用与操作同名的方法,例如“StudentList
”。控制器类中选定的操作方法将执行应用程序数据上的所有操作,并选择一个视图来显示给用户。操作方法通过“ViewData”字典传递要显示给视图的数据。
如果你想在同一个 ASP.NET 项目中混合使用常规的“aspx”页面和 MVC 视图,可以在映射 ASP.NET MVC 路由之前添加以下代码:
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
这样,路由将忽略指向常规“aspx”页面的 URL。这些页面将直接加载,而无需经过控制器-操作-视图模式。
解决方案资源管理器中显示的已完成项目
现在我们完成了本教程 ASP.NET MVC 应用程序的开发。下图显示了解决方案资源管理器中包含代码隐藏文件的所有文件:

运行 ASP.NET MVC 应用程序
当 Visual Studio 获得焦点时按下“F5”,我们可以开始调试运行本教程应用程序。下图显示了应用程序在“Google Chrome”中运行的样子:

单击其中一个“Delete this student”(删除该学生)链接,我们可以从列表中删除该学生。单击“Click to add a student to the list”(点击添加学生到列表)链接,网页将导航到以下内容:

输入学生姓名并为其评分,然后单击“Add student”(添加学生)按钮,我们就可以看到学生已被添加。

关注点
- 本教程旨在帮助读者在 Visual Studio 中快速入门 ASP.NET MVC 应用程序的开发。它可能不完全遵循 Scott Guthrie 的方法,甚至不完全遵循通用的 MVC。如果存在任何差异,你应始终以 Scott Guthrie 的为准。
- 关于视图是否应使用代码隐藏文件,我不想深入讨论。我认为最好将此选择留给应用程序开发人员。如果 MVC 模式是为了分离应用程序开发中的关注点,为什么我们不进一步分离视图开发中的关注点呢?在本教程中,所有视图都有代码隐藏文件。
- 值得注意的是,ASP.NET MVC 模式与 WPF 开发中的 MVVM 模式不同。在 MVVM 中,我们有更成熟的双向数据绑定,这使得 MVVM 能够最大限度地减少 XAML 文件的代码隐藏文件使用。但在 ASP.NET MVC 模式中,控制器通过“
ViewData
”字典将数据传递给视图进行显示。在视图中,如果我们不使用代码隐藏文件,我们将需要使用“aspx”文件中的内联服务器脚本,这使得视图的单元测试几乎不可能。 - 本 MVC 教程中的“
Model
”部分是一个存储在 Web 会话中的“DataTable
”。通过这样做,读者只需 Visual Studio 即可完成本教程。对于任何实际的 ASP.NET MVC 应用程序,都需要持久数据存储。 - 实用程序类“
ApplicationUtility
”中的“FormatURL
”方法是为了确保即使在部署时虚拟目录名称发生更改,我们也能始终获得正确的 ASP.NET MVC 模式 URL。有许多方法可以达到相同的目标。如果你不喜欢此方法,可以随时实现自己的方法。 - 开发在浏览器中运行的应用程序本质上是一项综合性任务。结合所有可用的技术,如 CSS 样式表、JavaScript、Ajax、jQuery、Silverlight 以及 MVC 模式,以提供最佳的性能和用户体验,总是更好的。
结论
为了完成本教程,我们将回答文章开头列出的问题:
- ASP.NET MVC 的 URL 如何与 Web 服务器上的资源关联?
- ASP.NET MVC 应用程序的 URL 包含控制器部分和操作部分,应用程序将使用控制器部分来定位控制器类,并使用操作部分来定位控制器类中实现的操作方法。当操作方法完成应用程序数据的操作后,它将选择一个视图来显示应用程序数据。
- 在 ASP.NET 中,模型、视图和控制器分别是什么?它们是如何实现的?
- 在 Visual Studio 创建的标准 ASP.NET MVC 应用程序中,有三个名为“Models”、“Views”和“Controllers”的文件夹。模型、视图和控制器将在相应的文件夹中实现。
- 模型代表应用程序数据。在本教程中,它是一个存储在应用程序 Web 会话中的“
DataTable
”。 - 视图是特殊的 ASP.NET“aspx”页面,视图的开发与“System.Web.UI.Page”类型的“aspx”页面的开发非常相似。
- 控制器是实现操作的类。每个操作将可选地对应用程序数据执行一些操作,并选择一个视图来显示数据。
- 模型、视图和控制器之间是如何传递信息的?
- 控制器如何访问模型中实现的应用数据应是一个设计问题,应由应用程序开发人员根据业务需求决定。
- 控制器可以通过“ViewData”字典传递要显示给视图的数据。
- 服务器上的应用程序代码如何访问浏览器通过 URL 参数和表单提交传递给服务器的数据?
- 本教程演示了应用程序可以使用熟悉的“Request.QueryString”和“Request.Form”来访问用户输入数据。为了遵循 MVC 方法论,用户输入数据应在控制器中访问,而不是在视图中。
- 如何在 ASP.NET MVC 中访问会话数据?
- 本教程演示了在开发“System.Web.UI.Page”类型的“aspx”页面时,Web 会话的使用方式与平常相同。为了遵循 MVC 方法论,会话数据应在控制器中访问,而不是在视图中。
- 如何在实现视图时使用代码隐藏文件?
- 在 Visual Studio 中,可以通过手动添加视图的代码隐藏文件。关于是否应该为视图使用代码隐藏文件,存在一个热门的讨论,但如果你喜欢使用代码隐藏文件,也可以添加它们。如果我们不使用代码隐藏文件,我们将在视图中使用内联服务器脚本。
历史
这是本文的第一个修订版。