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

ASP.NET WebForms 和 ASP.NET MVC 的和谐共存

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (34投票s)

2009年8月5日

CPOL

11分钟阅读

viewsIcon

229082

downloadIcon

3209

将 ASP.NET MVC 集成到现有的 ASP.NET WebForms 应用程序中。

目录

屏幕截图

简单的演示正在运行。第一个截图来自经典的 WebForms,URL 为:https://:41650/Src/ClassicWebforms/Home.aspx

第二个截图由 "Home" Controller 的 "Index" Action 提供,来自 MVC 应用程序。URL 为:https://:41650/src/Home/Index

The web form page

ASP.NET MVC 页面

The web form page

引言

由于该框架具有吸引人的功能,ASP.NET MVC 的热潮正迅速席卷许多开发人员,例如:

  • 约定优于配置
  • 不要重复自己(又名 DRY 原则)
  • 可插拔架构

其副作用是该框架支持面向测试驱动开发,又名 TDD。本文特别讨论了如何使 ASP.NET MVC 与现有的 WebForms 应用程序协同工作。 这不是学习 ASP.NET MVC 的教程。要学习 ASP.NET MVC,请参阅“参考文献”部分。

需求

每个解决方案都应该有一个与每个开发人员试图解决的相关问题。您可能希望同时运行这两种项目类型的原因有以下几点:

  • WebForms 在将视图逻辑封装到组件方面做得非常好。您可能习惯于使用您已知的技术开发复杂的解决方案。
  • ASP.NET MVC 的可插拔架构支持 TDD。在某些组织中,代码覆盖率策略可能非常严格。那么,还有什么比编写测试更能满足这一策略要求呢?
  • 您可能正在处理一个现有的复杂 ASP.NET 应用程序,并且可能处于迁移阶段。迁移需要增量进行,而不会影响现有功能。

本文没有代码演示,因为代码并非本文的重点。文章的核心是配置活动,这些活动使您能够与 WebForms 和 MVC 和谐共处。

解决方案概述

ASP.NET MVC 框架对可插拔性和可扩展性提供了高度支持。ASP.NET MVC 框架的核心是图中所示的三个程序集,它们扩展了 System.Web

Core Assemblies

此外,这些程序集可以在中等信任的服务器环境中工作,并且是 bin 可部署的。这本质上意味着程序集不需要安装到 GAC(全局程序集缓存)中。您只需引用这些程序集即可。

4 步流程

将 MVC 集成到现有的 WebForms 应用程序中是一个四步过程,如下图所示:

4 Step Process

步骤 1 - 引用必需的库

第一步是找到 ASP.NET MVC 工作所需的库。

  • System.Web.Mvc.dll 程序集存储在:[安装目录]\Microsoft.NET\ASP.NET MVC\Assemblies注意:本例中的[安装目录]c:\[windows]
  • System.Web.Abstractions.dllSystem.Web.Routing.dll 程序集存储在 [安装目录]\Reference Assemblies\Microsoft\Framework\v3.5注意:本例中的[安装目录]通常是[%Program Files%]

本文中的示例将这些文件存储在“Reference_Assembly”目录中。添加后,您需要通过“项目/添加引用”对话框在应用程序中引用这三个核心程序集。请参阅下图。

Solution Structure

注意:经典的 WebForms 位于“ClassicWebForms”文件夹中,而 ASP.NET MVC 视图位于“Views”文件夹中。

步骤 2 - 创建必要的目录

如前所述,ASP.NET MVC 遵循某些约定(以规定方式做事)。ASP.NET MVC 的核心约定之一是存储项目 Controller 和 View 的目录的命名。

在此示例中,我们将使用“Controllers”和“Views”目录来存储相应的 Controller 和 View。

我们在 App_Code 的 Controller 目录中创建了 HomeController.cs。在大型解决方案中,Controller 可能属于其自己的程序集。HomeController 视图文件 Index.aspx 位于 Views/Home 文件夹中。

步骤 3 - 更新 Web.config

第三步是更新 web.config 文件。请参阅下图添加所需的程序集。

前三个程序集是 ASP.NET MVC 程序集。

接下来是向 system.web/pages 部分添加命名空间引用。这样做可以从 ViewPage 访问 System.Web.Mvc 助手、System.LinqSystem.Collections Generics。

Pages Configuration

这里只需要 System.Web.MvcSystem.Web.Mvc.HtmlSystem.Web.Mvc.Ajax 这几个命名空间。但如果您希望使用 LINQ/Generics,其他命名空间也很有用。

最后,您需要注册 UrlRoutingModule。此模块负责将请求的 URL 匹配到正确的路由(Controller/Action)。

Assembly Configuration

步骤 4 - 注册路由

