常见 Web 项目转换问题和解决方案

 

迈克尔·邦丘
Microsoft 高级项目经理
罗伯特·麦戈文
输液开发

2005 年 11 月 (更新了 Visual Studio 2005 RTM 版本)

适用于:
   ASP.NET 1.x
   ASP.NET 2.0
   Visual Studio .NET 2003
   Visual Studio 2005

总结: 查看影响 Web 项目转换的 Visual Studio 2005 Web 项目和 ASP.NET 2.0 框架更改,然后讨论使用 Visual Studio 2005 进行转换的常见问题和解决方案。 ) (31 个打印页

目录

第 1 部分:Web 项目更改
   什么是 ASP.NET 和 Visual Studio?
   Web 项目更改
   新功能
   转换 Web 项目
   转换向导
   转换报告
第 2 部分:常见转换问题
   问题 1:代码隐藏类文件 (CB) 引用
   问题 2:独立类文件 (SA-CB) 引用
   问题 3:循环引用
   问题 4:资源管理器
   问题 5:不再排除排除的文件
   问题 6:孤立的 resx 文件
   问题 7:代码隐藏文件中的额外类型
   问题 8:访问自动生成的控制变量
   问题 9:无法切换到设计视图
   问题 10:无法分析文件名
第 3 部分:其他转换问题
   问题 11:Web 项目文件夹中的备份文件夹
   问题 12:位于同一位置的多个项目
   问题 13:引用相同文件的多个项目
   问题 14:访问修饰符无效
   问题 15:转换排除的文件
   问题 16:重复变量声明
   问题 17:Sub-Web应用程序
   问题 18:OnInit () 未删除
   问题 19:XHTML 验证错误
   问题 20:多个配置
   问题 21:自动生成的成员隐藏继承的成员
   问题 22:不明确的引用和命名冲突
   问题 23:多次调用事件处理程序
   问题 24:代码隐藏文件移动到App_Code文件夹
   问题 25:引用 Web 项目的项目
   问题 26:共享相同的代码隐藏文件
   问题 27:部分转换的解决方案
   问题 28:没有 C 命令行迁移#
   问题 29:Batch = True 或 False
总结
附录 A:实际错误消息

第 1 部分:Web 项目更改

将 Visual Studio 2002/2003 Web 项目转换为 Visual Studio 2005 时,在 Web 项目系统中所做的更改可能会遇到问题。 在本文中,我们将介绍转换过程和转换过程中可能遇到的一些常见问题。

什么是 ASP.NET 和 Visual Studio?

ASP.NET 是一种用于创建动态 Web 应用程序的技术。 (Web Forms) 编译 ASP.NET 页,使你能够构建基于表单的强大网页。 生成这些页面时,可以使用 ASP.NET 用户控件来创建常见的 UI 元素,并针对常见任务对其进行编程。

Visual Studio 是一个集成开发环境, (IDE) ,开发人员可以使用该环境为.NET Framework创建多种语言之一(包括 C# 和 Visual Basic)的程序。

你会发现,将 Web 应用程序转换为使用新的 Visual Studio 2005 和 ASP.NET 2.0 功能既简化了开发,又提供了更多用于编译和部署代码的选项。

Web 项目更改

这些更改会影响开发、配置和部署 Web 应用程序的方式。 作为开发人员或网站管理员,你需要了解这些更改,以便正确生成、部署和维护 Web 应用程序。

  • 无项目文件。 Visual Studio 2005 不再使用项目文件显式列出 Web 项目中的文件。 相反,它会将所有文件和文件夹视为 Web 项目的一部分。 存储在项目文件中的项目信息现在存储在解决方案或Web.config文件中。
  • 特殊目录。 ASP.NET 1.x 应用程序有一个包含程序集的必需文件夹 (\bin) 。 ASP.NET 2.0 应用程序具有更大的定义文件夹结构。 新目录以前缀“App_”开头,旨在存储资源、程序集、源代码和其他组件。 新的文件夹结构有助于消除对项目文件的需求,并启用一些新的部署选项。
  • 代码隐藏模型。 在 ASP.NET 1.x 中,代码隐藏模型允许将内容 ((例如 foo.aspx) )与代码 ((例如 foo.aspx.vb) )分离。 内容页继承自代码隐藏页,代码隐藏页包含用户和设计器生成的代码。
    ASP.NET 2.0 使用分部类增强了代码隐藏模型,从而允许类跨多个文件。 在新的代码隐藏模型中,内容页继承自编译的类,该类由相应的代码隐藏页和自动生成的分部类组成,该类定义内容页中使用的控件的字段声明。 此更改允许将自动生成的代码与用户代码分开,并使代码隐藏页面更小、更简洁。 分部类结构还通过编辑设计器生成的代码来降低无意中破坏页面的风险。
  • 编译模型 (一个程序集到多个程序集) 。 在 Visual Studio .NET 2003 中,所有代码隐藏类文件和支持代码都预编译到具有固定名称的单个程序集中。 在 Visual Studio 2005 中,默认使用唯一生成的文件名) 动态 (创建多个程序集。 例如,默认行为是将文件夹中的所有 Web 窗体和用户控件编译为自己的程序集。 App_Code 文件夹中的公共源代码将自动编译到其自己的独立程序集中。 这种新的编译模型会导致 Web 应用程序的结构发生一些更改,但极大地增强了部署选项以及 Web 应用程序在 Web 服务器上服务的方式。
  • (预编译、完整编译、可更新站点等) 部署选项。 在 Visual Studio 的早期版本中,Web 应用程序作为一个大型程序集进行预编译和部署。 (的内容页(例如 *.aspx 或 *.ascx) )在服务器上无法编译和编辑。 由于 Visual Studio 2005 中的新页面编译模型和文件夹结构,可以在许多不同的配置中部署 Web 应用程序。 在一个极端情况下,可以预编译所有内容页、其代码隐藏类文件及其隐藏的设计器页,并部署由完全编译的程序集组成的 Web 应用程序。 在此模式下,无法在服务器上轻松更改应用程序。 另一种极端是,可以部署完全没有预编译代码的应用程序。 在此配置中,可以直接在服务器上更改内容页、代码隐藏类文件或任何其他代码。 当用户从服务器请求页面时,将动态编译页面。

每个操作更改都可能需要在转换 Web 应用程序之前或之后修改应用程序体系结构和部署过程。

新功能

转换 Web 应用程序将使应用程序更强大、更灵活且可维护。 尽管本文重点介绍转换应用程序的机制,但你可以通过以下链接详细了解新的 Visual Studio 2005 和 ASP.NET 2.0 功能:

  • 功能概述
    本白皮书将全面概述 ASP.NET 2.0 中提供的新功能。 如果你正在考虑在使用 ASP.NET 1.x 构建的网站上利用 ASP.NET 2.0 内容,则应通读本文以了解哪些内容可供你使用。
  • 个性化
    ASP.NET 2.0 的个性化功能(称为 Web 部件)可让你将网站设计为对单个用户作出反应。 例如,你可以让每个用户选择网站布局或配色方案,并在访问之间保留该信息。 Web 部件允许你以最少的新代码提供个性化功能。
  • 数据访问
    ADO.NET 不仅已针对.NET Framework 2.0 进行了更新,ASP.NET 2.0 现在还包括一组新的数据源控件和数据访问功能。
  • 母版页
    在传统 ASP.NET 中,大多数开发人员都在努力设计一个将代码重用与灵活性相结合的 Web 应用程序框架。 母版页通过引入真正的继承来充分利用两者。 可以设置包含页眉、页脚和导航栏的母版页,然后创建填充内容的子页面,同时自动继承母版页的外观、行为和功能。
  • ASP.NET Development Server
    独立且仅限开发的 Web 服务器现在与 Visual Studio 2005 捆绑在一起。 此服务器代码为“Cassini”,允许用户开发和测试其 Web 应用程序,而无需在其开发系统上安装 IIS。 此服务器只能用于开发。 将应用程序部署到生产环境时,需要使用配置有 ASP.NET 2.0 的 IIS 服务器。

转换 Web 项目

转换 Web 项目不仅仅涉及更改框架版本! 转换分为三个部分:

  1. 转换前 - 在运行转换向导之前查看并可能更改 Web 项目体系结构。
  2. 转换 - 运行 Visual Studio 2005 转换向导以转换 Web 项目。
  3. 转换后 - 解决转换向导未捕获或无法解决的任何问题。

对于第 1 部分和第 2 部分,应阅读并应用将 Web 项目转换为 Visual Studio .NET 2005 的分步指南中所述的步骤。

对于第 3 部分,应应用本白皮书中概述的解决方案。

转换向导

Visual Studio 2005 具有内置的转换向导,可帮助转换 Web 应用程序。 此向导自动执行转换应用程序以使用 ASP.NET 2.0 功能所需的许多基本步骤。

运行向导

每当在 Visual Studio 2005 中打开 Visual Studio .NET 2003 Web 项目时,将自动调用转换向导。 向导检测应用程序文件夹中是否存在 Web 项目文件 (例如 *.vbproj 或 *.csproj) ,并自动启动转换过程。

Aa479312.upgradeaspnet01 (en-us,MSDN.10) .gif

图 1. 转换向导

必须做出的第一个选择是在转换前创建应用程序的备份。 强烈建议进行备份!

Aa479312.upgradeaspnet02 (en-us,MSDN.10) .gif

图 2. 备份应用程序

如果选择创建备份,Visual Studio 2005 将自动在所选文件夹中创建 Web 项目的副本。

注意 请确保将备份文件夹放在 Web 应用程序的文件夹树之外。 有关完整详细信息,请参阅 Web 应用程序文件夹中的备份文件夹问题。

接下来,你将看到转换过程的摘要屏幕,并有最后一个机会退出转换。 请注意有关此摘要屏幕的两个事项:

注意 第一个段落不正确,因为它指出,在进行更改之前,将从源代码控件签出 Web 项目。 这适用于 Visual Basic 和 C# 客户端项目,但 Web 项目并非如此。 相反,Web 项目转换向导将忽略源代码控制,并将它必须修改的文件更改为读写。

Web 项目将就地转换,这就是为什么进行备份既建议又重要的原因。

Aa479312.upgradeaspnet03 (en-us,MSDN.10) .gif

图 3. “摘要”屏幕

转换可能需要几分钟时间,具体取决于应用程序的大小。 完成后,你将看到一条消息,指示 Web 项目已转换。 还可能会看到一条有关某些警告或错误的消息。 如果转换向导进行了可能修改应用程序行为的更改,或者无法完全更新 Web 项目,则会出现警告和错误。

Aa479312.upgradeaspnet04 (en-us,MSDN.10) .gif

图 4。 转换已完成

转换完成后,即可查看转换报告,了解是否需要执行任何其他手动步骤才能完成转换。

转换报告

转换向导将在 XML 和文本文件中记录对 Web 项目所做的更改。 转换向导完成后,会显示报表的 XML 版本。 此报告将显示向导和代码区域遇到的任何问题,可能需要采取其他步骤来完成转换。

报表分为多个部分,用于转换后的解决方案和一个或多个项目。 解决方案报告几乎始终没有错误。 但是,项目部分可能针对项目中的每个文件列出了多个问题。 应查看本部分并解决转换向导报告的任何问题。

单击此处查看较大图像

图 5。 转换报表 (单击以获取较大的图像)

如果关闭转换报告,则始终可以在已转换项目的顶层找到文本版本。

注意 在 Visual Studio 2005 的最终版本中,文本报表的名称ConversionReport.txt。 将来的版本会将此文件重命名为 ConversionReport.webinfo。 文本版本将在 Web 应用程序的根文件夹中找到。

通知类型

报表中的每个项分为以下三个类别之一:

  • 注释 - 通知向导执行的操作。 你将看到许多有关已删除或移动的文件的注释,以及已删除或注释掉的代码。批注在转换报表的文本版本中列出,但在 XML 版本中省略。
  • 警告 - 每当向导必须执行可能导致应用程序中的行为更改或可能的编译错误的操作时,都会生成警告。 警告是要查看的项,但可能不需要执行操作。
  • 错误 - 如果向导遇到无法自动转换的内容,则会生成错误项。 这些项目需要你努力才能完成转换。 通常,如果尝试运行应用程序,错误将生成编译错误。

第 2 部分:常见转换问题

尽管 Visual Studio 2005 旨在与使用 Visual Studio .NET 2003 开发的代码配合使用,但你可能会遇到一个或多个常见的转换问题。 在本部分中,我们将介绍几个最常见的问题。

注意 转换向导已在最终版本的 Visual Studio 2005 中升级,并可能自动检测并修复以下某些问题。 但是,如果向导错过了特定问题,可以手动应用下述解决方案以完成 Web 项目的转换。

问题 1:代码隐藏类文件 (CB) 引用

注意 CB 是 Web 窗体 (*.aspx) 或用户控件 (*.ascx) 的代码隐藏文件的首字母缩略词。

新的编译模型使用多个通常在服务器上动态编译的程序集。 此模型可提高网站性能和可更新性。

但是,如果代码隐藏文件引用另一个代码隐藏文件,则将有一个损坏的引用,因为引用的代码隐藏文件将不再位于同一程序集中。

以下是触发它的一些常见方法:

  • 使用 Web 窗体或用户控件作为另一个 Web 窗体或用户控件的基类。
  • 使用 LoadControl() 并将结果强制转换为其他用户控件,例如
    UserControl1 c1 = (UserControl1)LoadControl("~/UserControl1.ascx");
  • 创建 Web 窗体类的实例,例如
    WebForm1 w1 = new WebForm1();
    其中 WebForm1 是在 Web 窗体的代码隐藏文件中定义的类。

如何解决

若要解决此问题,需要更改应用程序,以便找到引用。 由于这是 CB-CB 引用,因此最简单的解决方法是将引用指令添加到进行引用的 Web 窗体或用户控件。 这将告知编译器要链接到的程序集。

假设你有以下情况:

文件 ASP.NET 1.x 代码
Page1.ascx  
Page1.ascx.cs
Control1 c = (Control1)LoadControl("~/Control1.ascx");

更改代码以使用 reference 指令:

文件 ASP.NET 2.0 代码
Page1.ascx
<%@ Reference Control="~/Control1.ascx" %>
Page1.ascx.cs
Control1 c = (Control1)LoadControl("~/Control1.ascx");

通过使用 reference 指令,可以显式告知编译器在何处查找要使用的 Web 窗体或控件。 请注意,在 Visual Studio 2005 的最终版本中,转换向导将自动执行此操作。

问题 2:独立类文件 (SA-CB) 引用

注意 SA 是独立类文件的首字母缩略词。

如果你有引用代码隐藏类文件中代码的独立类文件,则可能会遇到另一种类型的损坏引用。 这类似于 CB-CB 中断的引用,只是你在尝试引用单独的页程序集的 App_Code 文件夹中有一个独立的类文件。 触发它的一种常见方法是访问 CB 类中的类变量。

如何解决

更需要修复 SA-CB 损坏的引用。 由于此问题发生在 SA 文件中,无法使用引用指令来查找引用。 此外,转换后,SA 文件将移动到 App_Code 文件夹,因此类文件将仅有权访问编译它的App_Code程序集。

解决方案是在 App_Code 文件夹中创建一个抽象基类,以在编译时引用,这将在运行时从页面程序集加载实际类。

假设你有以下情况:

文件 ASP.NET 1.x 代码
Control1.ascx
inherits="Control1"
Control1.ascx.cs
class Control1 : System.Web.UI.UserControl { 
    public static string myName = "Control1";
    public void foo() { some code } 
}
Code1.cs
String myName = "Class1 + " + Control1.myName;

更改代码以使用抽象基类:

文件 ASP.NET 2.0 代码
Control1.ascx
inherits="migrated_Control1"
Control1.ascx.cs
class migrated_Control1 : Control1 { 
    override public void foo() { some code } 
}
App_Code\Code1.cs
String myName = "Class1 + " + Control1.myName;
App_Code\Stub_Control1.cs
abstract class Control1 : System.Web.UI.UserControl {
    public static string myName = "Control1";
    abstract public void foo(); 
}

抽象基类将允许独立类文件和 CB 文件在此示例中) 的编译 (查找名为 Control1 的类,因为它现在存在于 App_Code 文件夹中。 但是,独立类文件将使用后期绑定来加载原始类, (在此示例中重命名为migrated_control,在运行时) 。 注意:在 Visual Studio 2005 的最终版本中,转换向导将自动创建此代码。

问题 3:循环引用

当代码隐藏文件引用另一个代码隐藏时,会发生循环引用

文件,后者又引用原始文件。 它可能发生在两个或更多代码隐藏文件中,例如:

Aa479312.circular-ref1 (en-us,MSDN.10) .gif

它还可能发生在程序集之间,其中一个程序集引用另一个程序集

程序集,后者又引用原始程序集,例如:

Aa479312.circular-ref2 (en-us,MSDN.10) .gif

如何解决

第一种类型的循环引用的解决方案是在App_Code文件夹中使用其中一个引用创建抽象基类,然后从关联的 Web 窗体或用户控件文件中删除 Reference 指令。 这会中断循环引用。

第二种类型的循环引用是 ASP.NET 编译器出于性能原因将程序集“批处理”在一起的副产品。 默认情况下,它将采用文件夹中的 Web 窗体和用户控件,并将其编译为程序集。

可通过多种方法解决此问题,但我们建议将引用的页面 (例如 Pages2.aspx.vb 和 Pages3.aspx.vb) 移动到其自己的文件夹。 通过

默认情况下,ASP.NET 编译器将创建包含这些页面的单独程序集,并且将在程序集 A 和 B 之间删除循环引用。

Aa479312.circular-ref3 (en-us,MSDN.10) .gif

问题 4:资源管理器

在 Visual Studio .NET 2003 中,资源管理器用于管理 Web 应用程序中的资源。 典型的示例如下所示:

文件 ASP.NET 1.x 代码
Control1.ascx.cs
Assembly a = Assembly.Load("myApp");
ResourceManager rm = new ResourceManager("myApp.Resource1", a);
String s = rm.GetString("foo");
Resource1.resx
Contains name/value pair  "foo = bar"

此类代码有问题,因为这取决于你知道要加载的程序集的名称,该名称在 Visual Studio 2005 中不再是固定名称。

如何解决

由于 Visual Studio 2005 使用非确定性程序集命名,需要更改代码以使用新的资源模型。 最简单的方法是将 Resource1.resx 移动到名为 App_GlobalResources 的特殊文件夹。 Visual Studio 2005 将自动通过强命名 (在此文件夹中找到的任何资源提供,并且可使用 IntelliSense) 发现 Web 应用程序。 下面是转换后的示例:

文件 ASP.NET 2.0 代码
Control1.ascx.cs
String s = Resources.Resource1.foo;
App_GlobalResources\
Resource1.resx
Resource1.resx moved to App_GlobalResources
Contains name/value pair  "foo = bar"

这只是在 Visual Studio 2005 中使用新资源模型的一种方法,应查看资源模型文档,以发现此模型中的新功能。

问题 5:不再排除排除的文件

在 Visual Studio .NET 2003 中,必须显式决定是否在 Web 项目中包括文件。 如果文件未显式列出为 include,则该文件已从项目中排除。 还可以通过将代码文件的生成操作设置为“none”来阻止其生成。 此信息存储在项目文件中。

转换时,必须考虑几个问题,例如:

  • 从一个项目中排除的文件可能包含在另一个项目中
  • 是否应尝试转换排除的文件,因为它可能只是用户想要记住的代码片段?

在 Visual Studio 2005 的最终版本中,转换向导将按原样保留排除的文件,并在转换报告中记下这些文件。 因此,Web 项目将包含额外的未转换文件,这些文件现在是项目的一部分。 根据文件的扩展名,编译器可能会尝试编译文件,这可能会导致应用程序中的冲突。

如何解决

转换后,可以从项目中删除任何以前排除的文件。 还可以使用解决方案资源管理器菜单上 (“从项目排除”功能,) 使用安全扩展名“.exclude”重命名它们来排除它们,从而从 Web 应用程序中有效地删除它们。

请注意 ,使用“.exclude”扩展名排除的文件仍然是 Web 项目的一部分,但它们不会被编译;如果这些文件恰好位于服务器上,则 IIS/ASP.NET 也不会提供这些文件。

请注意 ,将来的转换向导版本将更加主动,并在认为可以安全时排除文件。

问题 6:孤立的 resx 文件

Visual Studio .NET 2003 为 Web 窗体和用户控件生成了 resx (资源) 文件。 通常,用户不使用它们,因为它们是自动生成的,并且可能会覆盖用户添加的代码。

转换后,不会删除这些 resx 文件,因为迁移向导不确定用户是否添加了需要保存的资源。

如何解决

查看生成的 resx 文件,并将用户数据保存到其自己的资源文件中。 可将此数据合并到一个资源文件中。

将资源文件移动到App_GlobalResources或适当App_LocalResources的特殊文件夹,以便它可供 Web 应用程序使用。

以这种方式保存用户数据后,请从 Web 项目中删除生成的 resx 文件。

Aa479312.issue-orphaned-resx (en-us,MSDN.10) .gif

问题 7:代码隐藏文件中的额外类型

在 Visual Studio .NET 2003 中,通过将类型存储在某个 Web 窗体或用户控件的代码隐藏文件中,可以跨不同页面共享结构、枚举、接口、模块 ) 等 (类型。

此模型在 Visual Studio 2005 中中断,因为 Web 窗体和用户控件已编译为自己的程序集,因此无法再发现额外的类型。

如何解决

转换向导转换应用程序后,只需将任何非专用额外类型移动到其自己的独立代码文件App_Code文件夹中。 还需要将类型的访问修饰符更改为 public,因为它必须跨程序集工作。 共享类型将自动编译并在整个 Web 应用程序中被发现。

问题 8:访问自动生成的控制变量

在 Visual Studio .NET 2003 中,代码隐藏类文件包含用户和自动生成的设计器代码。 后者可以包含控制变量声明和页函数。 尽管不建议这样做,但某些开发人员将控件变量的访问权限更改为 Public,以便可以从其类外部对其进行修改。 示例如下所示:

文件 ASP.NET 1.x 代码
UserCtrl1.ascx
<asp:Label id="Label1" runat="server">UC1</asp:Label>
UserCtrl1.ascx.cs
public System.Web.UI.WebControls.Label Label1;
Page1.ascx.cs
UserCtrl1 uc1 = (UserCtrl1)LoadControl("~/UserCtrl1.ascx");
uc1.Label1.Text = "Foo";

在 Visual Studio 2005 中,此更改将不起作用,因为用户和自动生成的设计器代码使用分部类分隔。 分部类允许类跨越多个文件,并且用于在用户和自动生成的代码之间保持干净分离。

如何解决

通常,建议将代码更改为不依赖于自动生成代码的更改访问级别。 但是,如果代码中有数百个调用此类自动生成的控制变量的位置,并且需要快速运行代码,则有一种解决方法非常有用。 可以将原始控件变量重命名为其他变量,然后创建一个公共属性来访问重命名的控件变量。 例如:

文件 ASP.NET 2.0 代码
UserCtrl1.ascx
<asp:Label id="p_Label1" runat="server">UC1</asp:Label>
UserCtrl1 隐藏分部类
// this will be auto-generated in the hidden, partial class
protected System.Web.UI.WebControls.Label p_Label1;
UserCtrl1.ascx.cs
public System.Web.UI.WebControls.Label Label1 {
    get { return p_Label1; }
    set { p_Label1 = value; }
}
Page1.ascx.cs
UserCtrl1 uc1 = (UserCtrl1)LoadControl("~/UserCtrl1.ascx");
uc1.Label1.Text = "Foo";

问题 9:无法切换到设计视图

与 Visual Studio .NET 2003 相比,Visual Studio 2005 中内置的新 Visual Web Designer对正确的 HTML 更加严格。 如果 aspx 页面包含不匹配的标记或格式不佳的 HTML,则设计器将不允许你切换到 Visual Studio 2005 中的设计视图。 相反,在解决问题之前,只能使用代码视图。 出现此问题的原因是 Visual Studio 2005 中内置的新源代码保留和验证函数。

如何解决

若要避免此问题,只需确保 aspx 页面中的标记格式正确。 如果在转换后从代码视图切换到设计视图时遇到问题,则几乎可以肯定是错误标记。

问题 10:无法分析文件名

你可能会看到一条略显模棱两可的错误消息,告知你无法分析文件。 这意味着在 HTML 标记上方找不到“Codebehind”或“Src”属性。

如果 Web 窗体或用户控件不包含其中任一属性,则向导找不到匹配的代码隐藏文件,并且无法转换页面。

如何解决

如果纯 HTML 页面出现此错误,则可以忽略此错误 —如果应用程序具有使用 aspx 扩展的纯 HTML 页面,则经常会遇到此错误。

若要避免此问题,请确保正确命名 html 文件,并在 Web 窗体和 HTML 标记上方的用户控件中使用“Codebehind”和“Src”属性。

请注意 ,在 Web 项目迁移向导的下一个版本中,将使用以下消息使此错误更具描述性。

  • “警告:无法分析文件 %1,因为找不到代码隐藏属性或页面/控件指令。”
  • “警告:代码文件 %1 不是有效的代码文件。”

第 3 部分:其他转换问题

下面是可能遇到的其他不太常见的转换问题。

问题 11:Web 项目文件夹中的备份文件夹

如前所述,Visual Studio 2005 通常将文件夹或子文件夹中的所有文件视为 Web 项目的一部分。 默认情况下,转换向导将在安全位置创建 Web 项目的备份,但用户可能会覆盖默认值。 如果将备份文件夹放在 Web 应用程序的文件夹树中,则会出现以下有点神秘的生成错误:

Error 1 - It is an error to use a section registered as 
allowDefinition='MachineToApplication' beyond application level

如何解决

请确保备份位置不在 Web 应用程序的根文件夹或子文件夹中!

问题 12:位于同一位置的多个项目

如果 Web 项目与同一解决方案中的另一个项目共享文件夹位置,Visual Studio 2005 将考虑在单个 Web 应用程序的该文件夹部分中找到的所有文件。

如果它们都是 Web 项目,并且它们确实是独立的(即自包含的),则将它们转换为单个 Web 应用程序可能不会导致问题。 但是,在以下情况下,可能需要将这些项目分开:

  • 它是 Web 和客户端项目的混合
  • 使用不同的代码语言
  • 美学原因

如何解决

如果它们混合使用 Web 项目和客户端项目,则只需将客户端项目文件移动到其自己的文件夹中即可。

如果使用不同的代码语言,建议将 Web 项目移动到单独的文件夹中进行转换。 稍后,如果要将这些 Web 项目合并到单一多语言 Web 应用程序中,请查看 Visual Studio 2005 文档,了解如何构建 App_Code 文件夹并针对多种语言Web.config,并手动将 Web 项目合并到单个 Web 应用程序中。

问题 13:引用相同文件的多个项目

如果多个项目引用同一组文件,则这些常见文件可以迁移两次。

如何解决

确保给定文件仅由一个项目文件引用。

通常,引用同一组文件的多个项目意味着文件夹中的项目文件有重复或旧版本。 在这种情况下,可以删除或重命名额外的项目文件来解决此问题。

如果确实需要多个 Web 项目引用同一组文件,则最好将通用文件移到其自己的单独的客户端项目中,然后让多个 Web 项目引用该单独的客户端项目。 请参阅将 Web 项目转换为 Visual Studio .NET 2005 的分步指南

问题 14:访问修饰符无效

转换 Web 项目后,会收到“无效访问修饰符”错误。

由于 Visual Studio 2005 现在使用多个程序集,因此如果要从另一个程序集访问成员变量和函数,则需要修改对成员变量和函数的访问级别。

如何解决

查看代码并更改访问级别以允许访问。 通常,将修饰符更改为 public 可以解决问题。

注意 在执行此操作之前,应始终考虑成员变量或函数的安全性,即不建议盲目执行此操作。

问题 15:转换排除的文件

转换向导不会转换排除的文件,那么如何获取转换向导来转换这些文件?

如何解决

在转换之前,暂时将要转换的文件包含在 Web 项目中,并确保其生成操作未设置为“none”。

转换后,将转换文件。 然后,可以使用在 (“解决方案资源管理器”菜单上找到的“从项目中排除”功能) 再次排除该文件。

问题 16:重复变量声明

转换后,你可能会发现通过客户端脚本声明的控件对象也在分部类中声明。 示例可能如下所示:

文件 ASP.NET 1.x 代码
Page1.aspx
function Form1_onfocus() {
   var myType = <asp:literal id="myTypeId" runat="server" />;
}
Page1.ascx.cs
protected Literal myTypeId;

如何解决

根据设计,转换向导不会分析客户端脚本,也不会捕获此引用。 若要解决此问题,只需从分部类中删除 声明,代码即可编译。

文件 ASP.NET 2.0 代码
Page1.aspx
function Form1_onfocus() {
   var myType = <asp:literal id="myTypeId" runat="server" />;
}
Page1.ascx.cs
// protected Literal myTypeId;

问题 17:Sub-Web应用程序

如前所述,Visual Studio 2005 通常将文件夹或子文件夹中的所有文件视为 Web 项目的一部分。 但是,可以使用 IIS 管理器 (inetmgr) 将子文件夹设置为 IIS 虚拟文件夹,将子文件夹指定为其自己的 Web 应用程序。 当 Visual Studio 2005 发现此虚拟文件夹时,它不会将其视为 Web 应用程序的一部分。 如果通过 HTTP 打开 Web 项目,则此操作有效。

如果通过文件位置打开 Web 项目,则会出现此问题。 在这种情况下,Visual Studio 2005 将不知道它是 IIS 配置的 Web 应用程序,也不会发现 IIS 元信息,指出子文件夹是虚拟文件夹。 Visual Studio 2005 现在将尝试打开并编译 Web 应用程序以及子 Web 应用程序。

如果转换基于文件的 Web 项目,转换向导会发出以下警告。

警告:此 Web 项目已转换为基于文件的 Web 应用程序。 如果站点包含任何 IIS 元信息,例如标记为虚拟目录的子文件夹,建议关闭此网站,然后使用“打开网站”命令重新打开它,然后选择“本地 IIS”选项卡。

如何解决

请务必使用 IIS 管理器 (inetmgr) 将子 Web 应用程序标记为虚拟目录,并通过 HTTP 而不是文件位置打开 Web 项目,以便找到 IIS 元信息。

问题 18:未删除 OnInit ()

在 Visual Studio .NET 2003 中,设计器向代码隐藏类文件添加了自动生成的成员函数 OnInit () 和 InitializeComponent () 。 Visual Studio 2005 不使用这些函数,但如果存在,则会调用这些函数。 转换向导不会删除这些函数。

此行为是设计使然,因为向导不知道这些函数中是否存在用户代码,因此代码将按原样保留在代码隐藏文件中。

如何解决

查看函数以确保没有应保存的用户代码后,请从代码隐藏文件中删除这些函数。

Aa479312.oninit (en-us,MSDN.10) .gif

问题 19:XHTML 验证错误

转换 Web 项目后或打开已转换的 Web 项目时,生成 Web 项目后,错误窗口中会显示 XHTML 验证错误。

这是 Visual Studio 2005 的一项功能,旨在帮助你编写更多符合 XHTML 规范的代码。 (单击下图可查看较大的图像。)

单击此处查看较大的图像

如何解决

若要修复,应更改代码以匹配所面向的 XHTML 标准级别。 例如,严格级别为“XHTML 1.1”。

如果要关闭这些错误的显示,可以将验证级别设置为不太严格的级别。 默认情况下,转换 Web 项目时,验证级别设置为“Internet Explorer 6.0”,接近 Visual Studio .Net 2003 使用的验证级别。

可以通过单击“ 工具”,选择 “选项”,然后在“文本编辑器/HTML/验证”对话框中选择适当的级别来设置验证级别。

Aa479312.xhtmlval (en-us,MSDN.10) .gif

问题 20:多个配置

Visual Studio .Net 2003 允许 Web 项目具有多种配置(例如发布和调试)来配置生成和部署环境。

Visual Studio 2005 仅支持每个 Web 项目一个配置。 在转换期间,除非找到自定义配置,否则调试版本为默认值。 在这种情况下,对话框将提示你选择要在转换后的 Web 项目中使用的配置。

如何解决

解决方法是使用两个或更多与要支持的配置对应的 Web 配置文件。 复制要在操作期间Web.config的版本。

例如,对于发布配置,可以有一个 Web.config.release 文件,一个用于调试配置的 Web.config.debug 文件。 在调试或部署 Web 项目时,复制相应的文件以Web.config。

注意 Web 部署项目是一项技术预览功能,可用作 Visual Studio 2005 的 VSIP 外接程序,它将为 Web 项目提供真正的配置支持。 有关更多详细信息,请参阅上的 https://msdn.microsoft.com “Visual Studio 2005 Web 部署项目”白皮书。

问题 21:自动生成的成员隐藏继承的成员

如果使用基类 (Label1 定义控件变量,例如) 或用于派生类的事件处理程序,你可能会发现这些成员被 Visual Studio 2005 中页面分部类自动生成的成员隐藏。

Visual Studio 2005 生成页面类,通常看不到继承的成员。 因此,它将生成隐藏继承成员的控制变量或事件处理程序。

如何解决

ASP.NET 2.0 提供了一个名为 CodeFileBaseClass 的新属性来处理这种情况。 @Page@Control 指令现在支持此新属性,该属性指定页面的祖父类。 编译器在类生成期间使用此属性来获取对页面基类型的引用,并生成不隐藏基类型中继承成员的代码

文件 ASP.NET 2.0 代码
Base.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Base.aspx.cs" Inherits="myBase" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Base<br />
        <asp:Button ID="Button1" runat="server" 
         Text="Button" OnClick="Button1_Click" />
        <asp:Label ID="Label1" runat="server" 
         Text="Label"></asp:Label></div>
    </form>
</body>
</html>
Base.aspx.cs
public partial class myBase : System.Web.UI.Page {
  protected void Button1_Click(object sender, EventArgs e) {   
        Label1.Text = "Base";
}}
Derived.aspx
<%@ Reference Page="~/Base.aspx" %>
<%@ Page Language="C#" AutoEventWireup="true" 
CodeFileBaseClass="myBase" 
CodeFile="~/Derived.aspx.cs" 
Inherits="myDerived" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Derived<br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label></div>
    </form>
</body>
</html>
Derived.aspx.cs
public partial class myDerived : myBase
{
 // This is commented out since we will use 
 // the inherited functions and variables
 // protected void Button1_Click(object sender, EventArgs e)
 // {
 //    Label1.Text = "Derived";
 // }
}

问题 22:不明确的引用和命名冲突

.NET Framework 2.0 添加了大量新的命名空间和类。 其中一些可能会导致与 ASP.NET 1.x 应用程序冲突。 例如,新的个性化功能引入了名称为 Profile、Membership 和 MembershipUser 的类。 尤其要跟踪用户信息的开发人员通常会使用配置文件名称。 因此,如果应用程序中有 Profile 类,并且尝试使用任何新的个性化设置功能,则可能会遇到有关不明确类引用的编译器警告。

如何解决

提前规划命名冲突可能相当困难。 你需要快速浏览新的 ASP.NET 类。 如果看到可能与应用程序中的名称冲突,可以考虑使用显式命名。 例如,使用 System.Web.Security.Membership,而不是导入/使用 System.Web.Security,然后使用 Membership 类。

问题 23:多次调用事件处理程序

由于转换向导合并代码隐藏文件和 aspx 页的方式,可能会遇到在页面加载 (调用事件两次的情况,例如) 。 如果代码隐藏文件中的事件连接代码不在 InitializeComponent 方法中,则会出现这种情况。 如果转换向导位于 InitalizeComponent 方法中,则转换向导才足够智能,以便删除重复的连线。

你可能很难注意到此错误,因为在大多数情况下,第二个事件触发是无害的。 但是,如果发现自动调用的事件多次发生,则应检查已转换的代码隐藏文件,以查看处理程序是否已连接到该事件两次。 如果是这样,则必须手动删除第二个连接。

如何解决

可以通过扫描现有代码并确保代码隐藏文件的 InitialzeComponent 函数中包含所有事件连接,或者通过在页面中设置 AutoEventWireUp=False 来完全避免此问题。

问题 24:代码隐藏文件移动到App_Code文件夹

转换向导运行后,你可能会发现某些代码隐藏文件 (*.aspx.cs 或 *.ascx.vb,例如) 移动到App_Code文件夹。

这通常表示内容页的 Codebehind 指令格式不正确,并且未正确设置为代码隐藏文件。 换而言之,转换向导无法确定代码隐藏文件实际上已绑定到特定的 aspx 页。

转换向导会自动将所有独立类文件 (例如 *.cs 或 *.vb) 移动到 App_Code 文件夹。 如果 Codebehind 指令格式不正确,则代码隐藏文件将被视为独立类文件并移动到App_Code文件夹。

注意 (的 Web 服务文件(例如 *.asmx 和 *.asmx.cs) )不同于普通内容页及其代码隐藏页。 Web 服务文件的代码隐藏应位于 App_Code 文件夹中,因此,如果在此处找到一个,则不会出错。

也可能是 Web 窗体或用户控件迁移了两次,请参阅引用同一文件的多个 Web 项目问题,了解如何更正此问题。

如何解决

在转换之前,可以通过确保在所有内容页面中正确设置 Codebehind 指令来避免此问题。

转换后,将代码隐藏文件移动到与关联内容页相同的文件夹,并更正 ASP.NET 2.0) 指令中重命名的内容页的 Codefile (指向该代码隐藏文件。

问题 25:引用 Web 项目的项目

在 Visual Studio .Net 2003 中,让项目引用 Web 项目的程序集是有效的。 这在 Visual Studio 2005 中不起作用,因为 Web 项目会创建多个程序集,并且程序集的文件名可以在内部版本间更改。

如何解决

在转换之前,需要将通用的共享代码移动到单独的类库,并改为引用该库。

如果使用共享用户控件,则必须创建类库中存在的基类,供其他项目引用,并让 Web 项目的用户控件派生自它们。

有关此设计模式的详细信息,请参阅 将 Web 项目转换为 Visual Studio .NET 2005 的分步指南

问题 26:共享相同的代码隐藏文件

可以让多个页面共享同一个代码隐藏类文件。 这可能是由于用户设计或复制 Web 窗体或用户控件而未正确更新 @Page 指令的结果。

这可能会混淆 ASP.NET 2.0 编译器,后者要求每个 Web 窗体或用户控件包含唯一的代码隐藏文件。 运行转换后的代码时,可能会出现生成错误或运行时行为无效。

如何解决

在转换之前,请更改代码,以便为每个 Web 窗体和用户控件使用唯一的代码隐藏文件。

如果要在多个 Web 窗体或用户控件之间共享公共元素,请将这些常见元素移动到基类,并使 Web 窗体或用户控件派生自该基类。

问题 27:部分转换的解决方案

在 Visual Studio .NET 2003 和 Visual Studio 2005 中,可以有一个同时包含 Web 项目和客户端项目的解决方案,例如 C# 或 Visual Basic 类库或 Windows 应用程序

如果使用快速产品(如 Visual Web Developer 或 Visual Basic Express Edition),则只能转换解决方案中与快速产品相关的项目。 例如,如果使用 Visual Web Developer 并打开包含 Web 项目和 Visual Basic 类库项目的解决方案,则只会转换 Web 项目,留下一个部分转换的解决方案。

如何解决

应使用 Visual Studio 2005 的标准版、专业版或团队系统版来转换包含多个混合项目类型的解决方案。

如果不可能 (只有 Express 版本) ,则应创建一个仅包含支持的项目类型的新解决方案。

问题 28:没有 C 命令行迁移#

Visual Basic Web 项目的命令行迁移可以使用命令“”devenv.exe <PorSfile> /upgrade,其中 <PorSfile> 是 Visual Basic Web 项目文件或包含此类文件的解决方案。

遗憾的是,在产品周期的后期发现了一个 C# bug,其中向 Web 项目转换向导提供了无效的 C# 代码模型。 因此,在命令行 C# Web 项目转换期间,Web 应用程序会引入错误。

由于与通过用户界面进行转换相比,命令行转换被视为辅助功能,并且此 bug 的 C# 修复威胁了 Visual Studio 2005 的发布日期,因此在最终版本中未修复该 bug。

如何解决

没有解决方法,但解决方法是使用用户界面打开和转换 Web 项目或包含 Web 项目的解决方案。

问题 29:Batch = True 或 False

如 Web 项目更改中所述,ASP.NET 编译器的默认行为是将文件夹中的所有 Web 窗体和用户控件编译为其自己的程序集。 可以在 Web.config 中设置 Batch 属性,以更改编译器的行为。

例如,以下代码段将指示编译器将给定的 Web 窗体或用户控件编译到其自己的程序集中, (创建比正常) 更多的程序集。

文件 ASP.NET 2.0 代码
Web.config
<configuration>
    <system.Web>
        <compilation batch="false">
        </compilation>
    </system.Web>
</configuration>

使用此属性时,应注意几个问题。

  • 性能 - 当 Batch=false 时,ASP.NET 编译器将为 Web 应用程序中的每个 Web 窗体和用户控件创建一个程序集。 使用 F5 生成时,它还会导致编译器在 Visual Studio 2005 中执行完整编译,而不是增量编译。 最终结果是 Web 应用程序在部署时运行速度可能会变慢,并且生成时间将在 Visual Studio 2005 中显著增加。
  • 程序集引用 - Batch 属性可能会在 Batch=True) 时隐藏可能损坏的程序集引用 (,甚至在 Batch=False) 时引入循环引用 (。

如何解决

在 Web 项目上运行转换向导后,应在完成手动步骤以转换 Web 项目时暂时设置 Batch=False 。 这将确保捕获任何程序集引用问题。

完全转换 Web 项目后,应将 Batch=True 设置为正常开发和部署。

注意部署 Web 应用程序时,应使用 Batch=False 执行一次最终检查,以确保在 Web 应用程序开发过程中未引入程序集引用问题。 完成此检查后,请务必再次将 Batch=True。

总结

将应用程序从 Visual Studio .NET 2003 转换为 Visual Studio 2005 通常是一个顺利的过程。 但是,必须确保正确配置开发和部署环境。 还必须评估转换报告,以解决转换向导未处理的任何潜在问题。 你可能还希望提前查看应用程序并提前计划,以避免转换的已知问题。

未来将要发布的版本

鉴于 Web 项目迁移的重要性,我们一直在寻找反馈来改进此体验。 即使在 2005 年 11 月 Visual Studio 2005 正式发布之后,我们仍计划根据需要更新迁移向导。 如果有疑问或反馈,请将其发布到位于 的“Visual Studio .NET 2003 到 Visual Studio 2005 迁移”论坛。http://forums.asp.net

附录 A:实际错误消息

实际错误消息 ) (可能出现的问题
错误 1 – 当前上下文中不存在名称“Page1” 生成错误 代码隐藏类文件 (CB) 引用

(SA-CB) 引用的独立类文件

错误 1 - 找不到文件“Page1.aspx.cs” 生成错误 引用相同文件的多个项目
警告:代码隐藏文件“Page1.aspx.cs”也标记为“Page2.aspx”的代码隐藏。 这可能会导致生成错误 转换向导 共享相同的代码隐藏文件
警告:此 Web 项目已转换为基于文件的 Web 应用程序。 如果站点包含任何 IIS 元信息,例如标记为虚拟目录的子文件夹,建议关闭此网站并使用“打开网站”命令重新打开它,然后选择“本地 IIS”选项卡 转换向导 子 Web 应用程序
错误:已删除“Label1”的成员声明,其辅助功能已从“public”更改为“protected”。 若要从另一个页面访问此成员,应为其创建公共访问器属性 转换向导 访问自动生成的控件变量
错误:以下文件未迁移,因为未在项目文件中找到它们,或者关联的“BuildAction”设置为“无”。 可能需要在转换过程后从项目中排除这些文件,以便编译网站:文件列表 == Page1.aspx,
Page1.aspx.cs
转换向导 不再排除排除的文件
警告:资源文件已移动到“App_GlobalResources”文件夹。 使用资源的代码可能必须手动修复 转换向导 资源管理器
错误 1:无法加载类型“myApp.Page1” 生成错误 Codebehind 指令指向未转换的文件。 请参阅不再排除排除的文件。
错误 1:“myApp.Control1.Label1”因其保护级别而无法访问 生成错误 无效的访问修饰符
“/myApp”应用程序中的服务器错误。 无法加载文件或程序集“myApp”或其依赖项之一。 系统找不到指定的文件。 服务器错误 资源管理器
错误 1:验证 (XHTML 1.1) :此名称包含不允许的大写字符 生成错误 XHTML 验证错误
错误 1:使用注册为 allowDefinition = 'MachineToApplication' 的节超出应用程序级别时出错 生成错误 Web 项目文件夹中的备份文件夹

Sub-Web应用程序

由于页面中出现错误,无法切换到“设计”视图。 请在错误列表中关联标记为“无法切换:”的所有错误,然后重试 “错误”对话框 无法切换到设计视图
错误 1:找不到文件“Page1.aspx.cs” 生成错误 引用相同文件的多个项目
错误 1:不允许循环文件引用 生成错误 循环引用

© Microsoft Corporation. 保留所有权利。