MVC Source Code

今天有读者反映我的书【ASP.NET MVC 4 开发实战】讲到 如何对 ASP.NET MVC 原始码进行侦错 这一个技巧时,照著书操作没有成功,我自己重新试了一次,还真的没办法,这才发现事情没有想像中单纯,魔鬼总在细节裡,我今天又花了 6 个小时反覆研究、测试、分析,这才终于理清为什么以前可以,现在却无法对 ASP.NET MVC 4 原始码进行侦错的原因。因此我打算转载书中的内容,并加以更新、补充,好让大家能够完整且顺利的将 ASP.NET MVC 4 原始码加入到专案之中。

※本篇文章摘录自笔者出版的【ASP.NET MVC 4 开发实战】一书,并且更新部分内容!

开发 ASP.NET MVC 4 的过程中,难免会遇到一些疑难杂症,若能进一步瞭解 ASP.NET MVC 的内部运作逻辑,将有助于瞭解问题背后的运作细节,还好 ASP.NET MVC 是个开放原始码专案,任何人都可以到 CodePlex 网站下载到目前最新版的 ASP.NET MVC 原始码,最新版的 ASP.NET MVC 原始码可以在以下网址取得:http://aspnetwebstack.codeplex.com/

如果需要针对 ASP.NET MVC 4 原代码一并侦错,建议可以试试从 CodePlex 下载原代码,与现有的 ASP.NET MVC 4 专案放在一起,这样网站在执行时,就能同时查看 ASP.NET MVC 4 的原始码与执行单步侦错。



补充说明:笔者在学习 ASP.NET MVC 时,经常查阅 ASP.NET MVC 原始码,这有助于了解并理清各种 ASP.NET MVC 开发细节。

下载 ASP.NET MVC 4.0 原始码,并加入专案参考的流程如下:

Step01:前往 http://aspnetwebstack.codeplex.com/并点击 SOURCE CODE 页籤进入原始码页面。



Step02:先点选 Browsing changes in 下拉选单,并确认原始码分支 (Branches) 必须是 master 才行。

如下图示,请千万不要选择到非 master 的分支版本,这是我测试数小时得知的结论 Orz



事实上,如果你从 ASP.NET MVC 4.0 RTM 的下载页面中,也可以看到相对应的原始码连结(如下图示),这里所连结到的原始码将会是 v2-rtm 分支的原始码,

下载这一份将会遇到许多灵异现象,容后在述!

image

补充说明:预设你在 SOURCE CODE 页面所看到的 ASP.NET MVC 原始码是 master分支版本,代表的是持续开发中的原始码;但是另外还有两个分支分别是v2-rcv2-rtm 分支,分别代表著ASP.NET MVC 4 RCASP.NET MVC 4 RTM 的官方正式版本的原代码

在 master 分支版本裡,永远都是最新版的 ASP.NET MVC 版本,而目前最新版的 ASP.NET MVC 原始码已经是 ASP.NET 4.5 + ASP.NET MVC 5 (Preview) 的版本萝!(不要怀疑,目前 ASP.NET MVC 5 正在发展中,而且发展中的原始码大家一样可以下载预览)

这也代表著,在 master 分支版本裡的最新版原始码,已经与 ASP.NET MVC 4 RTM 版本相差胜远,经一番工夫的研究后发现,差异的地方真的非常多:

   1、 .NET Framework 版本,从当初的 4.0 已经升级到 4.5
   2、ASP.NET MVC 版本从 4.0 升级到 5.0
             ASP.NET MVC 的组件版本编号,从 4.1.0.0 升级到 5.0.0.0
             ASP.NET WebPages ( Razor ) 的组件版本编号,从 2.1.0.0 升级到 3.0.0.0
   3、Visual Studio 2012 版本推出了 Update 1 与 2012.2 更新 (源码有因为 2012.2 的出现做了些更新)

