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

Webforms 与 MVC:为什么 MVC 更胜一筹?

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (87投票s)

2014年9月21日

CPOL

10分钟阅读

viewsIcon

397976

在本文中,我们将解释 ASP.NET MVC,并将其与 Webforms 进行比较。

目录

先决条件

引言

ASP.NET Webform 后台代码——优势与弊端

问题 1:基于视图的解决方案,用于基于动作的需求

问题 2:糟糕架构的副作用:——紧密耦合

问题 3:HTML 并非唯一的响应类型

问题 4:视图和数据的灵活组合

问题 5:将后台代码转换为用于单元测试的普通类

所以解决方案是 MVC?

我们会失去什么?

来自一位父亲的请求

感谢我的女儿 Sanjana 创作了上面的图片。如果您能从 Facebook https://#/photo.php?fbid=685327044884788 分享这张图片,我将不胜感激,这将有助于她未来成为一名漫画家。我只想让她知道她的绘画天赋有多好,并应该考虑将其作为职业道路。

顺便说一句,上面的图片将帮助您直观地了解为什么 MVC 优于 Webforms。当您阅读本篇逐步学习 MVC 的文章时,这张图片将帮助您将各项内容联系起来。

先决条件

在本文中,我将频繁使用两个术语:ASP.NET Web Forms 和 ASP.NET MVC。许多开发人员认为 ASP.NET 与 MVC 不同。但事实是,MVC 是一种架构编码风格,而 ASP.NET 是一个框架。如果您属于认为 ASP.NET 与 MVC 不同的人群,那么我诚挚的建议是先阅读本文,以避免进一步的混淆 http://computerauthor.blogspot.in/2014/08/aspnet-vs-mvc-vocabulary-confusion_15.html

引言

如果您关注微软最近的议程,您会清楚地看到他们正在专注于 MVC、MVC 和 MVC。那么问题来了,为什么微软如此热衷于放弃像 ASP.NET Webform 这样成功的东西,并说服微软 Web 开发社区使用 ASP.NET MVC。

这正是本文将重点关注的内容。

ASP.NET Webform 后台代码——优势与弊端

如果您仔细观察 ASP.NET webform 技术,它是一种用于 web 开发的 RAD / 可视化方法。换句话说,开发人员在设计器上拖放用户控件,VS 工具则在后台代码中编写代码。

因此,换句话说,当您在设计器上拖放一个按钮控件时,就会创建一个按钮对象,开发人员可以在按钮对象的单击事件中编写代码。

public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            // Developers write code here
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            // Developers write code here
        }
    }

因此,当开发人员拖放这些 UI 元素,双击以在前端获取事件,在这些事件中编写逻辑等时。在后端,微软巧妙而安静地在 ASPX.CS 分部类文件中编写了逻辑。

现在,这个分部后台代码文件是 ASP.NET Webform 项目更快交付成功的关键,因为开发人员被封装了许多技术细节,如事件、委托、HTTP 协议 POST、GET、会话管理等。您可能想阅读这篇文章 为什么微软有分部类?以及微软 UI 成功案例。

但由于后台代码的定位和调用方式,它存在 5 个严重问题。因此,让我们讨论这 5 个问题以及 MVC 如何帮助解决这些问题。

问题 1:基于视图的解决方案,用于基于动作的需求

网站最终是由终端用户使用的。终端用户带着特定目的访问网站,并通过操作表达他们的目的。例如,如果有人在购物门户网站购物,他将通过以下操作表达他的目的:-

  • 购买产品。
  • 打印发票

现在,这些操作通过按钮点击、右键点击或通过浏览器 URL 等方式进行通信。由于这种基于动作的结构,HTTP 协议被选用于 Web,因为它具有 POST、GET、PUT、DELETE 等动作,可以更清晰地传达终端用户的目的。这也使得 REST 成为处理终端用户请求的流行方式。因此,从逻辑上讲,如果我们将这些动作映射到程序的 方法/函数,那将更有意义,并且也能保持架构的简单。