最后,您需要在 Global.asaxApplication_Start 事件中映射路由。

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",                      // Route name
        "{home}/{action}/{id}",         // URL with parameters
        new { controller = "Home", action = "Index", 
              id = "" }                 // Parameter defaults
    );
}

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
}

IIS 部署

托管 ASP.NET MVC Web 应用程序:如果您或您的 Web 托管提供商可以访问 Web 服务器的设置,则可以创建通配符脚本映射以获得完整的路由支持。通配符脚本映射使您能够将每个传入的请求映射到 ASP.NET 框架。请注意,此选项会将每个请求都传递到 ASP.NET 框架(包括图像和 CSS 文件!),并且可能会影响性能。如果您无权访问 Web 服务器的设置,可以修改路由表以使用文件扩展名。URL 将会是这样的:/Home.aspx/Index,而不是 /Home/Index。这样,无需配置 Web 服务器。但是,必须对应用程序的路由表进行一些修改。

如果您的 IIS 7.0 服务器以集成模式运行,则无需配置任何内容。

在 IIS 7.0 中创建通配符脚本映射

以下是在 Internet Information Services 7.0 中启用通配符脚本映射的方法:

  1. 启动 IIS Manager。
  2. 在“Connections”树状视图中,选择一个应用程序。
  3. 在底部工具栏中,确保选择了“Features”视图。
  4. 双击“Handler Mappings”快捷方式。
  5. 在“Actions”窗口中,单击“Add Wildcard Script Map”按钮。
  6. 输入 aspnet_isapi.dll 文件的路径,该文件通常位于:%windir%Microsoft.NETFrameworkv2.0.50727aspnet_isapi.dll
  7. 输入名称 ASP.NET MVC。
  8. 单击“OK”按钮。

完成此操作后,对此特定网站的任何请求都将由 ASP.NET 引擎执行。

在 IIS 6.0 中创建通配符脚本映射

以下是在 Internet Information Services 6.0 中启用通配符脚本映射的方法:

  1. 启动 Internet Information Services IIS Manager。
  2. 右键单击网站并选择“Properties”。
  3. 选择“Home Directory”选项卡。
  4. 在“Application settings”附近,单击“Configuration”按钮。
  5. 选择“Mappings”选项卡。
  6. 在“Wildcard application maps”附近,单击“Insert”按钮。
  7. 输入 aspnet_isapi.dll 文件的路径,该文件通常位于 %windir%Microsoft.NETFrameworkv2.0.50727aspnet_isapi.dll
  8. 取消选中“Verify that file exists”复选框。
  9. 单击“OK”按钮。

遵循这些步骤后,对此特定网站的任何请求都将由 ASP.NET 引擎执行。

让 Visual Studio 提供 MVC 菜单项

实际上,原生的 MVC Web 应用程序项目与您“升级”的 WebForms 项目之间有一个区别。当您想通过“Add New Item”对话框添加视图模板时,Visual Studio 不会提供 MVC View Page 或任何其他 MVC 特定项。而且,当您在 Action 方法内右键单击时,不会出现添加视图的选项。这是因为 Visual Studio 并不认为您拥有一个 ASP.NET MVC 项目。

要解决此问题,您需要为 Visual Studio 添加项目类型提示。通过一些注意事项,这很容易做到。

警告:在进行此操作之前,请备份您的项目文件(即扩展名为 .csproj 的文件)。如果错误地编辑了项目文件,Visual Studio 将无法打开它。

在“Solution Explorer”中,右键单击您的项目名称并选择“Unload Project”。再次右键单击项目名称,然后选择“Edit <yourproject>.csproj”(用您的项目名称替换尖括号中的内容)。您现在将看到 .csproj XML 文件。找到包含分号分隔的一系列 GUID 的 <projecttypeguids> 节点,并在其他节点之前添加以下值:{603c0e0b-db56-11dc-be95-000d561079b0};。不要添加任何额外的空格或换行符。如果您不想手动输入 GUID,可以从任何有效的 ASP.NET MVC .csproj 文件中相应的节复制并粘贴。保存更新后的 .csproj 文件。然后,通过在“Solution Explorer”中右键单击项目名称并选择“Reload Project”来重新加载项目。

如果您收到“This project type is not supported by this installation”的错误,那么您要么错误地键入了 GUID,要么没有在 PC 上安装 MVC Framework。

如果您收到“Unable to read the project file”的错误,请单击 OK,然后再次选择“Reload Project”。不知何故,它似乎能自我修复。

现在,您应该会发现在“Add New Item”对话框中出现了 MVC 特定项,以及通常的 WebForms 项,并且您可以在 Action 方法内右键单击并选择“Add View”。

迁移策略

