从VS2003(.net1.1)升级到vs2005(.net2.0)全程跟踪记录_[Asp.Net教程]
[项目背景介绍]
本文要升级的项目是我公司目前的一个电子商务门户站点,系统极其复杂,2004年做成这个系统,几年来不断变迁,代码日积月累,产生了许多无用或重复性的代码,光UI版面就已经更新过不下5个版本。我从去年夏天来到这个公司,中间就经历过一次惨痛的界面升级,说是界面升级,其实.net版本却不升级,依旧是.net1.1,仅仅是UI层的全部重做,可想而知,在不动原有逻辑的前提下,这个界面升级过程有多么得艰辛,何况还是使用VS2003,所以代码中不知不觉地“滋生”了数不尽的“”这样的垃圾代码,追求完美的我,极其讨厌这类东西的存在。虽然最早从VS2003的Beta2开始用起,我曾经也用过1年的VS2005,如今又用回了VS2003,这种落差很是痛苦,我曾经和同事开玩笑说“再不升级的话,下次招聘的新人,都不会用vs2003和.net1.1写代码了”。
说完了项目大概介绍,再说说项目的业务情况,由于涉及到公司机密,不便太具体。我们的站点涉及人员有5个业务人员、1个flash设计人员、两个开发人员,以及一个共用的DBA,还有若干共用的美工设计人员和共用的测试人员,我就是两个开发人员之一。说起DBA,也很无奈,在我来到这边的将近一年时间里,来了2个DBA,走了两个DBA,现在存储过程的编写及数据表的建立都是我们开发人员自己来完成,唯一的DBA只负责数据库层面的发布。几个业务人员在一个经理的带领下,不断地“折磨”我们,由于平时活动很多以及经常和公司其他项目合作,必须不断地谈需求、沟通,所以平时用于开发的时间实际上不到整个活动周期的1/2。由于活动安排得很紧凑,软件开发流程中能省得步骤都省去了,设计、评审等都只在美好的幻想中存在过,大多是头脑风暴式的开发,专业一点的说法应该是敏捷编程或极限编程吧,当然我们这样的开发过程绝对不能和敏捷编程或极限编程相提并论,这里只是一个形象得比喻,对敏捷编程、极限编程,我只了解大概意思,最近刚下了《敏捷软件开发:原则、模式与实践》这本书的电子稿(17.9m),还没来得及看。需要的朋友可以给我留言。说着说着就跑题了,说这么多都是为了升级做铺垫,我实在忍不住了,特别是对项目的现状很烦恼。既然无法改变自己,那就改变自己主宰的事物吧。
升级开始!但升级也面临着很大的挑战,不光是升级要解决的数不尽未知问题,更是由于业务人员可不会给我空闲时间来做这事,上头都是由指标的,我也理解,我自己也是和他们绑定在一起,考核同一个指标。所以升级过程中,我必须不断把最新的更新内容加到新版本中,升级的时间跨度越长,不断更新的内容就越多,升级的风险就越大。
五一只有三天,还没休息够,这周又连着上6天班,一直把今天当作周末,一直盼望着晚上可以稍微晚点睡觉以及明天的美美一觉,可惜一切只是幻想,直接导致了下午不想做事。
[升级准备]
说实话,以及收藏过很多.net1.1升级到.net2.0的文章,都是2年前的事,当初也是想将来总用得到吧,没想到真被我遇上了。大概地看下别人的介绍,毕竟具体情况具体分析,并没有很大的参照性,倒是给我的心理无形中增加了很大压力。
言归正传,升级前,我做了如下准备:(假设原web Application是http://localhost/ProjectWeb。)
1、确保VS2005已经打上sp1补丁。
2、准备好纸和笔,随时记录升级过程中的问题和操作步骤。
3、拷贝一份最新的代码到另一个目录(假设为NewProject,其中web项目的文件夹为ProjectWeb),所有文件全部取消“只读”属性。
4、给新目录中的web项目(即:NewProject中的ProjectWeb文件夹)指定一个新的虚拟目录,比如为http://localhost/NewProjectWeb,修改web项目的webinfo文件中的URL地址为http://localhost/NewProjectWeb/,相应的web项目中的*.csproj和*.vspscc中的URL地址都改为http://localhost/NewProjectWeb。
5、用vs2003打开拷贝的那份代码(下文操作对象都是这份拷贝的代码),先断开源代码连接并移除源代码管理信息,然后再拷贝一份移除源代码管理信息的“干干净净”的代码,事后证明这个貌似多余的一个步骤绝对是没错的。
6、再用VS2005打开第5步之后的没有源代码管理信息的“干干净净”的项目解决方案,提示转化,确定,不用备份(因为已经有备份了),直到转化完毕,好,问题来了。
[问题列表及解决方法]
1、Math.Floor()函数出错;2.0中,该函数接收两种类型的参数decimal和double,与1.1中有差别,所以这个小问题在参数前直接加上Convert.ToDecimal()即可。
2、在1.1中,某个页面Test.aspx的codebehind文件Test.aspx.cs,类名Test,如果在某个地方实例化Test的对象:
Test test = new Test();//注意实例名test
当从1.1转化到2.0的时候,会自动把Test作为一个抽象类,放在App_Code中Migrated文件夹下,然后Test.aspx.cs中的类名改为Migrated_Test,同时继承自Test这个抽象类。可想而知,原先代码内部实例化Test的部分就会出错。另外,转化生成的抽象类Test中包含几个抽象方法和属性,这些属性和方法都没有实现,并且这些属性名和方法名在原先未升级的代码中,都是被前面提到的实例化对象test所调用。test没有调用的那些属性和方法、字段都不会跑到这个抽象类中。
[解决方法]1)这类情况的解决方法,我的这样做的:把转化成的抽象类Test改为非抽象类TestProxy,然后其中的属性、方法等,把原先的代码拷贝过来,形成完整的一个类。
2)再把Test.aspx.cs中的类名Migrated_Test改为Test。
3)最后把前面实例化Test部分的代码Test test = new Test(); 改为 TestProxy test = new TestProxy();
3、这个问题就很普遍了,就是在绑定下拉框等控件过程中会遇到的情况。如果省市联动,一般都会使用两个DropDownList控件,用js脚本实现联动。很不幸的是,当转化之后,当你点击按钮post当前页面,会提示“回发或回调函数无效……”等一大串错误。如果大家不明白这个问题的描述,可以把“回发或回调函数无效”这几个字作为关键字,搜索下博客园,出来的结果会告诉你详细的事实。
[解决方法]还是以省市联动这个例子,首先把选择“市”这个下拉框改回html控件,别忘了其中的runat=server,不然在codefile中就引用不到这个控件,也就取不到选择的值。然后再CodeFile中,取省市的值的时候,用Request.Form[city.Name]即可。
(补充一句:这里的city.ClientID和city.Name的值是一样的,如果是在用户控件(假设ID为userControl)中,那两者的值就不一样了,ClientID的值是“userControl_city”,而Name的值是“userControl:city”,此时使用city.Name才能取到值,总之,使用city.Name取值就可以了。)具体代码在公司,细节描述如果有差错,请见谅,明天我核对再发。
4、这个问题估计不是什么问题……如果页面声明部分加上了AutoEventWireup="false",在1.1中,CodeBehide中的Page_Load()是可以被执行的,但是在2.0种,很偶然地,我发现页面声明部分加上AutoEventWireup="false"的CodeFile中的 Page_Load()就不会被执行。但OnLoad()是可以执行的,难怪以前见到有人从来不用Page_Load()而使用OnLoad()。偶然还是?至少我发现的几个页面都是这样。在查看了AutoEventWireup的相关知识之后,我大概可以这么理解:
AutoEventWireUp介绍,参考:http://www.cnblogs.com/apiapia/archive/2007/02/25/655731.html
1、AutoEventWireup --- 指示是否自动启用页事件。
2、AutoEventWireup:指示该页的事件是否为自动连网的。如果启用事件自动连网,则为 true;否则,为 false。
3、AutoEventWireup="false" 表示是否自动地将页面的事件和相应的方法绑定到一起,一般这个什要设为false,因为若设为true有可能两次调用相同的事件代码。
4、AutoEventWireup属性决定事件句柄怎样连接到控件事件中。当AutoEventWireup设置为true时,ASP.NET决定调用类中的哪一种方法来响应那些在用户与网页的交互中产生的事件。ASP.NET将不必用代理就可以为一个Web控件调用合适的事件句柄,对程序员而言,这样可以无需为事件句柄添加代理。在程序员不是使用Visual Studio因而必须自己添加代码的情况下,这是非常方便的。
当Visual Studio生成一个ASPX文件时,因为Visual Studio为我们生成必要的时间代理,所以将AutoEventWireup设为false。
如果在Visual Studio中将AutoEventWireup设为true,那么一个事件句柄将会被调用两次,一次通过代理,一次是AutoEventWireup的结果。
5、AutoEventWireUp默认为True。
[升级过程中的建议和推荐做法]
这里随便说说,在升级过程中我是如何保持新旧版本的同步问题吧。我们有两个开发人员,在升级的这一段时间里,我专门来做升级的事,偶尔也开发些属于我之前开发过的模块,另一个人负责新活动的开发任务。这就存在一个版本的同步更新问题。我是这么做的:
1、通过VSS来监视哪些文件修改了,每天下班前2个小时专门来同步新旧版本。
2、如果是类库的代码有更新,则直接从VSS来获得最新版本。
3、如果是页面的更新,则通过VSS的Show Difference来手动一点点更新,这个过程比较痛苦。
4、有耐心做,要够细心,也要有信心做好。
来源:http://www.cnblogs.com/lxinxuan