但微软别无选择,他们希望支持 RAD 概念,或者我们可以称之为可视化编程概念,因此他们最终为基于动作的结构提供了一个基于视图的解决方案。

所以对于 Web Forms,请求的流程变得有些奇怪(有关可视化效果,请参阅上面的图表):-

  • 最终用户发送带有 HTTP POST / GET 等操作的请求。
  • IIS Web 服务器将此请求映射到视图。
  • 视图调用页面生命周期,遍历事件,然后调用相应的动作
  • 最后,动作将结果以 HTML 格式发送给最终用户浏览器。

微软最终为基于动作的需求选择了基于视图的架构。因此,架构本身在逻辑上与终端用户基于动作的方法不符。换句话说,如果终端用户发送一个“购买”动作,它首先会进入一个像“Shopping.aspx”这样的视图,该视图反过来启动“Shopping.aspx.cs”,执行一个复杂的页面生命周期,然后执行满足终端用户请求的动作。

这就像是在打草惊蛇。最终请求在复杂的页面生命周期完成后才映射到实际动作。那么,我们能否将其构建为面向动作的架构,而不是面向视图的架构呢?或者我可以重新表述为 **“我们如何才能构建一个动作优先的结构,而不是视图优先的结构?”**。

那么,我们能否先处理动作,然后动作选择视图呢?这将使流程更加逻辑和清晰。这正是 MVC 架构所做的。首先,请求到达控制器中的一个动作,然后控制器使用适当的模型调用视图。

问题 2:糟糕架构的副作用:——紧密耦合

一旦您开始使用错误的架构,您就会不断调整,最终导致严重的副作用。在这种情况下,同样的事情正在发生。后台代码在物理上看起来在不同的文件中,但实际上从未解耦,即 ASPX.CS 无法与 ASPX 分离。

简单来说,我无法轻松地将“Customer.aspx.cs”附加到“CustomerDetailed.aspx”。后台代码与视图紧密耦合。它不可重用。

如果您分析后台代码相对于项目其他层的数量,它在大小和复杂事件方面都是巨大的。这使得代码难以阅读,并且从长远来看难以维护。

因此,如果我们可以将基于视图优先的架构改为基于动作优先的架构,那么我们就可以将相同的动作代码与不同的视图重用。例如,如果终端用户发送一个“显示”动作,它可以调用“DisplayDesktop.aspx”或根据设备类型显示“DisplayMobile.aspx”。

因此,在 MVC 动作中,我们可以根据情况调用“MobileView”或“NormalView”,下面是相同的示例代码。现在想象一下在 Webform 的后台代码中实现这一点,这非常困难,对吧。

public ActionResult Index(string DeviceType)
{
           if (viewType == "Mobile")
            {
                return View("MobileView");
            }
            else
            {
                return View("NormalView");
            }
}

问题 3:HTML 并非唯一的响应类型

由于视图和后台代码之间的紧密耦合,Webform 中的响应类型也是固定的,它默认是 HTML。如果您希望更改它,您需要调整 Content-type 和“Response.End”方法等,这非常繁琐。

如果我们创建“动作”优先结构,那么动作拥有世界上所有的自由来决定应该发出什么样的响应类型。这使得我们的系统在相同动作与不同输出方面更具灵活性。

下面是一个简单的 MVC 动作代码,它根据传递给动作的值发送 JSON 或 HTML 结果。这种灵活性很难通过 Webform 视图实现,因为它们只用于发出 HTML。

public ActionResult Index(string viewType)
{
            if (viewType == "JSON")
            {
                return Json(new Customer(), JsonRequestBehavior.AllowGet);
            }
            else
            {
                return View("DisplayCustomer", new Customer());
            }
}

问题 4:视图和数据的灵活组合

当我们向用户发送响应时,它是视图(显示)和数据(模型)的组合。Webform 是一个视图优先的架构,因此视图决定连接哪个模型,这使得视图不够灵活,并且视图也参与复杂的决策制定。这显然违反了 SOLID 原则中的 SRP,在此处阅读更多关于 SOLID 原则

