将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

时间:2021-03-20 02:59:16

如果您多年来一直都在使用 ASP.NET,很有可能您已使用适用于 Microsoft .NET Framework 1.1 的 Visual Studio 2003 编写过解决方案。 近年来,更新且功能丰富的 .NET Framework 2.0、3.0 和 3.5 版本相继推出,您可能想知道从可信赖的 1.1 Framework 应用程序升级到上述某个版本是否值得或切实可行。

如今,全新的 .NET Framework 4 正受到全世界开发人员的拥戴,认真考虑迁移问题也许比任何时候更紧迫。 如果决定迁移,您大可放心,Microsoft 已提供有用的工具帮助完成这样的任务,确保实现 ASP.NET 应用程序的现代化,以便充分利用最新的 NET Framework 的创新功能。 我会具体向您介绍如何通过将 ASP.NET 1.1 解决方案迁移到 Visual Studio 2010(Professional、Premium 或 Ultimate)使之再次焕发活力,确保这些解决方案适用于 .NET Framework 2.0、3.0、3.5 或 4 版本。

为什么要迁移?

即使您的目标仅仅是保持现有的 ASP.NET 1.1 站点,支持和扩展性选项也在逐渐减少。 作为一位 1.1 开发人员,您应注意到 Microsoft 已于 2008 年 10 月 14 日停止为 Visual Studio 2003 提供主流支持, 并表示不再发行针对 Visual Studio 2003 或 .NET Framework 1.1 的 Service Pack。 (但 Microsoft 在 2013 年 10 月之前仍将继续为 Visual Studio 2003 提供扩展支持。) 8,

您可能会非常担忧,越来越多的第三方供应商已停止提供或停止支持可基于 .NET Framework 1.1 运行或扩展 Visual Studio 2003 IDE 的组件。 的确,您的 .NET Framework 1.1 Web 应用程序和 Visual Studio 2003 IDE 已越来越不受重视并且即将被淘汰。

但也存在其他原因。 .NET Framework、C#、Visual Basic .NET 编程语言以及 Visual Studio IDE 的增强功能已大量出现,通过将 .NET 1.1 站点迁移到 .NET 2.0 或更高版本(以下称为 2.0+),您将最终可以使用最新的工具和技术以及所有新式语言和框架功能(例如母版页、AJAX、Windows Communication Foundation [WCF]、Silverlight、LINQ、分部类、泛型、lambda 表达式和匿名方法)来增强上述语言和工具,这些框架功能已得到领先的 .NET 开发人员的拥戴。 通常,您为 ASP.NET 应用程序选择的目标框架版本越高,就能够轻易获得更大的潜力和更强的功能。 您不仅可以从 Microsoft 本身获得坚实支持(到撰写本文时,Microsoft 已为所有 2.0+ 框架版本提供主流支持),还可以从活跃的开发人员论坛和第三方工具供应商处获得支持。 此外,还有涵盖最新技术的所有方面的书籍以及提供视频课程、博客、白皮书和其他培训选择的网站可供利用。

卓越的最新 Visual Studio 2010 IDE 本身就是您选择迁移的充分理由。 Visual Studio 2010 IDE 是 Visual Studio 2003 IDE 的下一代产品,支持 IntelliTrace 等新功能,可使用能有效提高编程工作效率的各种功能强大的第三方插件来实现扩展。 当很小一部分用户出于各种原因需要继续使用 Visual Studio 的较旧版本时,由于 Visual Studio 2010 面向 2.0+ 框架,因此几乎不需要并行运行 Visual Studio 2005 和 Visual Studio 2008。 但与 Visual Studio
2005 及 Visual Studio 2008 一样,Visual Studio 2010 也不适用于 1.1 框架。 这意味着您必须继续运行 Visual Studio 2003,或者必须将 ASP.NET 1.1 项目迁移到更新的框架。

最终结果就是,仅具有 1.1 框架经验的开发人员在职场上可能不会像具有 2.0+ 框架经验的开发人员那么抢手。 开发人员职位竞争比较激烈,因此您需要尽可能使自己更具有优势;如果在您的代码中充分利用更新的框架功能,将可增强您作为专业软件开发人员的候选资格和可信度。

迁移问题

