1. 程式人生 > >Linux.NET學習手記(6)

Linux.NET學習手記(6)

各位讀者大家好,好長一段時間沒有更新文章了,自從參加工作之後,每天等待去做的工作沒完沒了,個人的時間也變得奢侈起來,今後要儘量從中脫身,抽更多的時間來完成自己想做的事情(希望如此)。

言歸正傳,上一回合中,我們討論學習瞭如何在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>
Web.Config

最後,我們再建立一個簡單的控制器和頁面,然後把它跑起來。

在這裡,我有幾點本小節的小建議或解析:

  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又跑起來了。

寫在本回合最後,最大的感想就是,在漫步漫長的失敗的荊棘道路之後之後,成功的終點或許就在你面前的一步,只是因為霧太大了你沒有看清而已。做這個實驗時,前一個晚上折騰到三點半都沒有結果出來,當時就放棄了,不過第二天靈感一來了,又花了幾分鐘再次嘗試,最後產生了這一篇文章。

好的,不多說,期待下一次見面。