在将现有的 ASP.NET 应用程序迁移到 ASP.NET MVC 时,应注意以下几点:

  1. 规划流程。不要一次性完成迁移。选择一个区域并进行迁移。
  2. ASP.NET MVC2 (preview) 允许应用程序创建“区域”。区域提供了一种分组 Controller 和 View 的方法,以便可以相对独立地构建大型应用程序的子部分。
  3. 为您的新区域设计路由。
  4. 迁移视图。WebForms 应用程序有代码隐藏文件,这在 ASP.NET MVC 中是不被推荐的。但在这种情况下,我认为您可以保留代码隐藏文件并使应用程序正常工作。
  5. 作为一项实践,为视图中引发的每个事件创建 Controller 并添加 Action。
  6. 由于抽象是 MVC 设计的关键,您可以在功能迁移过程中编写单元测试用例。
  7. 对于单元测试,将代码隐藏中的所有具体依赖项抽象出来,并将它们移到 Controller 中。一些依赖项是 Session、Cache、HttpContext(相关方法)、Repository 等。
  8. 测试通过后,请自行判断是否要舍弃代码隐藏。
  9. 继续处理其余的功能。

处理旧版 URL

如果您正在将现有网站迁移到 ASP.NET MVC,您可能需要支持您的客户可能已收藏的现有 URL。这可能有很多原因。您的客户可能是高端客户,您不想因为升级了网站而让他不高兴。

我曾了解过这种技术,但这个示例是从 Mike 的网站改编而来的。所以,归功于他。请在“参考文献”部分找到引用的 URL。

这可以通过创建自定义路由来实现。所有路由都派生自 RouteBase。让您的旧版路由派生自 RouteBase 并覆盖 GetRouteData(..) 方法。例如,假设您有一个 URL http://yourdomain.com/profile.aspx?id=specialid。以下是一个简化的示例,用于理解该过程。

using System;
using System.Web;
using System.Web.Routing;

namespace CoolControls.Routes
{
  public class LegacyUrlRoute : RouteBase
  {
       public override RouteData GetRouteData(HttpContextBase httpContext)
       {
          const string status = "301 Moved Permanently";
          var request = httpContext.Request;
          var response = httpContext.Response;
          var name = "";
          var legacyUrl = request.Url.ToString();
          var newUrl = "";
          var id = request.QueryString.Count != 0 ? request.QueryString[0] : "";
          
          if (legacyUrl.ToLower().Contains("profile.aspx"))  
          {
                var rep = new ProfileRepository();
                var pro = rep.GetProfile(Convert.ToInt32(id));
                
                name = pro.Name;
                
                newUrl = "profile/" +  name;
                response.Status = status;
                response.RedirectLocation = newUrl;
                response.End();
          }
            return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, 
                                    RouteValueDictionary values)
    {
          return null;
    }
  }
}

HTTP 状态码会告知用户代理(浏览器和搜索引擎)它们正在查找的资源已移动到另一个位置。它不应对现有链接产生任何影响。

如果请求的 URL 不包含“profile.aspx”,则返回 null,以便 UrlRoutingModule 可以继续尝试在 RouteTable.Routes 集合中的其他路由匹配该 URL。

最后一项任务是在应用程序的 Global.asaxRouteTable 中注册 LegacyUrlRoute。这在 Global.asax 方法的开头完成。

public static void RegisterRoutes(RouteCollection routes)
{
     ......
     routes.Add(new LegacyUrlRoute());
     .......
}

现在,如果请求旧 URL(例如 http://mysocialnetwork.com/profile.aspx?id= 101),它会自动重定向到 http://mysocialnetwork.com/profile/rajesh,并向用户代理发送正确的标头。您可以通过 Fiddler 等 HTTP 调试器进行检查。

关注点

Web Forms 和 ASP.NET MVC 之间的和谐共存比我想象的要简单。总的来说,这是一次极好的学习经历,希望在未来我可能进行的迁移项目中会有所帮助。

未来文章

接下来的几篇文章将重点介绍使用基本的测试驱动方法构建一个端到端的应用程序,并遵循最佳实践。

结论

一些读者可能不同意某些观点,例如在 ASP.NET MVC 中使用代码隐藏文件。我本人也不赞成。但迁移是一个可以使用它的领域,它为开发人员/设计人员留下了根据需求和时间限制进行迁移的选择。所以,请不要把它当作“刻在石头上的话”。请自行判断。

参考文献

历史

  • 2009 年 8 月 19 日 - 添加了对旧版路由的支持。
  • 2009 年 8 月 11 日 - 添加了“让 Visual Studio 在菜单中提供 MVC 项”。
  • 2009 年 8 月 7 日 - 添加了“迁移策略”。
  • 2009 年 8 月 6 日,下午 3:30 - 添加了“IIS 部署”。
  • 2009 年 8 月 6 日 - 创建了文章的第一个版本。
© . All rights reserved.