为什么从 Visual Studio 2003 以来,并非每个用户在任何一个主要 Visual Studio 和 .NET Framework 版本发行期间即已从 ASP.NET 1.1 进行迁移? 一个原因就是开发人员需要实施 Visual Studio 2005 提供的 ASP.NET 1.1 至 ASP.NET 2.0 迁移选项。 这听起来并不那么糟糕,但应意识到,当首次部署 Visual Studio 2005 时,需要将 ASP.NET 1.1 项目转换为全新的 Web 项目类型。 这意味着,构建 ASP.NET 1.1 站点时所基于的整个体系结构必须已经过精心改进和严格的回归测试。 许多开发人员认为该过程类似于从头开始重新编写站点,会带来看似无法逾越的成本和技术挑战。 因此,决策者通常都会将 ASP.NET 1.1 站点原样保留。

若要更好地领会此 ASP.NET 1.1 至 ASP.NET 2.0 的迁移挑战,必须了解如何使用项目驱动的文件-文件夹配置来组织所有 ASP.NET 1.1 Web 项目。 该项目类型最初被称为“2003 Web 项目模型”,现在称为 Web 应用程序项目 (WAP)。 发行 Visual Studio 2005 后,Microsoft 引入一个文件夹驱动的全新项目类型,该类型专为 .NET Framework 2.0 而设计。 该项目类型最初被称为“2005 Web 项目模型”,现在称为网站项目 (WSP)。 (感到困惑吗? 我们借助简单的技巧,按它们的字母顺序记住缩写词:WAP 早于 WSP 出现,正如 Visual Studio 2003 早于 Visual Studio 2005 一样。)

在此不再赘述 WAP 和 WSP,总之,Microsoft 最初计划通过包含的转换向导将所有迁移的 1.1 Web 应用程序更改为 WSP。 相关开发人员立即对此提出异议,因为最初的 WAP 项目类型可提供更新的 WSP 项目类型所欠缺的特定技术和性能优势。 当开发人员、管理者和利益相关者获悉,Microsoft 仅提供 ASP.NET 1.1 WAP 至 ASP.NET 2.0 WSP 的迁移选项,经证实这一举措既耗时又成本高昂,尤其对复杂站点更是如此,ASP.NET 开发社区很快就此表现出强烈不满。 有关此类迁移过程中引起的技术问题的详细信息,包含在一篇单独的由多部分内容组成的文章中;您可以阅读 MSDN 库文章“常见的 Web 项目转换问题及解决方案”(msdn.microsoft.com/library/aa479312) 以了解相关的详细信息。

幸运的是,Microsoft 迅速做出响应,很快在 Visual Studio 2005 SP1 中提供经过修订的转换向导。 这一次,转换向导可以将 ASP.NET 1.1 WAP 转换为 ASP.NET 2.0 WAP。 但许多开发人员错过了了解该迁移选项的机会,因而无法再对其进行深入研究。 在 Visual Studio 2010 中,转换向导既能将 ASP.NET 1.1 WAP 转换为 ASP.NET 2.0+ WAP(这意味着转换为 2.0+ 后,即能用于 2.0、3.0、3.5 或 4.0 版),同时仍会提供迁移到旧版 Web 应用程序的机会。 (您不能使用 Visual Studio 2010 转换向导将 ASP.NET 1.1 应用程序转换为 WSP 应用程序,您可能也不希望如此;您必须有权访问 SP1 之前发布的原始 Visual Studio 2005 中提供的转换向导。)

您可能会注意到,无论何时在 Visual Studio 2010 中启动新项目,都可以选择是创建 WAP 还是 WSP。 Microsoft 承诺为当前及未来的所有 .NET Framework 版本同时提供 WAP 和 WSP 支持。

过程

使用 Visual Studio 2010 迁移 ASP.NET 1.1 应用程序包含以下主要步骤(我将详细介绍每项步骤):

  • 运行转换向导。
  • 设置目标框架和启动页。
  • 编译并修复。
  • 将页面和用户控件转换为分部类。
  • 编译并修复。

运行转换向导 若要使用转换向导将 1.1 WAP 转换至 2.0+ WAP(我们的目标),必须在安装 Visual Studio 2010 期间安装 Visual Web Developer 选件。 如果未安装该选件,则需要进行添加,方法是重新运行 Visual Studio 2010 安装程序并使用“更改或删除 Microsoft Visual Studio 2010”选项,选择“添加”或“删除”功能,然后确保 Visual Web Developer 功能被选中(请参阅图 1)。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 1 确保在启动转换向导之前已安装 Visual Web Developer 组件

如果未安装 Visual Web Developer,转换向导仍会启动并运行。 该向导将可以转换解决方案中除 Web 项目之外的所有项目。 建议您务必安装 Visual Web Developer 以便转换 Web 项目。