然而,如果直接照书中所写的直接下载原始码,加入专案到最后无法成功建置的最主要原因则是:

    .NET Framework 版本不相容!

因此,你只要下载到正确 .NET Framework 版本的原始码,就可以成功加入专案了!

要找到正确的原始码版本,你必须先点选 SOURCE CODE 页面下的 History 子页籤,并确保 Commits in 的下拉选单停留在 master 分支,如下图示:


然后卷到最下方,选择每页显示 100 笔资料,这样比较好搜寻

接著按下 Ctrl+F 搜寻页面资料,关键字请输入:2012.2-rtm

搜寻到之后 ( 如下图示,点图可放大显示 ),你会发现几个关键点,往上两个版本之后,这个分支就将 ASP.NET MVC 升级到 5.0 版了,也代表著 ASP.NET MVC 5.0 的开始。 ( 如果搜寻不到,请换到下一页继续搜寻 )

这时你搜寻到的原始码版本编号为 1b78397f32fc ( 你也可以直接点选这个链接进入下载页面 )

(2012.2-rtm 已更改为 v2.1,也就是MVC4.0的源码管理版本号,MVC5.0的源码管理版本号是3.0)



Step03:选对版本后,就可以点击右侧的 Download 链接,下载完整原始码。

备注:档名应该会是 aspnetwebstack-1b78397f32fc.zip



Step04:将下载后的 aspnetwebstack-1b78397f32fc.zip 档案解压缩到你现有的方案目录下



 

Step05:将你的现有方案执行 启用 NuGet 套件还原 功能。

完成后如下图示:



Step06:到 Visual Studio 2012 方案总管,将 ASP.NET MVC 4 相关的原始码专案加入方案中。

由于 ASP.NET MVC 4.0 原始码方案中的专案很多,如果你有用 Visual Studio 开启下载的 ASP.NET MVC 4.0 原始码方案档 (Runtime.sln) 的话,就可以看到,除了单元测是的专案之外,有高达 21 个专案之多,如下图示:

但是,我们如果只需让现有专案与 ASP.NET MVC 4 核心程式一起运作就够了,并不是所有专案都会用到,因此,你只要在现有方案中加入以下 5 个专案,就能够正确编译:

    System.Web.Mvc
    System.Web.Razor
    System.Web.WebPages
    System.Web.WebPages.Deployment
    System.Web.WebPages.Razor

完成后的图示如下:



Step07:接著修改原本 ASP.NET MVC 专案的组件参考,将准备加入的这几个组件参考移除。

再重新加入这几个专案参考。



Step08:由于透过 Visual Studio 2012 的 ASP.NET MVC 4 专案范本会加入的组建来自于 NuGet 下载的正式版本,而这些微软发佈的组件,都会有组件编号以及一个延迟签署的 Strong Name Key 所附带的公开金钥语彙基元 (PublicKeyToken),为了让这五个 ASP.NET MVC 4 的专案原始码能够与目前的专案顺利结合,又要避免这几个专案编译出来的组件与已经注册在 GAC 中的组件互相不衝突,我们必须对现有的 ASP.NET MVC 专案下的 Views\web.config 组态档稍作修改。

补充说明:公开金钥语彙基元 (PublicKeyToken) 是来自于应用程式签名的公开金钥,经过 SHA-1 杂凑运算的结果,并取得最后 8 个位元组所表示。

如果没修改 Views\web.config 组态档就直接执行网站,执行网站时就会看到如下图错误 (点图可放大):

