VS2013中的MVC5模板部署到mono上的艱辛歷程


部署環境:CentOS7 + Mono 3.10 + Jexus 5.6

在Xamarin.Studio創建的asp.net項目,部署過程非常順利,沒有遇到什么問題;但在VS2013中創建的asp.net項目,部署過程會有一些波折。現在想想,原因是Xamarin.Studio中的項目模板比較簡單,只是顯示幾個文字,並沒有用到mvc5中的東西。

vs2013新建一個asp.net的項目(目標框架是.net4.5),選擇mvc,並且更改身份驗證為不適用身份驗證。

編譯,並發布到jexus默認站點指向的目錄,訪問之。報出的錯誤信息如下圖。

根據異常堆棧信息,應該是調用HtmlHelper的ActionLink方法的時候,Helper友用到了RouteCollectionExtention的獲取虛擬路徑方法,問題就處在這個方法中。

看提示應該是RouteCollection少了AppendTrailingSlash這個屬性(bool,用來控制在轉換成虛擬路徑的時候是否在最后添加“/”)。

其實,Asp.net 路由框架的代碼位於System.web.dll中,System.Web.Routing.dll是個沒有代碼的空程序集。RouteCollectionExtention是mvc中為了方便使用而對路由框架中RouteCollection的一系列的擴展方法。

打開mvc的RouteCollectionExtention源碼(http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RouteCollectionExtensions.cs),發現了對RouteCollection的AppendTrailingSlash調用。

對比下.net和mono中的RouteCollection類,發現mono中沒有實現AppendTrailingSlash這個屬性,同樣也沒有LowercaseUrls這個屬性(代碼地址分別是,.net:http://referencesource.microsoft.com/#System.Web/xsp/system/Web/Routing/RouteCollection.cs#8f054052ef9931ac#references,mono:https://github.com/mono/mono/blob/master/mcs/class/System.Web.Routing/System.Web.Routing/RouteCollection.cs)。

再看一下mono中RouteCollection這個文件的最后更新時間,++,兩年前,好吧。

因為屬性無法像擴展方法一樣擴展,而且路由中又沒有針對RouteCollection進行抽象,都是直接引用的RouteCollection,這個問題我暫時沒招了。翻遍了google,只有問題,沒有答案。

只能先繞過去了,找到View/Share/_Layout.cshtml,注釋掉調用Html.ActionLink的代碼,重新發布。

這時候可以正常訪問,但頁面的樣式是亂的,在瀏覽器的開發人員工具中可以看到如下404信息,原因肯定是bundle框架並沒有起作用。

解決辦法是,找到bin文件夾刪除Microsoft.Web.Infrastructure.dll,因為mono在lib中有關於這個程序集的自己的實現,為了開發和部署方便,也可以直接把Microsoft.Web.Infrastructure.dll設置為不復制到本地。

再次訪問,可以看到清新的Bootstrap界面了,只是菜單上哪幾個倒霉的鏈接被注釋掉了。

以上可知,mono目前對mvc5的兼容性還不夠好,可能在等vNext不屑於兼容mvc5了吧。

MVC5在mono上顯示幾個文字還是沒有問題的,但HtmlHelper某些方法因為間接調用了mono沒有實現的路由框架的屬性,所以無法使用。

RouteCollectionExtention中獲取虛擬路徑的方法是非常重要而且使用頻繁的,為了這個,只能棄用mvc5了,將其降級為mvc4了。

降級的過程是一部血淚史,有血,有淚,有屎。mvc相關的nuget包主要有:Microsoft Asp.Net MVC、Microsoft Asp.net Web Pages 、Microsoft Asp.net Razor,比較坑爹的是這三個包的不同版本之間不一定兼容。本來想是直接在NuGet中引入MVC4就好,但是遇到了各種問題,不是這個包少個方法就是那個包少個方法,最終試了很多種組合也沒有成功。

最后不得已才用了一個投機取巧的方法,先創建一個mvc4的項目(在vs2013中的創建項目框中展開web選中vs2012就可以看到mvc4的模板),然后把vs自動創建的mvc4、webPage、razor包,復制到原解決方案的package目錄下。

在NuGet中依次卸載MVC5、WebPages、Razor,然后添加對上面復制過來的三個包中的程序集的引用,這時在vs2013中編譯運行會遇到下面的異常:

打開View文件夾下的Web.config,configSections中依然保留着對最初的那幾個程序集的引用,把mvc4項目中的這段配置復制過來,編譯運行,又看到下面的異常:

找不到System.Web.Helpers命名空間,可以我明明引用了System.Web.Helpers這個程序集啊,但bin中竟然沒有System.Web.Helpers.dll。仔細查看,原來是沒有設置為復制到本地,相應的檢查一下上面手動添加的幾個引用是否都設置了復制到本地,再次編譯運行,在windows下已經可以正常瀏覽了。

把上面layout.cshtml中被注釋掉的調用Html.ActionLink的代碼解開注釋。

編譯運行,OK;部署到CentOS上,在bin文件夾中刪除Microsoft.Web.Infrastructure.dll,重啟jexus,瀏覽之,正常顯示,點擊菜單上通過HtmlHelper生成的幾個連接,Perfect!!! 倒霉的菜單又回來了!!!


 

最終的代碼在這里


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM