第 1 部分:Web 项目更改
将 Visual Studio 2002/2003 Web 项目转换为 Visual Studio 2005 时,可能会遇到因 Web 项目系统中的更改而产生的问题。本文,我们将探讨转换过程以及该过程中可能会遇到的一些常见问题。
ASP.NET 和 Visual Studio 是什么?
ASP.NET 是一种创建动态 Web 应用程序的技术。编译 ASP.NET 页(Web 窗体),因此可以生成功能强大、基于窗体的 Web 页。生成这些页时,可以使用 ASP.NET 用户控件创建常见的 UI 元素,并对它们进行常规任务的编程。
Visual Studio 是一个集成开发环境 (IDE),开发人员可以使用它通过众多编程语言(包括 C# 和 Visual Basic)中的一种来创建用于 .NET Framework 的程序。
您将发现,转换 Web 应用程序以使用 Visual Studio 2005 和 ASP.NET 2.0 的新增功能可以简化开发工作,并为编译和部署代码提供了更多的选择。
Web 项目更改
这些更改影响开发、配置和部署 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 站点。例如,可以让每个用户选择一种站点布局或配色方案,并在下一次访问之前保留该信息。Web 部件使您可以用最少的新增代码提供个性化功能。
• 数据访问
不仅针对 .NET Framework 2.0 更新了 ADO.NET,而且 ASP.NET 2.0 现在还包括一组用于数据访问、新的数据源控件和功能。
• 母版页
在传统的 ASP.NET 中,大多数开发人员在努力设计一个将代码重用和灵活性相结合的 Web 应用程序框架。通过引入真正的继承,母版页将代码重用和灵活性发挥到最好。可以建立一个包含页眉、页脚和导航栏的母版页,然后创建子页,子页在填充内容的同时自动继承母版页的外观、行为和功能。
• ASP.NET 开发服务器
独立、仅用于开发的 Web 服务器现在与 Visual Studio 2005 捆绑在一起。该服务器(代号为“Cassini”)使用户无需在其开发系统上安装 IIS,即可开发和测试他们的 Web 应用程序。该服务器只能用于开发。将应用程序部署到生产中后,您需要使用配置了 ASP.NET 2.0 的 IIS 服务器。
转换 Web 项目
转换 Web 项目不仅仅需要更改框架版本!转换包括三个部分:
1.
转换前 — 在运行转换向导之前,查看并有可能修改 Web 项目的体系结构。
2.
转换 — 运行 Visual Studio 2005 转换向导以转换 Web 项目。
3.
转换后 — 解决转换向导没有发现或者无法解决的任何问题。
对于第 1 部分和第 2 部分,您应该阅读并应用将 Web 项目转换到 Visual Studio 2005 的分步指南中列出的步骤。
对于第 3 部分,您应该应用本白皮书中列出的解决方案。
转换向导
Visual Studio 2005 有一个内置的转换向导,用来帮助您转换 Web 应用程序。该向导自动完成将应用程序转换为使用 ASP.NET 2.0 功能所必需的许多基本步骤。
运行向导
只要您在 Visual Studio 2005 中打开一个Visual Studio .NET 2003 Web 项目,就会自动调用该向导。该向导检测应用程序文件夹中是否存在 Web 项目文件(例如 *.vbproj 或 *.csproj),然后自动开始转换过程。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet01.gif)
图 1. 转换向导
首先,要选择是否在转换之前创建应用程序的备份。强烈建议您进行备份!
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet02.gif)
图 2. 备份应用程序
如果选择创建备份,则 Visual Studio 2005 将在您选择的文件夹中自动创建 Web 项目的副本。
注 确保将备份文件夹放在 Web 应用程序的文件夹树外面。有关详细信息,请参阅备份位于 Web 应用程序文件夹中的文件夹。
接下来,您将看到转换过程的摘要屏幕,您还有最后一次机会取消转换。请注意有关此摘要屏幕的两件事情:
注 第一段是错误的,因为它声明在进行更改之前会将 Web 项目从源代码控件中签出。这只对 Visual Basic 和 C# 客户端项目有效,对于 Web 项目无效。相反,Web 项目转换向导将忽略源代码控件,并且更改那些它必须将其更改为读写的文件。
Web 项目将进行就地转换,这就是备份之所以受到推崇且很重要的原因。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet03.gif)
图 3. 摘要屏幕
转换可能要花几分钟,这取决于应用程序的大小。转换完成后,您将看到一条指出 Web 项目已经转换的消息。您可能还会看到一条有关一些警告或错误的消息。当转换向导进行了一些可能修改应用程序行为的更改,或不能完全更新 Web 项目时,就会出现警告和错误。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet04.gif)
图 4. 转换完成
转换完成后,应该查看转换报告以了解是否必须执行任何其他手动步骤来完成转换。
转换报告
转换向导将在 XML 文件和文本文件中记录对 Web 项目所做的更改。转换向导完成后,它会显示 XML 版本的报告。该报告将向您显示向导遇到的所有问题以及代码区域,您可能需要在代码区域采取其他步骤才能完成向导。
该报告分成两部分,一部分是转换的解决方案,另一部分是一个或多个项目。解决方案报告几乎都是没有错误的。然而,项目部分会针对项目中的每个文件列出多个问题。您应该查看该部分,然后解决转换向导报告的所有问题。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/conversion-report-sm.gif)
图 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) 引用
注CB 是 Web 窗体 (*.aspx) 或用户控件 (*.ascx) 的代码隐藏文件的缩写。
新的编译模型使用多个通常在服务器上动态编译的程序集。该模型改善了 Web 站点的性能和可更新性。
然而,如果您的代码隐藏文件引用其他的代码隐藏文件,那么您将有一个中断的引用,这是因为引用的代码隐藏文件将不再位于同一个程序集中。
以下是一些可能引发此问题的常见方式:
• 使用 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");
将代码更改为使用引用指令:
文件 ASP.NET 2.0 代码
Page1.ascx
<%@ Reference Control="~/Control1.ascx" %>
Page1.ascx.cs
Control1 c = (Control1)LoadControl("~/Control1.ascx");
通过使用引用指令,明确地通知编译器在哪里寻找您要使用的 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();
}
由于抽象基类现在位于 App_Code 文件夹中,因此允许独立类文件和 CB 文件在编译期间找到一个类(本例中名为 Control1)。然而,独立类文件将在运行时使用后绑定加载原始类(在本例中,重命名为 migrated_control)。注意:在 Visual Studio 2005 的最新版本中,转换向导将自动创建此代码。
问题 3:循环引用
如果代码隐藏文件引用其他代码隐藏
文件,这个被引用的代码隐藏文件又引用原始文件,就会发生循环应用。这种情况可能发生在两个或更多代码隐藏文件中,例如:
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/circular-ref1.gif)
还会发生在程序集之间,其中一个程序集引用另一个
程序集,引用的程序集又引用原始程序集,例如:
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/circular-ref2.gif)
如何修复
第一种循环引用的解决方案是:用其中一个引用在 App_Code 文件夹中创建一个抽象基类,然后从相关联的 Web 窗体或用户控件文件中删除引用指令。这将破坏循环引用。
第二种循环引用是 ASP.NET 编译器由于性能原因而“批处理”程序集的副产品。默认情况下,它将 Web 窗体和用户控件放在一个文件夹中,然后将它们编译成一个程序集。
解决此问题的方式有很多,但是我们建议将引用的页(例如,Pages2.aspx.vb 和 Pages3.aspx.vb)移动到它们自己的文件夹中。
默认情况下,ASP.NET 编译器将创建一个包含这些页的单独的程序集,程序集 A 和 B 之间的循环引用将被删除。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/circular-ref3.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 自动将在该文件夹中找到的所有资源用于 Web 应用程序(利用 IntelliSense 使资源成为可发现的)。下面是转换后的示例:
文件 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 项目中包括文件。如果没有明确列出包含某个文件,则该文件会排除在项目之外。还可以通过将一个代码文件的生成操作设为“none”,来停止生成该代码文件。该信息存储在项目文件中。
转换时必须考虑几个问题,例如:
• 排除在一个项目之外的文件可能包括在另一个项目中
• 您是否会因为一个排除的文件可能是用户想要记住的一个代码片段就尝试转换它呢?
在 Visual Studio 2005 的最新版本中,转换向导将原样保留排除的文件并在转换报告中注明。因此,您的 Web 项目将包含额外的、未转换的文件,它们现在是项目的一部分。根据文件的扩展名,编译器可能会尝试编译该文件,这可能会引发应用程序中的冲突。
如何修复
转换之后,可以从项目中删除任何不想要的、以前排除的文件。您也可以使用“Exclude from Project”功能(可以在解决方案资源管理器找到)排除它们,通过使用安全的扩展名“.exclude”对它们进行重命名,以便有效地从 Web 应用程序中删除它们。
注 用“.exclude”扩展名排除的文件仍然是 Web 项目的一部分,但不对它们进行编译,如果它们碰巧在服务器上,IIS/ASP.NET 也不支持这些文件。注 未来版本的转换向导将更主动,并且在它认为安全的情况下将排除文件。
问题 6:孤立的 resx 文件
Visual Studio .NET 2003 为 Web 窗体和用户控件生成了一个 resx(资源)文件。通常情况下,用户不使用这些文件,因为它们是自动生成的并且可能会改写用户添加的代码。
转换之后并不删除这些 resx 文件,因为迁移向导不确定用户是否已经添加了需要保存的资源。
如何修复
查看生成的 resx 文件并将用户数据保存到它自己的资源文件中。将该数据合并到一个资源文件中会更好。
根据需要将该资源文件移到特殊的文件夹 App_GlobalResources or App_LocalResources 中,这样 Web 应用程序就可以使用它了。
用这种方式保存用户数据后,从 Web 项目中删除生成的 resx 文件。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/issue-orphaned-resx.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 hidden partial class
// 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 2005 中内置的新 Visual Web 设计器在正确的 HTML 方面比 Visual Studio .NET 2003 更严格。如果 aspx 页包含不匹配的标记或格式不正确的 HTML,则该设计器将不允许您在 Visual Studio 2005 内切换到设计视图。相反,您将被限制在代码视图,直到修复了问题为止。发生该问题的原因是 Visual Studio 2005 内置有新的源代码保留和验证功能。
如何修复
为了避免此问题,您所能做的就是确保 aspx 页中的标记格式正确。如果在从代码视图切换到设计视图的后转换时遇到问题,则该问题几乎肯定是错误的标记。
问题 10:无法解析文件名
您可能会看到有些模糊的错误消息,告诉您无法解析某个文件。这意味着在 HTML 标记上找不到 ‘Codebehind’ 或 ‘Src’ 属性。
如果您的 Web 窗体或用户控件不包含以上任何一个属性,则该向导找不到匹配的代码隐藏文件,也无法转换该页。
如何修复
如果这碰巧是一个纯 HTML 页,则该错误可以忽略,如果应用程序具有使用 aspx 扩展名的 HTML 页,则会经常遇到此错误。
为了避免此问题,请确保为 html 文件正确命名,并且在 HTML 标记上的 Web 窗体和用户控件中使用 ‘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 应用程序,则查看有关针对多种语言构建 App_Code 文件夹和 Web.config 的 Visual Studio 2005 文档,并手动将 Web 项目合并成一个 Web 应用程序。
问题 13:多个项目引用相同的文件
如果多个项目引用一组相同的文件,则这些公共文件可能会迁移两次。
如何修复
请确保只有一个项目文件引用给定的文件。
通常,多个项目引用一组相同的文件意味着文件夹中存在重复版本或旧版本的项目文件。在这种情况下,可以删除或重命名多余的项目文件以解决此问题。
如果确实需要多个 Web 引用一组相同的文件,最好将公共文件移到它们自己单独的客户端项目中,然后让多个 Web 项目引用单独的客户端项目。请参阅将 Web 项目转换到 Visual Studio 2005 的分步指南。
问题 14:无效的访问修饰符
转换完 Web 项目后,您将收到无效的访问修饰符错误。
由于 Visual Studio 2005 现在使用多个程序集,因此如果要从其他程序集访问成员变量和函数,需要更改它们的访问级别。
如何修复
检查您的代码,并更改访问级别以允许访问。通常,将修饰符更改为 public 将解决此问题。
注 在执行此操作之前,您应该始终关心成员变量或函数的安全性,即我们不建议您盲目执行此操作。
问题 15:转换排除的文件
转换向导不能转换排除的文件,因此如何才能让转换向导转换这些文件呢?
如何修复
转换之前,在 Web 项目中暂时包括希望转换的文件并确保它的生成操作没有设为“none”。
转换后,将转换该文件。然后,可以使用 Exclude from Project 功能(可以在解决方案资源管理器菜单上找到)再次排除该文件。
问题 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:子 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 元信息(例如,标记为虚拟路径的子文件夹),建议您关闭该 Web 站点,然后使用 Open Web Site 命令并选择 Local IIS 选项卡重新打开它。
如何修复
一定要使用 IIS 管理器 (inetmgr) 将子 Web 应用程序标记为虚拟目录,通过 HTTP 而不是文件位置来打开 Web 项目,这样就能找到 IIS 元信息。
问题 18:OnInit() 未删除
在 Visual Studio®.NET 2003 中,设计人员向代码隐藏类文件中添加了自动生成的成员函数 OnInit() 和 InitializeComponent()。Visual Studio 2005 不使用这些函数,但如果存在这些函数,则会调用它们。转换向导没有删除这些函数。
这一行为是构划好的,因为向导不知道这些函数内是否存在用户代码,因此代码隐藏文件中的代码原样保留。
如何修复
查看函数以确保没有要保存的用户代码,然后从代码隐藏文件中删除这些函数。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/oninit.gif)
问题 19:XHTML 验证错误
转换 Web 项目后或者打开转换的 Web 项目后,您将在生成 Web 项目后的错误窗口中看到 XHTML 验证错误。
这是 Visual Studio 2005 的一个功能,旨在帮助您编写与 XHTML 更兼容的代码。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/issue-validationS.gif)
如何修复
要修复此问题,应该更改代码以匹配您的目标 XHTML 标准级别。例如,严格的级别是“XHTML 1.1”。
如果想关闭这些错误的显示,可以将验证级别设置为不太严格的级别。默认情况下,转换一个 Web 项目后,验证级别设置为“Internet Explorer 6.0”,该级别接近 Visual Studio .Net 2003 使用的验证级别。
可以设置验证级别,方法是:单击 Tools,然后选择 Options,然后在 Text Editor/HTML/Validation 对话框上选择适当的级别。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/xhtmlval.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 项目的真正配置支持。有关更多详细信息,请参阅 http://msdn.microsoft.com 中的“Visual Studio 2005 Web Deployment Projects”白皮书。
问题 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 名称,它被那些想要跟踪用户信息的开发人员广泛使用。因此,如果应用程序中有一个 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 窗体或用户控件迁移两次。有关更正该问题的方法,请参阅 Multiple Web Projects Referencing the Same Files。
如何修复
转换前,通过确保所有内容页中的 Codebehind 指令设置正确,可避免此问题。
转换后,将代码隐藏文件移到相关内容页所在的文件夹中,并更正页的 Codefile(在 ASP.NET 2.0 中进行了重命名)指令以指向该代码隐藏文件。
问题 25:多个项目引用一个 Web 项目
在 Visual Studio .Net 2003 中,一个项目引用一个 Web 项目的程序集是无效的。这在 Visual Studio 2005 中不起作用,因为 Web 项目创建多个程序集,并且程序集的文件名会因不同的生成而异。
如何修复
转换之前,您需要将常用的共享代码移到单独的类库中,并引用该库。
如果您要使用共享代码控件,则必须创建基类,这些基类存在于其他项目要引用的类库中,并让 Web 项目的用户控件从这些基类派生。
有关此设计模式的更多信息,请参阅 将 Web 项目转换到 Visual Studio 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 应用程序
如果要使用 express 产品(例如,Visual Web Developer 或 Visual Basic Express Edition),您将只能转换与该 express 产品相关的解决方案中的项目。例如,如果您正在使用 Visual Web Developer,并且打开了一个带有 Web 项目和 Visual Basic 类库项目的解决方案,则只会转换 Web 项目,这因此产生一个部分转换的解决方案。
如何修复
您应该使用 Visual Studio 2005 的 Standard、Professional 或 Team System 版本转换包含多个、混合项目类型的解决方案。
如果不可能这么做(您只有一个 Express 版本),您应该新建一个只包含支持的项目类型的解决方案。
问题 28:没有针对 C# 的命令行迁移
通过使用“devenv.exe /upgrade”命令(其中 是一个 Visual Basic Web 项目文件或包含这样文件的解决方案),Visual Basic Web 项目的命令行迁移是可能的。
遗憾的是,在产品周期的后期会发现 C# 错误:为 Web 项目转换向导提供了无效的 C# 代码模型。因此,在命令行 C# Web 项目转换期间,Web 应用程序中会引入错误。
因为与通过用户界面进行转换相比,命令行转换被看作辅助功能,因此对此错误进行 C# 修复会影响 Visual Studio 2005 的发布日期,因此最新发布版本中没有修复此错误。
如何修复
虽然没有修复,但替代方案是使用用户界面打开并转换 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 窗体和用户控件创建一个程序集。当您在 Visual Studio 2005 中使用 F5 生成时,它还会导致编译器进行全编译,而不是增量式编译。最终结果是,在部署时 Web 应用程序可能运行的较慢,您在 Visual Studio 2005 中的生成时间会显著增加。
• 程序集引用 — Batch 属性可能会隐藏可能的中断的程序集引用(如果 Batch=True),甚至会引入循环引用(如果 Batch=False)。
如何修复
在一个 Web 项目上运行了转换向导后,应该临时设置 Batch=False,同时完成手动步骤以转换 Web 项目。这样可以确保您发现所有程序集引用问题。
Web 项目完全转换后,您应该设置 Batch=True 以进行正常开发和部署。
注 部署 Web 应用程序时,您应该在 Batch=False 的情况下进行以下检查之一,以确保在开发 Web 应用程序过程中没有引入任何程序集引用问题。进行了该检查之后,一定要再次设置 Batch=True。
返回页首
小结
将应用程序从 Visual Studio .NET 2003 转换到 Visual Studio 2005 通常是一个顺畅的过程。然而,您必须确保正确配置了开发和部署环境。您还必须评估转换报告,以解决转换报告没有处理的任何潜在问题。您可能还希望提前查看应用程序并且提前规划,以避免转换中已知的问题。
将来的发行版本
由于 Web 项目迁移的重要性,因此我们始终期待反馈以便丰富这方面的经验。即使在 2005 年 11 月正式发布了 Visual Studio 2005 后,我们仍计划根据需要更新迁移向导。如果您有问题或反馈,请将它们发送到 http://forums.asp.net 上的“Visual Studio .NET 2003 to Visual Studio 2005 Migration”论坛上。
返回页首
附录 A:实际错误消息
实际错误消息 原因 可能的问题(一个或多个)
错误 1 — The name ‘Page1’ does not exist in the current context
生成错误
代码隐藏类文件 (CB-CB) 引用
独立类文件 (SA-CB) 引用
错误 1 - File 'Page1.aspx.cs' was not found
生成错误
多个项目引用相同的文件
警告: Code-behind file 'Page1.aspx.cs' is marked as code-behind for 'Page2.aspx' too. This may cause build errors
转换向导
共享相同的代码隐藏文件
警告: This Web project was converted as a file-based Web application. If your site contained any IIS meta-information, e.g. sub-folders marked as virtual directories, it is recommended that you close this Web site and re-open it using the Open Web Site command and selecting the Local IIS tab
转换向导
子 Web 应用程序
错误: The member declaration for 'Label1' was removed and its accessibility has been changed from 'public' to 'protected'. To access this member from another page you should create a public accessor property for it
转换向导
访问自动生成的控制变量
错误: The following files were not migrated because they were not found in the project file or the associated 'BuildAction' is set to 'None'. You may need to exclude these files from the project after the conversion process in order to compile your Web site: File List == Page1.aspx,
Page1.aspx.cs
转换向导
不再对已排除的文件进行排除
警告: Resource files were moved to 'App_GlobalResources' folder. Code using resources may have to be fixed manually
转换向导
资源管理器
错误 1: Could not load type 'myApp.Page1'
生成错误
Codebehind 指令正指向一个未转换的文件。请参阅已排除的文件不再被排除。
Error 1: 'myApp.Control1.Label1' is inaccessible due to its protection level
生成错误
无效的访问修饰符
Server Error in '/myApp' Application. Could not load file or assembly 'myApp' or one of its dependencies. The system cannot find the file specified
服务器错误
资源管理器
错误 1:Validation (XHTML 1.1): This name contains uppercase characters, which is not allowed
生成错误
XHTML 验证错误
错误 1: It is an error to use a section registered as allowDefinition = 'MachineToApplication' beyond application level
生成错误
备份文件夹位于 Web 项目文件夹中
子 Web 应用程序
Cannot switch to Design view because of errors in the page. Please corrrect all errors labeled 'Cannot switch:' in the Error List and try again
错误对话框
无法切换到设计视图
错误 1: File 'Page1.aspx.cs' was not found
生成错误
多个项目引用相同的文件
错误 1: Circular file references are not allowed
生成错误
循环引用
将 Visual Studio 2002/2003 Web 项目转换为 Visual Studio 2005 时,可能会遇到因 Web 项目系统中的更改而产生的问题。本文,我们将探讨转换过程以及该过程中可能会遇到的一些常见问题。
ASP.NET 和 Visual Studio 是什么?
ASP.NET 是一种创建动态 Web 应用程序的技术。编译 ASP.NET 页(Web 窗体),因此可以生成功能强大、基于窗体的 Web 页。生成这些页时,可以使用 ASP.NET 用户控件创建常见的 UI 元素,并对它们进行常规任务的编程。
Visual Studio 是一个集成开发环境 (IDE),开发人员可以使用它通过众多编程语言(包括 C# 和 Visual Basic)中的一种来创建用于 .NET Framework 的程序。
您将发现,转换 Web 应用程序以使用 Visual Studio 2005 和 ASP.NET 2.0 的新增功能可以简化开发工作,并为编译和部署代码提供了更多的选择。
Web 项目更改
这些更改影响开发、配置和部署 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 站点。例如,可以让每个用户选择一种站点布局或配色方案,并在下一次访问之前保留该信息。Web 部件使您可以用最少的新增代码提供个性化功能。
• 数据访问
不仅针对 .NET Framework 2.0 更新了 ADO.NET,而且 ASP.NET 2.0 现在还包括一组用于数据访问、新的数据源控件和功能。
• 母版页
在传统的 ASP.NET 中,大多数开发人员在努力设计一个将代码重用和灵活性相结合的 Web 应用程序框架。通过引入真正的继承,母版页将代码重用和灵活性发挥到最好。可以建立一个包含页眉、页脚和导航栏的母版页,然后创建子页,子页在填充内容的同时自动继承母版页的外观、行为和功能。
• ASP.NET 开发服务器
独立、仅用于开发的 Web 服务器现在与 Visual Studio 2005 捆绑在一起。该服务器(代号为“Cassini”)使用户无需在其开发系统上安装 IIS,即可开发和测试他们的 Web 应用程序。该服务器只能用于开发。将应用程序部署到生产中后,您需要使用配置了 ASP.NET 2.0 的 IIS 服务器。
转换 Web 项目
转换 Web 项目不仅仅需要更改框架版本!转换包括三个部分:
1.
转换前 — 在运行转换向导之前,查看并有可能修改 Web 项目的体系结构。
2.
转换 — 运行 Visual Studio 2005 转换向导以转换 Web 项目。
3.
转换后 — 解决转换向导没有发现或者无法解决的任何问题。
对于第 1 部分和第 2 部分,您应该阅读并应用将 Web 项目转换到 Visual Studio 2005 的分步指南中列出的步骤。
对于第 3 部分,您应该应用本白皮书中列出的解决方案。
转换向导
Visual Studio 2005 有一个内置的转换向导,用来帮助您转换 Web 应用程序。该向导自动完成将应用程序转换为使用 ASP.NET 2.0 功能所必需的许多基本步骤。
运行向导
只要您在 Visual Studio 2005 中打开一个Visual Studio .NET 2003 Web 项目,就会自动调用该向导。该向导检测应用程序文件夹中是否存在 Web 项目文件(例如 *.vbproj 或 *.csproj),然后自动开始转换过程。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet01.gif)
图 1. 转换向导
首先,要选择是否在转换之前创建应用程序的备份。强烈建议您进行备份!
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet02.gif)
图 2. 备份应用程序
如果选择创建备份,则 Visual Studio 2005 将在您选择的文件夹中自动创建 Web 项目的副本。
注 确保将备份文件夹放在 Web 应用程序的文件夹树外面。有关详细信息,请参阅备份位于 Web 应用程序文件夹中的文件夹。
接下来,您将看到转换过程的摘要屏幕,您还有最后一次机会取消转换。请注意有关此摘要屏幕的两件事情:
注 第一段是错误的,因为它声明在进行更改之前会将 Web 项目从源代码控件中签出。这只对 Visual Basic 和 C# 客户端项目有效,对于 Web 项目无效。相反,Web 项目转换向导将忽略源代码控件,并且更改那些它必须将其更改为读写的文件。
Web 项目将进行就地转换,这就是备份之所以受到推崇且很重要的原因。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet03.gif)
图 3. 摘要屏幕
转换可能要花几分钟,这取决于应用程序的大小。转换完成后,您将看到一条指出 Web 项目已经转换的消息。您可能还会看到一条有关一些警告或错误的消息。当转换向导进行了一些可能修改应用程序行为的更改,或不能完全更新 Web 项目时,就会出现警告和错误。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/upgradingaspnet04.gif)
图 4. 转换完成
转换完成后,应该查看转换报告以了解是否必须执行任何其他手动步骤来完成转换。
转换报告
转换向导将在 XML 文件和文本文件中记录对 Web 项目所做的更改。转换向导完成后,它会显示 XML 版本的报告。该报告将向您显示向导遇到的所有问题以及代码区域,您可能需要在代码区域采取其他步骤才能完成向导。
该报告分成两部分,一部分是转换的解决方案,另一部分是一个或多个项目。解决方案报告几乎都是没有错误的。然而,项目部分会针对项目中的每个文件列出多个问题。您应该查看该部分,然后解决转换向导报告的所有问题。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/conversion-report-sm.gif)
图 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) 引用
注CB 是 Web 窗体 (*.aspx) 或用户控件 (*.ascx) 的代码隐藏文件的缩写。
新的编译模型使用多个通常在服务器上动态编译的程序集。该模型改善了 Web 站点的性能和可更新性。
然而,如果您的代码隐藏文件引用其他的代码隐藏文件,那么您将有一个中断的引用,这是因为引用的代码隐藏文件将不再位于同一个程序集中。
以下是一些可能引发此问题的常见方式:
• 使用 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");
将代码更改为使用引用指令:
文件 ASP.NET 2.0 代码
Page1.ascx
<%@ Reference Control="~/Control1.ascx" %>
Page1.ascx.cs
Control1 c = (Control1)LoadControl("~/Control1.ascx");
通过使用引用指令,明确地通知编译器在哪里寻找您要使用的 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();
}
由于抽象基类现在位于 App_Code 文件夹中,因此允许独立类文件和 CB 文件在编译期间找到一个类(本例中名为 Control1)。然而,独立类文件将在运行时使用后绑定加载原始类(在本例中,重命名为 migrated_control)。注意:在 Visual Studio 2005 的最新版本中,转换向导将自动创建此代码。
问题 3:循环引用
如果代码隐藏文件引用其他代码隐藏
文件,这个被引用的代码隐藏文件又引用原始文件,就会发生循环应用。这种情况可能发生在两个或更多代码隐藏文件中,例如:
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/circular-ref1.gif)
还会发生在程序集之间,其中一个程序集引用另一个
程序集,引用的程序集又引用原始程序集,例如:
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/circular-ref2.gif)
如何修复
第一种循环引用的解决方案是:用其中一个引用在 App_Code 文件夹中创建一个抽象基类,然后从相关联的 Web 窗体或用户控件文件中删除引用指令。这将破坏循环引用。
第二种循环引用是 ASP.NET 编译器由于性能原因而“批处理”程序集的副产品。默认情况下,它将 Web 窗体和用户控件放在一个文件夹中,然后将它们编译成一个程序集。
解决此问题的方式有很多,但是我们建议将引用的页(例如,Pages2.aspx.vb 和 Pages3.aspx.vb)移动到它们自己的文件夹中。
默认情况下,ASP.NET 编译器将创建一个包含这些页的单独的程序集,程序集 A 和 B 之间的循环引用将被删除。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/circular-ref3.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 自动将在该文件夹中找到的所有资源用于 Web 应用程序(利用 IntelliSense 使资源成为可发现的)。下面是转换后的示例:
文件 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 项目中包括文件。如果没有明确列出包含某个文件,则该文件会排除在项目之外。还可以通过将一个代码文件的生成操作设为“none”,来停止生成该代码文件。该信息存储在项目文件中。
转换时必须考虑几个问题,例如:
• 排除在一个项目之外的文件可能包括在另一个项目中
• 您是否会因为一个排除的文件可能是用户想要记住的一个代码片段就尝试转换它呢?
在 Visual Studio 2005 的最新版本中,转换向导将原样保留排除的文件并在转换报告中注明。因此,您的 Web 项目将包含额外的、未转换的文件,它们现在是项目的一部分。根据文件的扩展名,编译器可能会尝试编译该文件,这可能会引发应用程序中的冲突。
如何修复
转换之后,可以从项目中删除任何不想要的、以前排除的文件。您也可以使用“Exclude from Project”功能(可以在解决方案资源管理器找到)排除它们,通过使用安全的扩展名“.exclude”对它们进行重命名,以便有效地从 Web 应用程序中删除它们。
注 用“.exclude”扩展名排除的文件仍然是 Web 项目的一部分,但不对它们进行编译,如果它们碰巧在服务器上,IIS/ASP.NET 也不支持这些文件。注 未来版本的转换向导将更主动,并且在它认为安全的情况下将排除文件。
问题 6:孤立的 resx 文件
Visual Studio .NET 2003 为 Web 窗体和用户控件生成了一个 resx(资源)文件。通常情况下,用户不使用这些文件,因为它们是自动生成的并且可能会改写用户添加的代码。
转换之后并不删除这些 resx 文件,因为迁移向导不确定用户是否已经添加了需要保存的资源。
如何修复
查看生成的 resx 文件并将用户数据保存到它自己的资源文件中。将该数据合并到一个资源文件中会更好。
根据需要将该资源文件移到特殊的文件夹 App_GlobalResources or App_LocalResources 中,这样 Web 应用程序就可以使用它了。
用这种方式保存用户数据后,从 Web 项目中删除生成的 resx 文件。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/issue-orphaned-resx.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 hidden partial class
// 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 2005 中内置的新 Visual Web 设计器在正确的 HTML 方面比 Visual Studio .NET 2003 更严格。如果 aspx 页包含不匹配的标记或格式不正确的 HTML,则该设计器将不允许您在 Visual Studio 2005 内切换到设计视图。相反,您将被限制在代码视图,直到修复了问题为止。发生该问题的原因是 Visual Studio 2005 内置有新的源代码保留和验证功能。
如何修复
为了避免此问题,您所能做的就是确保 aspx 页中的标记格式正确。如果在从代码视图切换到设计视图的后转换时遇到问题,则该问题几乎肯定是错误的标记。
问题 10:无法解析文件名
您可能会看到有些模糊的错误消息,告诉您无法解析某个文件。这意味着在 HTML 标记上找不到 ‘Codebehind’ 或 ‘Src’ 属性。
如果您的 Web 窗体或用户控件不包含以上任何一个属性,则该向导找不到匹配的代码隐藏文件,也无法转换该页。
如何修复
如果这碰巧是一个纯 HTML 页,则该错误可以忽略,如果应用程序具有使用 aspx 扩展名的 HTML 页,则会经常遇到此错误。
为了避免此问题,请确保为 html 文件正确命名,并且在 HTML 标记上的 Web 窗体和用户控件中使用 ‘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 应用程序,则查看有关针对多种语言构建 App_Code 文件夹和 Web.config 的 Visual Studio 2005 文档,并手动将 Web 项目合并成一个 Web 应用程序。
问题 13:多个项目引用相同的文件
如果多个项目引用一组相同的文件,则这些公共文件可能会迁移两次。
如何修复
请确保只有一个项目文件引用给定的文件。
通常,多个项目引用一组相同的文件意味着文件夹中存在重复版本或旧版本的项目文件。在这种情况下,可以删除或重命名多余的项目文件以解决此问题。
如果确实需要多个 Web 引用一组相同的文件,最好将公共文件移到它们自己单独的客户端项目中,然后让多个 Web 项目引用单独的客户端项目。请参阅将 Web 项目转换到 Visual Studio 2005 的分步指南。
问题 14:无效的访问修饰符
转换完 Web 项目后,您将收到无效的访问修饰符错误。
由于 Visual Studio 2005 现在使用多个程序集,因此如果要从其他程序集访问成员变量和函数,需要更改它们的访问级别。
如何修复
检查您的代码,并更改访问级别以允许访问。通常,将修饰符更改为 public 将解决此问题。
注 在执行此操作之前,您应该始终关心成员变量或函数的安全性,即我们不建议您盲目执行此操作。
问题 15:转换排除的文件
转换向导不能转换排除的文件,因此如何才能让转换向导转换这些文件呢?
如何修复
转换之前,在 Web 项目中暂时包括希望转换的文件并确保它的生成操作没有设为“none”。
转换后,将转换该文件。然后,可以使用 Exclude from Project 功能(可以在解决方案资源管理器菜单上找到)再次排除该文件。
问题 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:子 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 元信息(例如,标记为虚拟路径的子文件夹),建议您关闭该 Web 站点,然后使用 Open Web Site 命令并选择 Local IIS 选项卡重新打开它。
如何修复
一定要使用 IIS 管理器 (inetmgr) 将子 Web 应用程序标记为虚拟目录,通过 HTTP 而不是文件位置来打开 Web 项目,这样就能找到 IIS 元信息。
问题 18:OnInit() 未删除
在 Visual Studio®.NET 2003 中,设计人员向代码隐藏类文件中添加了自动生成的成员函数 OnInit() 和 InitializeComponent()。Visual Studio 2005 不使用这些函数,但如果存在这些函数,则会调用它们。转换向导没有删除这些函数。
这一行为是构划好的,因为向导不知道这些函数内是否存在用户代码,因此代码隐藏文件中的代码原样保留。
如何修复
查看函数以确保没有要保存的用户代码,然后从代码隐藏文件中删除这些函数。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/oninit.gif)
问题 19:XHTML 验证错误
转换 Web 项目后或者打开转换的 Web 项目后,您将在生成 Web 项目后的错误窗口中看到 XHTML 验证错误。
这是 Visual Studio 2005 的一个功能,旨在帮助您编写与 XHTML 更兼容的代码。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/issue-validationS.gif)
如何修复
要修复此问题,应该更改代码以匹配您的目标 XHTML 标准级别。例如,严格的级别是“XHTML 1.1”。
如果想关闭这些错误的显示,可以将验证级别设置为不太严格的级别。默认情况下,转换一个 Web 项目后,验证级别设置为“Internet Explorer 6.0”,该级别接近 Visual Studio .Net 2003 使用的验证级别。
可以设置验证级别,方法是:单击 Tools,然后选择 Options,然后在 Text Editor/HTML/Validation 对话框上选择适当的级别。
![按此在新窗口打开图片](http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/xhtmlval.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 项目的真正配置支持。有关更多详细信息,请参阅 http://msdn.microsoft.com 中的“Visual Studio 2005 Web Deployment Projects”白皮书。
问题 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 名称,它被那些想要跟踪用户信息的开发人员广泛使用。因此,如果应用程序中有一个 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 窗体或用户控件迁移两次。有关更正该问题的方法,请参阅 Multiple Web Projects Referencing the Same Files。
如何修复
转换前,通过确保所有内容页中的 Codebehind 指令设置正确,可避免此问题。
转换后,将代码隐藏文件移到相关内容页所在的文件夹中,并更正页的 Codefile(在 ASP.NET 2.0 中进行了重命名)指令以指向该代码隐藏文件。
问题 25:多个项目引用一个 Web 项目
在 Visual Studio .Net 2003 中,一个项目引用一个 Web 项目的程序集是无效的。这在 Visual Studio 2005 中不起作用,因为 Web 项目创建多个程序集,并且程序集的文件名会因不同的生成而异。
如何修复
转换之前,您需要将常用的共享代码移到单独的类库中,并引用该库。
如果您要使用共享代码控件,则必须创建基类,这些基类存在于其他项目要引用的类库中,并让 Web 项目的用户控件从这些基类派生。
有关此设计模式的更多信息,请参阅 将 Web 项目转换到 Visual Studio 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 应用程序
如果要使用 express 产品(例如,Visual Web Developer 或 Visual Basic Express Edition),您将只能转换与该 express 产品相关的解决方案中的项目。例如,如果您正在使用 Visual Web Developer,并且打开了一个带有 Web 项目和 Visual Basic 类库项目的解决方案,则只会转换 Web 项目,这因此产生一个部分转换的解决方案。
如何修复
您应该使用 Visual Studio 2005 的 Standard、Professional 或 Team System 版本转换包含多个、混合项目类型的解决方案。
如果不可能这么做(您只有一个 Express 版本),您应该新建一个只包含支持的项目类型的解决方案。
问题 28:没有针对 C# 的命令行迁移
通过使用“devenv.exe /upgrade”命令(其中 是一个 Visual Basic Web 项目文件或包含这样文件的解决方案),Visual Basic Web 项目的命令行迁移是可能的。
遗憾的是,在产品周期的后期会发现 C# 错误:为 Web 项目转换向导提供了无效的 C# 代码模型。因此,在命令行 C# Web 项目转换期间,Web 应用程序中会引入错误。
因为与通过用户界面进行转换相比,命令行转换被看作辅助功能,因此对此错误进行 C# 修复会影响 Visual Studio 2005 的发布日期,因此最新发布版本中没有修复此错误。
如何修复
虽然没有修复,但替代方案是使用用户界面打开并转换 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 窗体和用户控件创建一个程序集。当您在 Visual Studio 2005 中使用 F5 生成时,它还会导致编译器进行全编译,而不是增量式编译。最终结果是,在部署时 Web 应用程序可能运行的较慢,您在 Visual Studio 2005 中的生成时间会显著增加。
• 程序集引用 — Batch 属性可能会隐藏可能的中断的程序集引用(如果 Batch=True),甚至会引入循环引用(如果 Batch=False)。
如何修复
在一个 Web 项目上运行了转换向导后,应该临时设置 Batch=False,同时完成手动步骤以转换 Web 项目。这样可以确保您发现所有程序集引用问题。
Web 项目完全转换后,您应该设置 Batch=True 以进行正常开发和部署。
注 部署 Web 应用程序时,您应该在 Batch=False 的情况下进行以下检查之一,以确保在开发 Web 应用程序过程中没有引入任何程序集引用问题。进行了该检查之后,一定要再次设置 Batch=True。
返回页首
小结
将应用程序从 Visual Studio .NET 2003 转换到 Visual Studio 2005 通常是一个顺畅的过程。然而,您必须确保正确配置了开发和部署环境。您还必须评估转换报告,以解决转换报告没有处理的任何潜在问题。您可能还希望提前查看应用程序并且提前规划,以避免转换中已知的问题。
将来的发行版本
由于 Web 项目迁移的重要性,因此我们始终期待反馈以便丰富这方面的经验。即使在 2005 年 11 月正式发布了 Visual Studio 2005 后,我们仍计划根据需要更新迁移向导。如果您有问题或反馈,请将它们发送到 http://forums.asp.net 上的“Visual Studio .NET 2003 to Visual Studio 2005 Migration”论坛上。
返回页首
附录 A:实际错误消息
实际错误消息 原因 可能的问题(一个或多个)
错误 1 — The name ‘Page1’ does not exist in the current context
生成错误
代码隐藏类文件 (CB-CB) 引用
独立类文件 (SA-CB) 引用
错误 1 - File 'Page1.aspx.cs' was not found
生成错误
多个项目引用相同的文件
警告: Code-behind file 'Page1.aspx.cs' is marked as code-behind for 'Page2.aspx' too. This may cause build errors
转换向导
共享相同的代码隐藏文件
警告: This Web project was converted as a file-based Web application. If your site contained any IIS meta-information, e.g. sub-folders marked as virtual directories, it is recommended that you close this Web site and re-open it using the Open Web Site command and selecting the Local IIS tab
转换向导
子 Web 应用程序
错误: The member declaration for 'Label1' was removed and its accessibility has been changed from 'public' to 'protected'. To access this member from another page you should create a public accessor property for it
转换向导
访问自动生成的控制变量
错误: The following files were not migrated because they were not found in the project file or the associated 'BuildAction' is set to 'None'. You may need to exclude these files from the project after the conversion process in order to compile your Web site: File List == Page1.aspx,
Page1.aspx.cs
转换向导
不再对已排除的文件进行排除
警告: Resource files were moved to 'App_GlobalResources' folder. Code using resources may have to be fixed manually
转换向导
资源管理器
错误 1: Could not load type 'myApp.Page1'
生成错误
Codebehind 指令正指向一个未转换的文件。请参阅已排除的文件不再被排除。
Error 1: 'myApp.Control1.Label1' is inaccessible due to its protection level
生成错误
无效的访问修饰符
Server Error in '/myApp' Application. Could not load file or assembly 'myApp' or one of its dependencies. The system cannot find the file specified
服务器错误
资源管理器
错误 1:Validation (XHTML 1.1): This name contains uppercase characters, which is not allowed
生成错误
XHTML 验证错误
错误 1: It is an error to use a section registered as allowDefinition = 'MachineToApplication' beyond application level
生成错误
备份文件夹位于 Web 项目文件夹中
子 Web 应用程序
Cannot switch to Design view because of errors in the page. Please corrrect all errors labeled 'Cannot switch:' in the Error List and try again
错误对话框
无法切换到设计视图
错误 1: File 'Page1.aspx.cs' was not found
生成错误
多个项目引用相同的文件
错误 1: Circular file references are not allowed
生成错误
循环引用