[A]System.Web.WebPages.Razor.Configuration.HostSection 無法轉型為 [B]System.Web.WebPages.Razor.Configuration.HostSection. 型別 A 源自 'System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' (在內容 'Default' 中,位置為 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages.Razor\v4.0_2.0.0.0__31bf3856ad364e35\System.Web.WebPages.Razor.dll'). 型別 B 源自 'System.Web.WebPages.Razor, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' (在內容 'Default' 中,位置為 'G:\Temp\Temporary ASP.NET Files\root\23e4a2c6\cb39cbc1\assembly\dl3\ceda86bd\0077b1ae_9621ce01\System.Web.WebPages.Razor.dll').

文字错误讯息为:

[A]System.Web.WebPages.Razor.Configuration.HostSection 无法转型为 [B]System.Web.WebPages.Razor.Configuration.HostSection. 型别 A 源自 'System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' (在内容 'Default' 中,位置为 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Web.WebPages.Razor\v4.0_2.0.0.0__31bf3856ad364e35\System.Web.WebPages.Razor.dll'). 型别 B 源自 'System.Web.WebPages.Razor, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' (在内容 'Default' 中,位置为 'G:\Temp\Temporary ASP.NET Files\root\23e4a2c6\cb39cbc1\assembly\dl3\ceda86bd\0077b1ae_9621ce01\System.Web.WebPages.Razor.dll').

代表著两个相同完整名称的类别发生衝突,因为 .NET Framework 载入组件的顺序是固定的,一定会先载入 GAC 的组件,然后才会尝试载入 bin 目录下的组件。所以当载入了两个同名的组件后,就会遇到这种错误,解决方法就是修改 Views\web.config 组态档。

你只要将档案中的以下两段文字,利用「全部取代」的方式,将出现的字串全部清空,就可以修改完成:

, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35

, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35

请注意:我因为测试的时候,有试著下载 v2-rtm 分支的原始码回来编译,并加入方案中,结果却造成一系列灵异现象发生,这也是我今天花最多时间的地方,非常值得一提。

首先,我从 master 分支下载回来的 5 个专案,其设定的组件编号为:

    System.Web.Mvc 的组件版本编号为 4.1.0.0 ( 注册在 GAC 的组件版本为 4.0.0.0 )
    System.Web.Razor 的组件版本编号为 2.1.0.0 ( 注册在 GAC 的组件版本为 2.0.0.0 )
    System.Web.WebPages 的组件版本编号为 2.1.0.0 ( GAC 组件版本为 2.0.0.0 )
    System.Web.WebPages.Deployment 的组件版本编号为 2.1.0.0 ( GAC 组件版本为 2.0.0.0 )
    System.Web.WebPages.Razor 的组件版本编号为 2.1.0.0 ( GAC 组件版本为 2.0.0.0 )

再者,我从  v2-rtm 分支下载回来的 5 个专案,其设定的组件编号为:

    System.Web.Mvc 的组件版本编号为 4.0.0.0 ( 注册在 GAC 的组件版本为 4.0.0.0 )
    System.Web.Razor 的组件版本编号为 2.0.0.0 ( 注册在 GAC 的组件版本为 2.0.0.0 )
    System.Web.WebPages 的组件版本编号为 2.0.0.0 ( GAC 组件版本为 2.0.0.0 )
    System.Web.WebPages.Deployment 的组件版本编号为 2.0.0.0 ( GAC 组件版本为 2.0.0.0 )
    System.Web.WebPages.Razor 的组件版本编号为 2.0.0.0 ( GAC 组件版本为 2.0.0.0 )

各位看官看出端倪了吗?v2-rtm 分支的原始码,编译出来的版本号将会与注册在 GAC 的版本一致!

由于 .NET Framework 载入组件的顺序,一定会先载入 GAC 的组件,然后才会尝试载入 bin 目录下的组件,不过,当 .NET Runtime 发现在 bin 目录下的组件编号与 GAC 组件编号相同时,一律只会载入 GAC 组件!!!

这时有趣了!我还第一次遇到这种鬼打牆的事,我明明可以在 Visual Studio 2012 中顺利编译,按下 F12 执行「移至定义」( Go To Definition ) 也都运作正常,但网站执行起来后,一律只会载入 GAC 组件,不会载入 bin 目录下的组件。不过,当我试图删除 bin 目录下的 System.Web.Mvc.dll 组件后,竟然发生找不到组件的情况。我是不断思索其原因,还问到在微软美国总部担任研发的朋友,就是百思不得其解,直到我终于看出是「组件编号」的差异后,这才真相大白。解决方法有二:

    透过 gacutil 工具,将 System.Web.Mvc.dll 与其他组件从 GAC 中移除 ( 感觉这不是个好方法 )
    只要修改掉专案中使用的组件编号,或直接使用 master 分支下的原始码,也可以解决此问题。
    ( 因为 master 分支下的原始码组件编号已经故意调整成 4.1.0.0 与 2.1.0.0,以前都不知道为何会这样,到今天才恍然大悟!耗费精华 6 小时换来的~ T_T )

 

Step09:此时,体验与 ASP.NET MVC 4.0 原始码一起侦错的过程,在预设的 HomeController 的 Index 动作方法加上一个中断点,并按下【F5】功能键开始侦错。

这时我们开启「呼叫堆叠」窗格 ( Call Stack ) 就可以完整查询 ASP.NET MVC 4.0 的原始码了!

补充说明:由于 ASP.NET MVC 原始码採用M icrosoft Public License (MS-PL) 开放原始码授权,你甚至可以修改并重新散布修改过的 ASP.NET MVC 原始码。笔者的公司也曾经因为 ASP.NET MVC 4.0 有部分功能无法符合专案需求而自行调整过,不过,如果你也想自行修改 ASP.NET MVC 的原始码,必须要注意版本控管的问题。

 

最后,如果你还是想下载 v2-rtm 分支的原始码,又要能正常编译与执行的的话,如本文稍早所说,只要修改掉专案中使用的组件编号,就可以顺利编译,且正常的执行。

首先我开启另一个专案,下载 v2-rtm 分支的原始码,并加入专案、移除现有参考、重新加入专案参考后,开启 System.Web.Mvc 专案的 Properties\CommonAssemblyInfo.cs 档案。如下图示:

这个 Properties\CommonAssemblyInfo.cs 档案,是透过「连结档案」的方式加入到各专案之中,所以基本上这个档案会共用于所有 ASP.NET MVC 4 原始码专案裡,你只要改一次,就可以了。

你可以看到这个档案裡定义了各专案的 组件版本编号 (AssemblyVersion) 与 档案版本编号 (AssemblyFileVersion) 如下:

只要把组件编号改掉,所有灵异现象就会全数消失:

 

好久没这样斩妖除魔了,蛮过瘾的! (^_^)

也感谢读者的力量,你们真的很认真地看完我书中每一个片段,这是对作者最大的鼓励喔!

希望大家都能有所收货!


原文:http://blog.miniasp.com/post/2013/03/16/ASPNET-MVC-4-Source-Code-with-YOUR-projects.aspx



v3.0 beta1:aspnetwebstack.codeplex.com/SourceControl/changeset/3fd6562cad19160992429ce12f378cdfb03c16e2

v3.0-rcaspnetwebstack.codeplex.com/SourceControl/changeset/11495b6971ac4ba31e4d72c3d5efb9beda7235f2

在v3.0-rc之后,没有出现v3.0-rtm,而是 Update Versions from 5.0 & 3.0 to 5.1 & 3.1,所以这个之前的一条记录,就是MVC5.0 & v3.0 最后一个版本。

更新了MVC的版本号 : 5.2 ,也就对应着 v-3.2 的源码管理版本。

v3.2-preview : aspnetwebstack.codeplex.com/SourceControl/changeset/ced363bb59dc678c152e2fdf0700f0efdb7f4717

v3.2-rc : aspnetwebstack.codeplex.com/SourceControl/changeset/2c160ea866678f502b0afbe9696533a296f0546b


v3.2-rtmaspnetwebstack.codeplex.com/SourceControl/changeset/2b12791aee4ffc56c7928b623bb45ee425813021


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值