执行转换任务之前,有必要确保您的应用程序不仅已构建且能够良好地运行,还应尽可能条理清晰。 因此:

  1. 删除任何未使用或不需要的文件,只保留 Web 应用程序的基本组件,使应用程序清楚明了。
  2. 确保在编译解决方案中的每个项目时均未发生编译时错误。
  3. 虽然建议将解决方案添加到源代码控制中,但如果尚未按此方式配置,请务必确认没有专门从存储库签出任何文件。 将解决方案添加到源代码控制下后,您将可以在转换过程完成后检查向导所做的特定更改。
  4. 确保未将源代码控制范围之外的任何文件或文件夹标记为只读。 这样,向导将可以根据需要更新这些文件/文件夹。
  5. 创建备份。 如果在虚拟机中运行解决方案,最好是仅备份整个虚拟机(或创建虚拟机快照)。 否则,备份整个应用程序(包括所有依赖项)。 如果不确定有哪些依赖项,最好查看应用程序的解决方案 (.sln) 文件及各个项目 (.proj) 文件(这些是可直观检查的文本文件)。 许多 ASP.NET 解决方案包含的项目指向网络位置或者 Web 根目录或应用程序文件夹之外的文件夹。 如果您希望从备份文件还原应用程序,不备份这些依赖项可能会导致严重后果。 请注意,完整的迁移过程会对应用程序中的每个项目进行更改,因此在开始之前了解应用程序的依赖项对您有帮助。 此外,如果使用在多个 ASP.NET 1.1 应用程序之间共享的项目,则应意识到,一旦迁移这些解决方案,就不能再在 Visual Studio 2003 中打开。 如果在团队环境下工作,更改共享项目还会影响团队成员的解决方案,这可能会终止对已转换项目的引用。 因此,无论是在项目还是团队间共享,应通过为共享项目创建备份,同时确保开发工作站上存在本地副本,来将共享项目分离出来。 如果移动项目(例如,为了使之分离),您的解决方案文件将发生变化,因此在更改解决方案文件引用的任何项目之前,您可能需要考虑备份解决方案文件。然后在正确分离项目依赖项之后,但在运行转换向导之前,再次进行备份。 最后,可以在转换过程完成之后发现原始解决方案文件中的错误。保留方便使用的转换前解决方案的备份,您即可轻松地在重新运行转换向导之前回头检查并修复这些错误。
  6. 考虑设置并行环境:Visual Studio 2003 和 Visual Studio 2010 可以在同一台计算机上并行运行,因此您也可以并行运行 ASP.NET 1.1 站点和 ASP.NET 2.0+ 站点。 这有助于您执行迁移后的 QA 测试。

若要启动转换向导,请依次使用 Visual Studio 2010 中的“文件”、“打开”和“项目/解决方案”菜单选项打开 Visual Studio 2003 解决方案文件。 很快您就可以看到 Visual Studio 转换向导简介对话框(请参阅图 2)。 单击“下一步”。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 2 Visual Studio 转换向导简介对话框

转换向导可以在处理过程中发现问题,而您自己可能也想从备份还原解决方案,请进行少量的更改并从头开始重新启动该过程。 即使将解决方案的所有依赖项放在指定的备份文件夹内(以便正确还原),该步骤也可以快速创建备份(请参阅图 3),但您必须完全确信您知道这些备份文件夹的初始布局情况。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 3 转换向导允许您在继续操作之前创建备份

如果您要在该步骤备份解决方案,只需提供文件夹路径,向导即可创建用于存放解决方案文件的子文件夹 Backup。 解决方案中的每个项目都将被备份到 Backup 文件夹下的相应子文件夹(即使项目源自原始解决方案的根目录之外),因此,要成功创建备份,重要的是确保项目名称在解决方案中是唯一的。 单击“下一步”。

此时您将看到最后一个对话框,其中包含有关源代码控制和读/写权限的指导(请参阅图 4)。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 4 转换向导在允许您继续操作之前提出相关建议

如果选择创建备份,您将看到所请求的备份类型和备份文件的写入位置。 您将看到正在转换的解决方案名称及其所有项目的摘要。 如果一切正确并且可接受,请单击“完成”。

此时可能会提示您提供源代码控制存储库的登录凭据(例如 Visual SourceSafe),以便可以签出项目。

在转换解决方案的每个项目时会显示进度栏。 由于向导要在解决方案中的项目间反复运行,因此该过程可能需要几分钟。

转换向导会显示一条消息,说明您已完成第一步,现在需要转换您的 Web 应用程序(请参阅图 5)。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 5 转换向导提示您需要转换 Web 项目才能完成迁移

