各位讀者大家好,好長一段時間沒有更新文章了,自從參加工作之后,每天等待去做的工作沒完沒了,個人的時間也變得奢侈起來,今后要盡量從中脫身,抽更多的時間來完成自己想做的事情(希望如此)。
言歸正傳,上一回合中,我們討論學習了如何在Linux.NET中讓一個 MVC 3.0 和 MVC 4.0 的項目在mono中跑起來。而就在早前幾天,我在新浪微博中看到一位朋友轉發了一篇有關如何將MVC4.0項目升級到MVC5.0的文章:《How to Upgrade an ASP.NET MVC 4 and Web API Project to ASP.NET MVC 5 and Web API 2》。我不禁感嘆,這時代的步伐還真快,MVC還真的一年一版本的出,同時,一個想法在腦海中形成:既然MVC都發展到5.0了,那當前能否讓它在Mono中跑起來呢?
進入本回合主題,本回合中我們將討論學習:
1、得到一個ASP.NET MVC 5 的框架應用
2、將一個簡單的ASP.NET MVC 5 的應用部署到Linux中
本回合的程序源碼包,可以點擊“這里”進行下載。
1、得到一個ASP.NET MVC 5 的框架應用
巧婦難為無米之炊,想要部署一個MVC 5的應用,必須先得到一個基於這個版本的MVC應用。當前我使用的開發工具是Visual Studio 2012,而ASP.NET MVC 5.0 卻是跟 Visual Studio 2013 綁定一同發布,官方貌似還沒有提供獨立的模板安裝文件。當然,我們也不可能為了做這么一個ASP.NET MVC 5.0的實驗而跑去下載並安裝一個Visual Studio 2013,因此我們要通過一些其他辦法來獲得這么一個應用。
NuGet,果然是一枚好東西,我們很容易的就在上面的發現了ASP.NET MVC 5.0 的包,這樣,我們可以先使用Visual Studio建立一個MVC 4.0(或以下)的項目,然后在通過NuGet為該項目升級即可。
首先,我們先建一個ASP.NET MVC 4.0 的項目:

然后調出我們的控制台程序(具體可以在:“工具->庫程序包管理器->程序包管理器控制台”調出),輸入:“Update-Package”,讓它自動的把所有當前的版本庫升級。

第三步,我們需要對“~/View/Web.config”中的配置進行修改。
具體的修改內容,可以參照前言中說提及的那篇文章,“Update the web.config files under the Views folder”這一節中的1、2兩個步驟,在這里,我把我修改后的Web.Config配置全部貼出來讓各位讀者參考。
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" /> </sectionGroup> </configSections> <system.web.webPages.razor> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <pages pageBaseType="System.Web.Mvc.WebViewPage"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> </namespaces> </pages> </system.web.webPages.razor> <appSettings> <add key="webpages:Enabled" value="false" /> </appSettings> <system.web> <httpHandlers> <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/> </httpHandlers> <!-- 在視圖頁面中啟用請求驗證將導致驗證在 控制器已對輸入進行處理后發生。默認情況下, MVC 在控制器處理輸入前執行請求驗證。 若要更改此行為,請對控制器或操作 應用 ValidateInputAttribute。 --> <pages validateRequest="false" pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"> <controls> <add assembly="System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" /> </controls> </pages> </system.web> <system.webServer> <validation validateIntegratedModeConfiguration="false" /> <handlers> <remove name="BlockViewHandler"/> <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> </handlers> </system.webServer> </configuration>
最后,我們再建立一個簡單的控制器和頁面,然后把它跑起來。

在這里,我有幾點本小節的小建議或解析:
1、在建立初始項目的時候,建議選擇MVC項目,而非WebForm應用程序。為什么呢?這里並不是說通過WebForm+MVC庫的方式無法實現,而是如果各位讀者采用WebForm+MVC庫的方式實現的話,除了沒有辦法使用Visual Studio所提供的便利之外,建立的每一個View頁面,后方都有可能帶一個CS文件(如果你是通過建立aspx頁面然后改后綴名之類的),並且編譯發布之后的代碼,View中的內容也有可能被編進了dll中。總而言之,這都將造成極大的不便。
2、由於ASP.NET MVC 5僅支持.NET FrameWork 4.5以上的版本,因此新建項目是,FrameWork 4.0 或 以下的版本是無法升級到MVC 5 的。
3、使用NuGet升級,因為本次"Update-Package"沒有帶上任何的參數,因此系統會默認的幫你升級到最新的版本,換句話說,如果下次是MVC 6 的話,NuGet則會幫你升到最新版本(當然,是否成功則是另外一個問題啦)。各位讀者也可以通過在項目資源管理器中“右鍵本項目->管理NuGet程序包”來對這些庫進行相關操作。
2、將一個簡單的ASP.NET MVC 5 的應用部署到Linux中
好的,接下來,我們要將這個簡單的小項目部署進Linux當中,由於使用的是.NET FrameWork 4.5,我手頭上的mono版本擔心會有所不足(原先版本為:mono 3.0.12)因此我把Linux中的Mono重新安裝了一遍(說起慚愧,由於“rm -rf /usr/local/mono/” 時忘了關Jexus,重新編譯的時候還Error了一次),現在的版本為:mono 3.2.3。

把環境搭建好之后,再把這個小項目發布到Linux中(jexus網站配置和網站發布過程這里不再寫了,又需要的讀者可以翻閱前面的文章),然后嘗試訪問。

嗯嗯,就知道不會有這么順利的,我們把“CustomError”設為“Off”看看它報了些什么錯。

第一個錯誤報出來了,說是無法加載“System.Web.Http.WebHost”程序集中的一個方法。
我們先檢查是否是因為缺少程序集造成的。

檢查發現,這個程序集已經自帶在bin文件夾中,初步排除是缺少程序集造成的,並且改程序集的版本也是5.0.0.0,也排除版本問題造成的。
再觀察它是否和mono不兼容(如該版本庫使用了和操作系統緊密關聯的東西之類的),在觀察之前這里有個小技巧,那就是先看看mono中有沒有這個程序集,如果有,則把mono里面的庫直接替換它,如果沒有再慢慢觀察。

很幸運的,找到了這一個對應的程序集,我們把它抽取出來,直接替換掉bin里面的這個程序集。
然后再刷新頁面:

好的,第二個問題報出來了,這次是程序集中缺少方法了。
通過命名空間來查找,我們尋尋覓覓的找到了bin文件夾中“System.Web.Http.dll”中的class HttpConfiguration:

雖然Methods沒有明確的寫有“get_Service”這個方法,不過留意紅色框框那里,那里使用了語法糖,程序集編譯后會自動的產生這個方法,因此此dll中是有這個方法存在的。
與此同時,我們發現了mono中也存在這個程序集:

我們再撬開mono中的這個程序集:

可以發現,這兩個屬性,雖然名稱相同,但是卻是分別兩個不同的類型,細心的讀者還能夠發現,就連這個類本身都是有不少東西是不同的。
這樣的話,我們就把mono的這個程序集拿來替換掉bin下的這個程序集。
再次刷新我們的頁面:

嘿嘿,出現了。結果證明,ASP.NET MVC 5又跑起來了。
寫在本回合最后,最大的感想就是,在漫步漫長的失敗的荊棘道路之后之后,成功的終點或許就在你面前的一步,只是因為霧太大了你沒有看清而已。做這個實驗時,前一個晚上折騰到三點半都沒有結果出來,當時就放棄了,不過第二天靈感一來了,又花了幾分鍾再次嘗試,最后產生了這一篇文章。
好的,不多說,期待下一次見面。
