65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (21投票s)

2008年11月14日

CPOL

6分钟阅读

viewsIcon

90576

downloadIcon

489

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

已更新,包含设计模式、.NET 最佳实践和 Model View Presenter 的链接

目录

引言和目标

在本节中,我们将逐步了解 ASP.NET MVC 的基础知识,然后了解如何使用 HttpHandler 在 ASP.NET 中实现相同的功能。

其他文章

有关设计模式,请单击 此处

有关 .NET 最佳实践,请单击 此处

有关 Model View Presenter,请单击 此处

警告 

Microsoft 已发布 ASP.NET MVC 框架,第二个教程将对此进行介绍。在本教程中,我们将尝试了解如何在纯 ASP.NET 中实现 MVC。这将使我们在看到现成的 MVC ASP.NET 框架时,对基础知识有更清晰的认识。

先决条件

我们建议您阅读 HttpHandlers HttpModules 的概念。您可以阅读我关于同一主题的文章 此处

世界关于行动、格式和数据

当我们谈论任何项目时,都与行动有关。根据行动,用户会以某种格式看到一些数据。让我们来看一个下面显示的小型三行客户项目需求

  • 用户访问主页。
  • 用户可以查看包含销售数据的客户。
  • 用户可以查看不包含销售数据的客户。

从需求中,您可以典型地区分三个实体:一个是行动,第二个是根据行动而定的视图,第三个是为特定行动和格式显示的数据。

上图显示了行动、视图和模型/数据如何协同工作以满足我们的需求。根据上述需求,我们有三个行动

  1. 用户可以访问主页
  2. 他/她可以查看带有销售额的客户
  3. 他/她可以查看不带销售额的客户

每个行动都映射到一个需要显示的视图/网页。例如,当用户执行 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 的模型部分。这是最简单的开始部分,然后我们将继续处理更复杂的东西,如控制器和视图。模型只不过是一个类,它将为视图提供必要的数据源。

下面的代码显示了客户数据。它有三个属性

  1. 客户姓名
  2. 地址
  3. 客户的销售金额
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:视图

我们在视图中有三个文件

  1. Home.aspx
  2. DisplayCustomerWithOutSales.aspx 
  3. 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 的概念。您可以阅读我关于同一主题的文章 此处

对于每个行动,我们都有一个控制器类。在实际项目中,您可以将多个行动映射到一个控制器类。为了使教程简单,我为每个行动保留了一个控制器。

控制器将执行三件事

  1. 加载模型。
  2. 将模型传递给视图。
  3. 加载视图并将其发送给最终用户。

以下是主页处理程序类。由于它没有与任何数据绑定,因此它不调用任何模型,只调用视图。

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 日:初始发布

如需进一步阅读,请观看以下面试准备视频和分步视频系列。

© . All rights reserved.