然后,向导会提示您已完成初始过程(请参阅图 6)。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 6 转换向导在转换过程完成时向您发出提示

然后,可以使用“转换报告”模板检查转换日志。 该日志文件名为 Upgrade­Log.XML,存放在解决方案的 .sln 文件所在的文件夹内。 升级日志中显示已转换的项目文件、任何相关错误以及警告消息。 日志中还提供有用的注释以及有关每个项目所面向的框架版本的注释。 我已在图 7 中包含该报告的摘录。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 7 转换日志显示有关已转换 Web 应用程序的详细信息

应检查所有警告和错误。 警告(例如对备份路径的相对路径的更改)通常涉及次要的技术问题,一般不需要您执行进一步的操作也能成功编译转换后的解决方案。 但必须认真检查错误消息(例如文件引用丢失)并采取相应措施,因为错误消息涉及的问题通常会阻止您成功编译转换后的解决方案。 如果发现许多错误,则转换日志将起到很好的作用,它可清楚说明您需要执行的操作,通常您也可以使用 Visual Studio 2010 帮助文件或在各种技术网站中找到更多帮助。 许多情况下,您可能发现记录转换日志错误并在原始 Visual Studio 2003 项目文件中进行处理,比在转换后的解决方案(方便您使用创建的备份)中处理更有效。 您始终都可以针对修改后的 Visual Studio 2003 解决方案重新运行转换向导。

在检查所有警告并清除所有错误之后,可以退出转换向导的最终屏幕。 转换向导现已完成任务。 您的解决方案 (.sln) 文件及其项目 (.proj) 文件现已转换为 Visual Studio 2010 格式。 但在完成迁移之前仍有一些工作要做。

设置目标框架和启动页 转换向导完成后,即已将 Visual Studio 2003 Web 项目配置为基于 .NET Framework 4 运行,同时将解决方案的其他项目设置为基于 .NET Framework 2.0 运行。 虽然允许混合搭配不同的框架版本,但建议对解决方案的所有项目使用单一目标框架,除非存在由 Web 托管公司或组织基础结构强加的限制。 (Visual Studio 2010 根据活动项目的有效目标框架修改其 IDE 功能集。 如果您的项目面向不同的框架版本,在项目之间切换时可能会发现 IDE 的行为令人费解。 如果对所有项目使用相同的框架版本,不仅 IDE 可以在所有项目之间提供一致的界面,而且您还能针对一致的框架进行编程。)

如果希望更改所有已转换项目的目标框架,只需在解决方案资源管理器中右键单击该项目的根目录并选择“属性”即可执行。 在出现的配置页面(请参阅图 8)中,选择“应用程序”选项卡,将“目标框架”更改为任意的 2.0+ 框架值。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 8 将任何项目的目标框架更改为 2.0、3.0、3.5 或 4

最后,为 Web 项目设置起始页。 为此,请在解决方案资源管理器中找到该页面并右键单击,然后选择“设为起始页”。

编译并修复 既然解决方案和项目文件已升级到 Visual Studio 2010 格式,则可以对您的 ASP.NET 2.0+ WAP 进行编译。 若要强制生成解决方案中的所有项目,建议您在 Visual Studio 2010 中使用“生成”、“重新生成解决方案”菜单选项进行编译。 重新生成之后,可以通过显示“错误列表”窗口查看任何生成问题(可以通过选择“查看”和“错误列表”选项显示这些问题)。 “错误列表”窗口中显示错误、警告和消息(可以通过切换相应的“错误”、“警告”和“消息”按钮来指定窗口中显示的内容)。 Visual Studio 2010 通常会提供有关如何解决“错误列表”窗口中各项问题的明确指导。 如果您不能理解错误/警告/消息文本,只需选择包含相应指导的“错误列表”窗口行并按 <F1>。 此时将会出现一个帮助窗口,其中包含有关该问题的更多详细信息(如果您未安装本地帮助,可以连接到 Internet 查看该帮助)。 您看到的大部分错误都与框架更改有关,这些更改导致与您自己的代码发生命名冲突。 通常,您可以使用命名空间对引用进行完全限定来解决这些问题。 您看到的大多数警告都涉及过时成员。 虽然您仍可以使用过时成员,但应了解 .NET Framework 的更高版本中可能不支持这些成员。 如果您看到过时成员并以 2.0 框架为目标,则在决定以 3.x 或 4 框架为目标时可能无法使用这些成员。

准备抽出一些时间解决“错误列表”窗口中的这些问题。 在继续执行接下来的步骤之前,您应可以解决所有的错误和大部分(即使不是全部)警告。