但是,如果我们将架构设计为“动作优先”,那么第一个请求会到达动作,动作会选择模型和视图来发送不同的响应。

在 MVC 动作中,您可以像下面所示那样编写代码。您可以选择相同的模型并将其与不同的视图关联。例如,在下面的代码中,我们采用了“customerdata”模型并将其与“DetailCustomer”视图关联,而在其他情况下,相同的模型又与“Customer”视图关联。

public ActionResult Index(string ViewName,Customer customerdata)
{
            if (ViewName == "Detailed")
            {
return View("DetailCustomer",customerdata);
            }
            else
            {
                return View("Customer",customerdata);
            }
}

通过 Webform 实现这种灵活性非常困难,因为调用发生在视图本身,然后您需要在页面生命周期中编写所有决策逻辑并重定向到其他视图,这使得实现不够清晰。

问题 5:将后台代码转换为用于单元测试的普通类

Webform 中的后台代码是一个非常典型、笨重且庞大的部分类,无法直接在简单的 C# 代码中实例化。请记住,Webform 屏幕继承自“Page”类。这个 Page 类无法直接创建,因为它有很多依赖项。

public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public void Button1_Click(object sender, EventArgs e)
        {
            Session["SomeSession"] = "Is this set";
        }
    }

现在,您接下来会想到为什么要实例化这个页面类。我希望实例化这个页面类的一个地方是用于单元测试。我希望调用按钮点击方法的动作并测试会话变量是否正确设置,视图状态是否正确等。

但是,如果您尝试像下面代码所示那样做,您将得到下面所示的奇怪代码。请注意那些传递给按钮点击方法的丑陋事件参数。

[TestMethod]
public void TestMethod1()
{
            WebApplication22.WebForm1 obj = new WebApplication22.WebForm1();

            obj.Button1_Click(this, new EventArgs());
}

当您调用它时,它会要求更多东西,这使得 UI 单元测试变得不可能。

在 MVC 中,这变成了一个普通类。一个可以在简单单元测试项目中实例化的类,您可以轻松测试会话、viewbag、tempdata 等各个方面。

public class HomeController : Controller // ß this class is simple 
{
        public ActionResult Index()
        {
            Session["SomeSession"] = "Is this set";
            return View("SomeView");
        }
}

所以解决方案是 MVC?

因此,要从基于视图的架构更改为基于动作的 MVC 架构,我们需要进行以下结构性更改(上图提供了相应的可视化视图):-

  • 将后台代码移动到一个控制器类中,并将所有事件转换为可以称为动作的方法。
  • 中间层成为模型,提供数据和业务逻辑。
  • 视图只负责显示、定位和布局。
  • DAL 和其他层没有太大变化,因为它们与后台代码问题没有直接联系。

所以,采用 MVC 架构,我们有以下三步流程:-

  • 最终用户将请求发送到应用程序。应用程序将请求路由到控制器。控制器是一个逻辑实体,它将动作分组在一起。
  • 控制器将该请求映射到特定的动作。
  • 现在,动作有两个任务:首先,它需要根据动作访问适当的数据;其次,该数据必须连接到正确的视图。动作创建模型对象并将模型连接到视图以发送最终响应。

我们会失去什么?

ASP.NET WebForm 的最大优势在于 RAD / 可视化编程。尽管这是一种快速而粗糙的做事方式,但它能帮助您更快地完成应用程序,让您的客户满意并按时交付。您可以阅读这篇讨论您在 MVC 中将错过什么的文章 https://codeproject.org.cn/Articles/808297/Things-you-will-miss-in-ASP-NET-MVC-as-an-ASP-NET

Webforms 在 2000 年是微软的正确选择,因为它希望将习惯了 RAD 编程的 VB6、VF、VC++ 开发人员迁移过来。我认为 Webform 已经实现了其创建目标,现在是时候转向更好、更逻辑的架构,即 MVC 了。

因此,如果您确信 MVC 是未来的方向,您可以通过观看下面的视频在两天内(即 16 小时)学习 MVC。

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

另请阅读并学习 Web Form vs MVC 文章。

© . All rights reserved.