3 Musketeers:使用 HTTPHandler 实现 Model, View 和 Controller - 第 1 部分






4.59/5 (21投票s)
3 Musketeers:使用 HTTPHandler 实现 Model, View 和 Controller - 第 1 部分
已更新,包含设计模式、.NET 最佳实践和 Model View Presenter 的链接
目录
- 引言和目标
- 警告
- 先决条件
- 世界关于行动、格式和数据
- 紧耦合问题及解决方案
- 在 ASP.NET 中实现 MVC
- 简单的 Musketeer 模型
- 第二位 Musketeer:视图
- 第三位强硬的 Musketeer:控制器
- Web.Config 文件和 HttpHandler 部分
引言和目标
在本节中,我们将逐步了解 ASP.NET MVC 的基础知识,然后了解如何使用 HttpHandler
在 ASP.NET 中实现相同的功能。
其他文章
有关设计模式,请单击 此处
有关 .NET 最佳实践,请单击 此处
有关 Model View Presenter,请单击 此处
警告
Microsoft 已发布 ASP.NET MVC 框架,第二个教程将对此进行介绍。在本教程中,我们将尝试了解如何在纯 ASP.NET 中实现 MVC。这将使我们在看到现成的 MVC ASP.NET 框架时,对基础知识有更清晰的认识。
先决条件
我们建议您阅读 HttpHandlers
和 HttpModules
的概念。您可以阅读我关于同一主题的文章 此处。
世界关于行动、格式和数据
当我们谈论任何项目时,都与行动有关。根据行动,用户会以某种格式看到一些数据。让我们来看一个下面显示的小型三行客户项目需求
- 用户访问主页。
- 用户可以查看包含销售数据的客户。
- 用户可以查看不包含销售数据的客户。
从需求中,您可以典型地区分三个实体:一个是行动,第二个是根据行动而定的视图,第三个是为特定行动和格式显示的数据。
上图显示了行动、视图和模型/数据如何协同工作以满足我们的需求。根据上述需求,我们有三个行动
- 用户可以访问主页
- 他/她可以查看带有销售额的客户
- 他/她可以查看不带销售额的客户
每个行动都映射到一个需要显示的视图/网页。例如,当用户执行 GotoHome
行动时,他将看到 Home.aspx 页面。每个视图都将使用模型来获取数据。目前对于 Home.aspx,没有模型,但客户视图将连接模型以显示数据。
我们得出的最终表格如下:
操作 | 视图 | Data |
GotoHome | Home.aspx | 不适用 |
ViewCustomerWithOutSales | DisplayCustomerWithOutSales.aspx | 客户模型 |
ViewCustomerWithSales | DisplayCustomerWithSales.aspx | 客户模型 |
紧耦合问题及解决方案
如果我们仔细观察上述问题,我们可以发现两个很大的紧耦合:一个是行动与视图的耦合,另一个是视图与模型的耦合(即数据)。在实际场景中,我们总是可以考虑许多可以绑定到同一模型的视图,以及导致相同视图的许多行动。因此,如果我们将它们解耦,我们可以避免冗余的编码并获得更好的可重用框架。
因此,我们将协调工作交给第三方,即控制器。现在,所有行动都发送到控制器。控制器的作用是更新和加载模型,然后根据行动将模型与视图绑定。
在 ASP.NET 中实现 MVC
我们将以之前讨论过的三行客户项目为例。下面是事物的可视化视图以及它们的移动方式。如果行动是 GotoHome
,则显示 Home.aspx 页面,其中包含两个链接:一个用于查看带销售额的客户,另一个用于查看不带销售额的客户。如果行动是 ViewCustomersWithOutSales
,它将显示一个简单的视图,其中显示客户详细信息而不显示销售额。如果行动是 ViewCustomerWithSales
,它将显示客户及其销售额的明细。
简单的 Musketeer 模型
首先,我们来理解 MVC 的模型部分。这是最简单的开始部分,然后我们将继续处理更复杂的东西,如控制器和视图。模型只不过是一个类,它将为视图提供必要的数据源。
下面的代码显示了客户数据。它有三个属性
- 客户姓名
- 地址
- 客户的销售金额
public class clsCustomer
{
private string _strCustomerName;
private string _strAddress;
private double _dblSales;
public string CustomerName
{
set
{
_strCustomerName = value;
}
get
{
return _strCustomerName;
}
}
public string Address
{
set
{
_strAddress = value;
}
get
{
return _strAddress;
}
}
public double Sales
{
set
{
_dblSales = value;
}
get
{
return _dblSales;
}
}
}
相应地,我创建了一个集合,我将在其中加载一些虚拟记录。在实际项目中,此类将连接到数据库加载数据。为了使文章保持简单,我已将数据硬编码到客户集合中。
public class clsCustomers : CollectionBase
{
public clsCustomers()
{
}
public void LoadCustomers()
{
Add("Shiv", "Mulund", 20);
Add("Raju", "Mumbai", 20);
Add("Manish", "Delhi", 20);
Add("Lalu", "Nepal", 20);
Add("Khadak", "Ratoli", 20);
Add("Shaam", "Ghatkopar", 20);
}
void Add(string strCustomerName, string strAddress, double dblSales)
{
clsCustomer objCustomer = new clsCustomer();
objCustomer.Address = strAddress;
objCustomer.CustomerName = strCustomerName;
objCustomer.Sales = dblSales;
List.Add(objCustomer);
}
}
第二位 Musketeer:视图
我们在视图中有三个文件
- Home.aspx
- DisplayCustomerWithOutSales.aspx
- DisplayCustomerWithSales.aspx
Home.aspx 非常简单,只包含链接。
DisplayCustomerWithOutSales.aspx 将绑定控制器提供的客户数据。控制器将通过 ASP.NET 上下文传递数据。
public partial class DisplayCustomerWithOutSales : System.Web.UI.Page
{
clsCustomers objCust;
protected void Page_Load(object sender, EventArgs e)
{
objCust = (clsCustomers) Context.Items["Customers"];
dtgWithOutSales.DataSource = objCust;
dtgWithOutSales.DataBind();
}
}
DisplayCustomerWithSales.aspx 也有相同的代码。您可以在随本教程提供的源代码中看到这一点。
第三位强硬的 Musketeer:控制器
我们建议您阅读 HttpHandlers
和 HttpModules
的概念。您可以阅读我关于同一主题的文章 此处。
对于每个行动,我们都有一个控制器类。在实际项目中,您可以将多个行动映射到一个控制器类。为了使教程简单,我为每个行动保留了一个控制器。
控制器将执行三件事
- 加载模型。
- 将模型传递给视图。
- 加载视图并将其发送给最终用户。
以下是主页处理程序类。由于它没有与任何数据绑定,因此它不调用任何模型,只调用视图。
public class clsHomeHandler : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
context.Server.Transfer("./view/Home.aspx");
}
public bool IsReusable
{
get
{
return true;
}
}
}
无销售额的客户控制器类:它加载模型并将模型数据添加到上下文中。如果您还记得,在视图代码片段中,数据是从上下文获取的。之后,它只加载视图,即 DisplayCustomerWithSales.aspx。
public class clsHandlerCustomerWithSales : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
clsCustomers objCustomers = new clsCustomers();
objCustomers.LoadCustomers();
context.Items.Add("Customers", objCustomers);
context.Server.Transfer("./view/DisplayCustomerWithSales.aspx");
}
public bool IsReusable
{
get
{
return true;
}
}
}
第三个控制器是无销售额的客户。代码是不言自明的,因为它与之前的代码片段逻辑匹配。
public class clsHandlerCustomerWithOutSales : IHttpHandler
{
public void ProcessRequest(System.Web.HttpContext context)
{
clsCustomers objCustomers = new clsCustomers();
objCustomers.LoadCustomers();
context.Items.Add("Customers", objCustomers);
context.Server.Transfer("./view/DisplayCustomerWithOutSales.aspx");
}
public bool IsReusable
{
get
{
return true;
}
}
}
Web.Config 文件和 HttpHandler 部分
在 Web.config 文件中,我们将行动与处理程序进行映射。目前,行动就是路径。
<httpHandlers>
<add verb="*" path="GoToHome" type="Controller.clsHomeHandler, Controller"/>
<add verb="*" path="ViewCustomersWithOutSales"
type="Controller.clsHandlerCustomerWithOutSales, Controller"/>
<add verb="*" path="ViewCustomersWithSales"
type="Controller.clsHandlerCustomerWithSales, Controller"/>
</httpHandlers>
因此,GoToHome
调用主页,如下图所示
ViewCustomersWithSales
行动调用带有销售额的数据:
行动 ViewCustomerWithOutSales
调用不带销售额的客户数据
历史
- 2008 年 11 月 14 日:初始发布
如需进一步阅读,请观看以下面试准备视频和分步视频系列。