将页面和用户控件转换为分部类 接下来运行“转换为 Web 应用程序”(以下称为 CWA)命令。 虽然可以针对单个页面或用户控件运行该命令以
了解其所做的更改,但针对整个解决方案运行该命令会更快速。 为此,请在解决方案资源管理器中右键单击“解决方案”节点,然后选择“转换为 Web 应用程序”。 该过程将执行以下操作:

  1. 通过为页面和用户控件添加新的“设计器”文档来实施分部类。
  2. 设置页面和用户控件的 AutoEventWireup。
  3. 为页面和用户控件上的每个控件添加声明性事件处理程序。

ASP.NET 1.1 应用程序具有代码隐藏模块(C# 的 aspx.cs 和 ascx.cs,Visual Basic .NET 的 aspx.vb 和 ascx.vb),该模块中包含开发人员编写的代码和 Web 窗体设计器生成的代码。 在 Visual Studio 2003 中创建页面或用户控件,并使用 Web 窗体设计器为它们添加控件时,IDE 将向代码隐藏模块添加受保护的实例字段,这样,您就可以引用所添加的这些控件。 运行 CWA 命令之后,将显示每个页面和用户控件的设计器文档(仅当启用解决方案资源管理器的“显示所有文件”选项时,解决方案资源管理器才会显示该文件)。 您将注意到设计器文件名与扩展名为 designer.cs (C#) 或 designer.vb (Visual Basic .NET) 的页面或用户控件相同。

例如,如果 C# 中存在名为 MyPage.aspx 的页面,即会出现一个名为 MyPage.aspx.designer.cs 的新文档。 该设计器文档包含将在代码隐藏模块中使用的受保护实例字段。 这些字段已转换为设计器模块,因此不会再混合在您自己的代码中。 这可能是因为设计器模块属于分部类,意味着 CWA 命令也会将相应页面或用户控件的代码隐藏代码转换为分部类。

例如,在 Visual Studio 2003 项目的代码隐藏文档中,C# 和 Visual Basic .NET 中的实例代码如下所示:


[VB]
Protected WithEvents MyButton As System.Web.UI.WebControls.Button

[C#]
protected System.Web.UI.WebControls.Button MyButton;
The CWA command moves each to a corresponding designer file:
[VB]
Protected WithEvents MyButton As Global.System.Web.UI.WebControls.Button

[C#]
protected global::System.Web.UI.WebControls.Button MyButton;
        

global:: 表示系统在搜索命名空间时,应从全局命名空间级别开始,从而确保框架系统命名空间不会被您自己的系统命名空间所隐藏。)

设计器文件的创建是动态的,可以随时重新生成。 因此,只需在解决方案资源管理器中右键单击该页面或用户控件节点,然后对其重新运行 CWA 命令,即可安全删除并重新生成 designer.cs 或 designer.vb 文档(如果该文档丢失,也可以还原)。 CWA 命令在页面或用户控件的 HTML 标记中扫描服务器控件,然后在设计器分部类文件中生成必要的实例变量。 接下来,它将删除仍显示在您自己的代码隐藏文件(aspx.cs、ascx.cs、aspx.vb 或 ascx.vb)中的所有实例变量。

分部类允许在命名空间内的两个或更多物理文件间编写单个类、结构或接口的源代码。 编译器稍后将这些分部定义组合起来,形成每个类型的单一声明。 虽然分部类保持 Visual Studio 使用的实际机制,以便将开发人员编写的代码与 IDE 生成的代码明确分开,但开发人员也可在代码隐藏模块中使用分部类,尤其在团队环境下工作时更是如此。

由于分部类是 ASP.NET 2.0+ 应用程序的标准,因此应将 ASP.NET 1.1 类划分为分部类。 如果您跳过该步骤,页面和用户控件将继续运行,但您在修改页面 (.aspx) 或用户控件 (.ascx) 上的控件时,需要手动更新代码隐藏文件中的控件字段声明。

CWA 命令还会更改 AutoEvent­Wireup 的值以及事件的声明和绑定方式,我认为这一影响非常重要,值得我们详细讨论。 AutoEventWireup 属于布尔属性,用于指定是隐式(如果为 True)还是显式(如果为 False)绑定页面对象事件处理程序。 对于页面,在 @Page 标记中设置 AutoEventWireup;对于用户控件,在 @Control 标记中设置 AutoEventWireup。 CWA 命令为 C# 页面和用户控件将 AutoEventWireup 设置为 True,为 Visual Basic .NET 页面和用户控件将其设置为 False。

各个开发人员有着不同的偏好,ASP.NET 1.1 应用程序中的某些页面或用户控件很可能将 AutoEventWireup 设置为 True 或 False,或者根本不指定该值,在后一种情况下,其默认值来自 web.config 或 machine.config(如果未指定 web.config)。 您应该了解,AutoEventWireup 的值可在运行 CWA 命令后发生更改。 此更改可能会导致无法预料的行为,例如页面事件触发两次。 当您在 ASP.NET 1.1 应用程序中为页面对象事件创建自己的命名约定时,通常会发生这种情况。 例如,考虑使用下面的 C# 代码,其中将 Page_Load2 处理程序绑定到 Page.Load 事件委托:


          this.Load += new System.EventHandler(this.Page_Load2);
        

如果 AutoEventWireup 为 False,事件将按预期触发一次,即使存在名为 Page_Load 的代码隐藏函数也是如此。 但是,如果 AutoEventWireup 为 True,则会触发两个事件,一个对应此处说明的显式绑定代码,一个对应将 Page_Load 事件处理程序预订到 Page.Load 事件的隐式绑定代码。 请考虑使用图 9 中的代码。

图 9 测试 AutoEventWireup 行为


 public partial class _Default : System.Web.UI.Page
{
  override protected void OnInit(EventArgs e)
  {
    InitializeComponent();
    base.OnInit(e);
  }

  private void InitializeComponent()
  {
    this.Load += new System.EventHandler(this.Page_Load2);
  }

  protected void Page_Load()
  {
    Response.Write("In Page_Load().<br />");
  }

  protected void Page_Load2(object sender, EventArgs e)
  {
    Response.Write("In Page_Load2().<br />");
  }
}
        

图 9 中的代码生成以下输出:


          In Page_Load().
          In Page_Load2().
          Top of Form 1
Bottom of Form 1
        

如果 AutoEventWireup 设置为 True,同样的情况也将发生在 Visual Basic .NET 中。 请考虑使用以下代码:


          Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)

  Response.Write("In Page_Load.<br />")

End Sub

Private Sub Page_Load2(ByVal sender As System.Object, _
  ByVal e As System.EventArgs) Handles MyBase.Load

  Response.Write("In Page_Load2.<br />")

End Sub
        

如果 AutoEventWireup 为 True,将触发两个事件处理程序以显示页面:


          In Page_Load2.
          In Page_Load.
        

您不仅可以看到执行两个事件处理程序,还可以看到相应的执行顺序(与所有多播委托相同)可能与您预期的顺序不同。 最后,应意识到 AutoEventWireup 为 True 时,无论是否使用参数定义包含正确函数名称(例如 Page_Load)的页面事件处理程序,都会触发该处理程序。 例如,


          protected void Page_Load()
  {
    Response.Write("In Page_Load().<br />");
  }
        

与以下相同:


          protected void Page_Load(object sender, EventArgs e)
  {
    Response.Write("In Page_Load().<br />");
  }
        

如果两个都存在,则仅触发使用参数的事件处理程序,这是在排除故障时要考虑的又一个问题。 因此,通常情况下,在测试页面和用户控件时应谨慎,尤其是在 AutoEvent­Wireup 设置被 CWA 命令更改时更是如此。

最后,CWA 命令将删除用于绑定控件事件的显式 C# 和 Visual Basic .NET 代码,并在页面或用户控件的标记中改用声明性事件属性。 例如,在 ASP.NET 1.1 中,按钮上的单击事件通常具有代码处于隐藏状态的事件处理程序,例如:


          this.MyButton.Click += new System.EventHandler(this.MyButton_Click);
        

CWA 命令删除该事件,改为向服务器-控件声明中添加如下 OnClick 属性:


          <asp:Button ID="MyButton" runat="server" Text="MyButton" onclick="MyButton" />
        

在 Visual Basic .NET 中,不添加声明性事件, 而是向隐藏代码中添加 Handles 关键字。 因此,“按钮”控件的标记将显示为:


          <asp:Button ID="MyButton" runat="server" Text="Button" />
        

而隐藏代码将控件绑定到处理程序:


          Protected Sub MyButton_Click(
  ByVal sender As Object, ByVal e As EventArgs) _
Handles MyButton.Click

End Sub
        

这些声明性事件处理程序构造的事件委托是在编译时创建的。

编译并修复 迁移现已完成。 建议您重新生成解决方案,练习解决可能会收到的任何其他编译器错误或警告。 请注意,您必须解决编译错误,才能成功生成 Web 项目以及在浏览器中查看已迁移的网站。 此外,还应解决编译警告,但警告不是关键问题,不会阻止您使用 Web 应用程序。 最后,记录下所有的编译器消息,因为这些消息通常可提供帮助性的改进建议,如果时间允许,应考虑实施这些建议。 除了错误和警告之外,还必须对您迁移的代码执行回归测试和 QA 测试,执行这些测试时务必小心,确保按预期触发事件。

迁移后注意事项

由于您的 ASP.NET 项目现在面向更新的框架,并在更新式版本的 IDE 下运行,因此还应注意其他的一些问题。

如果将 ASP.NET 1.1 解决方案从 32 位操作系统迁移到 64 位操作系统,应意识到 IIS 6.0 及其更高版本同时支持 32 位和 64 位操作模式。 由于 ASP.NET 1.1 仅在 32 位模式下运行,您可能会发现已转换的 ASP.NET 应用程序仍包含 32 位依赖项(例如 COM 或 P/Invoke 调用),这些依赖项在迁移后可能无法继续正常工作。 若要修复此问题,请访问应用程序的应用程序池的“高级设置”,并将“启用 32 位应用程序”值设置为 True。

Visual Studio 2010 要求网页与 XHTML 兼容。 您在 ASP.NET 1.1 中的页面可能与 XHTML 不兼容。 因此,大多数页面将会显示 XHTML 验证警告(若要查看这些警告,请在“源”或“设计”模式下查看页面,然后访问“查看”菜单并选择“错误列表”)。 虽然这些警告不会阻止页面运行,但指明页面无法在最新浏览器中正确呈现。 如果时间允许,应更新页面和用户控件以使它们与 XHTML 兼容,从而确保页面和用户控件在最新浏览器中正确呈现。 如果您的 Web 应用程序特定于较旧版本的浏览器,或者此时不想为标记验证错误费神,则可以更改标记的验证方式,方法是转到“工具”菜单,选择“选项”,再转到“文本编辑器”节点,然后将“目标”更改为 Internet Explorer 6(请参阅图 10)。 该方法仅适用于需要针对 Internet Explorer 6 进行开发的开发人员(例如,如果您的应用程序是企业 Intranet 应用程序)。 这可以将呈现验证有效设置为与在 Visual Studio 2003 中可能使用的级别所类似的级别。

将 ASP.NET 1.1 应用程序迁移到 Visual Studio 2010

图 10 可以通过将 HTML 验证目标更改为 Internet Explorer 6 来抑制 XHTML 验证错误

对于必须在 Internet Explorer 以外的浏览器或 Internet Explorer 6 以上的版本中正确显示的应用程序,应继续在 HTML 编辑器中显示 XHTML 标记错误,并充分利用作为 Web.config system.web 部分中的属性提供的新 .NET Framework 4 controlRenderingCompatibilityVersion 配置设置。


          <system.web>
  <pages controlRenderingCompatibilityVersion="4.0"/>
</system.web>
        

如果未在 Web.config 中设置 controlRenderingCompatibilityVersion,则默认为正在运行的 ASP.NET 的版本。 但是,当指定 controlRenderingCompatibilityVersion 值时,可以将其设置为“3.5”或“4.0”(转换向导将其设置为“3.5”,以按照 ASP.NET 3.5 中的相同方式呈现页面)。 该设置决定 .aspx 文件中指定的标记如何在浏览器中最终呈现。 若要引用 Visual Studio 2010 联机帮助中的示例,如果 controlRenderingCompatibilityVersion 设置为“3.5”,则 IsEnabled 属性设置为 false 的服务器端 ASP.NET 标签控件将呈现“disabled”属性设置为“disabled”的 HTML span 元素;如果 controlRenderingCompatibilityVersion 设置为“4.0”,生成的 span 元素将包含一个引用 CSS 类的“class”属性。

您应注意到使用“4.0”设置可生成最新的 XHTML 标记,但这可能会破坏在 ASP.NET 1.1 版本页面中正常工作的客户端脚本或 CSS 规则,从而将会影响所呈现的内容的行为和/或美感。 因此,在您全心致力于生成有效 XHTML 之前,建议您将 controlRenderingCompatibilityVersion 设置为“3.5”。如果您使用该“3.5”设置,则需要了解可设置为“Legacy”、“Strict”或“Transitional”(默认值)的 xhtmlConformance(仅在 controlRenderingCompatibilityVersion 设置为“3.5”时适用)。 “Strict”可呈现 XHTML 1.0 Strict 标记;“Transitional”可呈现 XHTML 1.0 Transitional 标记;“Legacy”以类似于(不一定完全一样)ASP.NET 1.1 中的呈现方式呈现 HTML:


          <system.web>
  <pages controlRenderingCompatibilityVersion="4.0"/>
  <xhtmlConformance mode="Transitional"/>
</system.web>
        

根据我的经验,应避免使用“Legacy”模式,因为它可能会妨碍 ASP.NET AJAX UpdatePanel 正常运行。 此外,还应注意,controlRenderingCompatibilityVersion 值不会更改网页的 DOCTYPE,而仅会更改 ASP.NET 控件自身的呈现方式。 因此,正确呈现页面在很大程度上取决于 controlRenderingCompatibilityVersion、xhtmlConformance 和 DOCTYPE 值以及所用的目标浏览器类型和版本的组合。

另外,还应考虑以下事项:您可能需要更改在其下运行新迁移站点的虚拟目录,尤其是在计划与 ASP.NET 1.1 版本并行运行时。 为此,请在解决方案资源管理器中右键单击 Web 项目,选择“属性”,然后访问“Web”选项卡。 在“服务器”下,您将看到“使用本地 IIS Web 服务器”选项。 确保选中该选项,指定项目 URL(例如 http://localhost/mysitemigrated),如果虚拟目录不存在,还请单击“创建虚拟目录”按钮。

ASP.NET 1.1 应用程序利用 Windows ASPNET 用户来分配对虚拟根目录下的文件和文件夹的特权。 ASP.NET 2.0+ 利用 NETWORK SERVICE 用户。 例如,如果应用程序要求 ASP.NET 具有特定文件或文件夹的写入访问权限,也必须将这些权限授予 NETWORK SERVICE 用户。 如果您不确定需要该访问权限的用户,可以通过在运行 ASP.NET 应用程序时检查 Envionment.UserName 属性的值来查看该用户名。

如果使用任何第三方加载项或依赖项(无论是二进制文件还是源代码),则需要与供应商核实来确保您拥有最新的版本。 例如,常用的日志记录程序 NLog 提供 1.1 和 2.0 库版本。 获取 2.0 版本,避免花费精力迁移 1.1 代码。 另外,供应商将为针对 Visual Studio IDE 设计的工作效率加载项提供更新。 务必执行升级,为新 Visual Studio 2010 IDE 获取这些产品的最新版本。

迁移 ASP.NET 1.1 Web 应用程序后,将会发现可立即享受以下两个好处。 首先,您无需再使用 Front Page Server Extensions (FPSE) 为站点提供支持(除非希望继续使用 FPSE)。 其次,您无需再在开发计算机上安装 IIS,因为 Visual Studio 2010 提供了自己的内置 ASP.NET Development Server。 虽然可以继续并行运行 Visual Studio 2003 ASP.NET 应用程序和 Visual Studio 2010 ASP.NET 应用程序(例如,出于 QA/调试目的),但已转换的 Visual Studio 2010 ASP.NET 应用程序无需再使用 Visual Studio 2003 或访问 .NET Framework 1.1。

如果您是一位 C# 开发人员,可能注意到在设计模式下查看页面和用户控件事件时,它们在“属性”窗口中不再显示为黄色的雷电图标。 若要按照 Visual Studio 2003 中的相同方式查看/创建这些事件,必须在解决方案资源管理器中右键单击该页面 (.aspx) 或用户控件 (.ascx),然后选择“查看组件设计器”。 此时,您将看到包含熟悉的事件列表的“属性”窗口。 您可以双击列表中的任何事件,以便创建事件过程和委托绑定代码(从而将其添加到 InitializeComponent 函数)。

若要托管站点,应了解所需的 CLR。 如果使用 3.0 和 3.5 .NET Frameworks,将针对 CLR 2.0 运行;如果使用 .NET Framework 4,将针对 CLR 4.0 运行。 若要托管 ASP.NET 4.0 解决方案,您的托管公司必须支持 CLR 4.0。

希望我已经为您将 Visual Studio 2003 ASP.NET 应用程序迁移到 Visual Studio 2010 提供了帮助。 一旦完成该任务,那么您将进入一个随您掌控的全新编程技术世界。 我相信这是一个相对容易接受的技术决策,您绝不会后悔。

Jonathan Waldman PC Magazine 撰稿,是一位高级 Microsoft 认证专家,利用 .NET Framework 技术为桌面和 Web 全身心创建自定义软件解决方案。可以通过 jonathan.waldman@live.com 与他联系。

衷心感谢以下技术专家对本文的审阅: Scott Hanselman