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

Linux.NET學習手記(5)

上一回閤中,我們牛刀小試的在Mono中部署了我們的第一個ASP.NET應用,此外我們還結合了PostgreSQL資料庫實現了一個簡單CRUD操作的小站點。它們的成功部署並正常執行很好的體現出.NET在Linux中運作的可行性。

同時,在上回合結尾部分中提到,這回合我們將一起討論學習企業級開源框架“Spring.NET”在Mono中的部署使用。但是,最近由於個人的一些私事,一直都沒有時間對Spring.NET作出系統的學習,在這裡,我向各位讀者表示歉意。因此,在本回閤中,我們學習討論的內容將發生一些變化,我們不再討論“Srping.NET”如何在Mono中部署,我們轉而討論學習跟WebForm處於平行位置的“ASP.NET MVC”如何部署到我們的Mono中,示例程式碼可以點選

這裡下載(由於程式碼過大,無法上傳到園子中,所以我放到了微盤,望各位讀者見諒)。

本回合,我們將討論學習:

1、部署前的準備工作

2、從零開始,把MVC3網站應用程式部署到Mono中

3、從部署MVC3中啟發,把MVC4部署到Mono中

4、另外一種與前面部署方式“相逆”的MVC4部署方式

1、系統約定——部署前的準備工作

最近一段時間,許多朋友都紛紛發帖發部落格表示已經成功的在Mono中成功的部署了最新版的MVC框架,相當的喜聞樂見。MVC是什麼,我想各位讀者一定知道,它作為微軟推出的重要建站模式,其地位與WebForm相當,重要性也是不容忽視的。試想一下,如果MVC無法在Mono中部署,那我們的Linux.NET彷彿就是一隻折翼了的小鳥——“想要飛也飛不高?“不對,直接是飛不起來了。因此,MVC能夠正常的在Mono中執行似乎已經就是Linux.NET的一項”理所當然“的事情。

好的進入我們的正題,在部署MVC之前,我們需要新建一個Jexus的網站配置:

我們先在Linux中新建一個存放檔案的資料夾,然後cd(進入)到Jexus存放網站配置檔案的目錄,再新建一個本次實驗的網站配置檔案”linux.net5“

新增上我們配置的內容

最後儲存退出,然後再重啟我們的Jeuxs即可。

在這裡,特別值得注意的地方:

那就是”NoFile“配置項,各位讀者一定要把此功能關閉(新增後註釋掉或直接就不新增進去,Jexus預設此功能是關閉的)。在MVC中我們的訪問路徑是經過路由重寫的,當我們發起一個訪問請求時,比如:localhost/Home/Index/,請求會經過路由的匹配並改寫,最終把請求指派到Controller資料夾中的HomeController.cs檔案中的Index方法,然後再由該方法對請求作出處理併發出應答。在整套的MVC”請求--應答“處理過程中,瀏覽器在位址列發起的URl請求在網站中未必都是真實的檔案實體地址訪問請求。而這恰恰相反的,在Jexus的NoFile檢測中,Jexus會對使用者發起的訪問請求(URL)進行檔案實體地址的檢測,檢測不通過時就直接對使用者應答一個預設的應答頁面(比如這裡的404頁面),不再使用.NET的功能對URl作更多的處理,因此,請求將永遠無法指派到正確的Action進行處理,整套的MVC網站也會因此而報廢。

同樣,對於一些在.NET中使用URlRewrite的站點,Jexus的”NoFile“功能也是需要關閉的,原因與MVC一樣,將會被URL重寫的請求還沒有通過Jexus這一關就被拒絕了,無法繼續的進入.NET進行處理,網站的訪問也會因此而造成一定程度的影響(這裡網站不會被報廢,因為在瀏覽器中輸入真實的實體地址,網站又可以正常的訪問)。

 2、部署MVC3網站應用程式

Mono中部署MVC3應用程式,這不是我們本回合的終極目標,但是確實本回合最重要的內容,因為只要學會了在Mono中部署MVC3,部署MVC4也就是那麼一回事了。其實,在Mono中成功部署MVC3也不是一件新鮮的事情,早前就已經有不少成功的案例,園子中也有一些關於如何在Mono中部署MVC3的文章,各位讀者如有興趣,可以自行查閱,當然,讀者們也可以從本文中直接找到方法,我們在這裡採用的是Step By Step的討論學習方法,一步一步的說明白如何操作,並指出當中需要注意的地方和解析原因。

好的,我們先新建一個MVC3應用程式”MVC31“,並選擇”空模板“和”Razor檢視引擎“

由於這個是一個空模板,裡面沒有任何現成的Controller,我們簡單的新建一個HomeController,並新增上一個Index Action和相關的檢視。然後在windows中執行:

那是沒有問題的,但如果我們釋出到Linux中,效果就不一樣了:

沒錯,正如所想的一樣,無法正常執行,按照上面的提示,我們設定”CustomError“節點,把它設定為”OFF“,重新發布,看看那裡出了問題:

第一個問題出現了,很明顯,是由於Entity Framework引起的。沒錯,如果有認真讀過我前一篇文章《Linux.NET學習手記(4)》 的讀者大概已經明白其中的原因和知道解決辦法了。正如我上回合為什麼沒有使用EF(我最喜歡的ORM)而改為使用PetaPoco的原因一樣,Mono中的EF版本已經是6.0並且還不支援低於此版本的EF框架,恰好微軟正式釋出的EF版本最高只有5.0,於是這就造成了我們這裡的第一個錯誤。不過這裡的問題也只是暫時性的,隨著微軟將來EF6.0的釋出,這個問題,將會得到解決。

我們通過NuGet解除安裝所有的Entity Framework。

然後再清除Web.Config和Global中的一些殘留項,然後再次釋出。

然後順利的進入到我們的第二個問題,這裡我解釋一下出現此問題的原因,由於mono 3.0.X對語言文化的支援暫時還沒有對中文支援(2.X中則可以支援中文),因此係統預設所使用的”zh-CN“讓Mono無法識別。此問題的解決辦法就是:在WebConfig的”system.web“節點中新增上”globalization“節點,並把當中的”uiCulture“設定成”en-US“。在這裡我們推薦的配置為”<globalization culture="zh-CN" uiCulture="en-US"/>“,這樣就可以讓我們的程式本身以”英語“語法來執行,但是顯示時卻能夠以”中文“語法來顯示。

我們新增上這個節點,並重新發布:


非常不幸的,我們繼續進入到了一個新的錯誤,到這裡,各位讀者有什麼感覺了?抓狂了?想想放棄了?俗話說:”行百里者半九十“,這時千萬別放棄,因為成功就在眼前了。通過從網上翻閱大量的資料,我們找到這這次問題的真凶,沒錯,作怪的就是”Microsoft.Web.Infrastructure.dll“,我們把Windows中”Microsoft.Web.Infrastructure.dll“和Mono中的”Microsoft.Web.Infrastructure.dll“反編譯:

可以看出,Windows中的Infrastructure和Mono中的Infrastructure還不是同一回事,那這就好辦了,我們把MVC3專案中的Infrastructure剔除,讓程式使用Mono自帶的動態庫,或許就可以解決我們現有的問題。我們刪除這個動態庫後,再次釋出:

終於看到了我們一直努力想要看到的”Index“,MVC3成功的在Mono中跑起來了。

 趁熱打鐵,我們再結合上PostgreSQL資料庫和PetaPoco快速的建立一個CRUD的小應用。

我們先新建一個商品表”Goods“,其表結構如下:

然後在新建相關的Controller、Model、View等,這裡就不再介紹當中的程式碼如何編寫和實現,有興趣的讀者可以在程式碼演示中檢視。

把做好的站點發布到Mono中:

頁面能夠正常顯示,沒有問題,我們在試試新增一個新的商品:

新增商品時報了一個錯,同時在“Details”中提示有一個程式集找不到。

通過排錯,我們發現了我們引用的一個DLL檔案在Mono中是沒有的:

這樣,我們只要在“C:/Windows/assembly”目錄中找到“System.ComponentModel.DataAnnotations.dll”(注意版本),然後再手動的新增到我們釋出的網站中的bin目錄中即可。

再次新增資料,OK!成功新增!

出現了“Linux.NET學習手記”這個商品。至此,MVC3的簡單部署已經完成~!!

這裡做一些小提示:

  (1)、由於我採用了的是虛擬機器,因此我結合了一個Linux的Samba服務來直接釋出,各位讀者也可以採用Ftp或者釋出到本地再上傳的方式進行網站的釋出,釋出後記得重啟一下Jexus。

  (2)、“Infrastructure”動態庫除了可以採用釋出會刪除的方式進行處理,也可以採用“不復制”的屬性才處理

 3、Mono中部署MVC4

上一小節中,我們歷盡艱辛“取得真經”,成功的把一個MVC3網站應用部署到了Mono中,在這取得重要的成功之後,我們向我們本回合的終極目標繼續推進——在Mono中部署一個MVC4應用。其實,無論是MVC3還是MVC4,它們的部署方法都是類似的,我們在上小節中詳講了MVC3的部署就是為了能夠在部署MVC4起到一定的參考作用。

 好的,心動不如行動,我們馬上的新建一個MVC4的網站應用:

然後再根據我們剛才部署MVC3的經驗步驟,進行相關的修改:

  (1)、剔除所有Entity Framework的應用(使用NuGet解除安裝EF,並清除所有關於EF的殘留)

  (2)、在Web.Conf配置檔案中的“system.web”節點中加入“<globalization culture="zh-CN" uiCulture="en-US"/>”

  (3)、移除“Infrastructure”這個動態庫檔案

把這個MVC4應用程式釋出到Mono中:

可以正常的執行,同樣的,我們在建立一個“商品”的增刪查改,並把缺少的“System.ComponentModel.DataAnnotations.dll”補上:

同樣的實現了我們想要的功能。

通過“照葫蘆畫瓢”的方法,我們把一個MVC4的網站應用程式順利的部署到Mono中了,其實也就差不多而已。

4、另一種版本的MVC4部署方法

從本回合開篇起,無論是部署MVC3還是部署MVC4,我們所採用的辦法都是直接使用Visual Studio所提供的MVC模板,然後通過“哪裡不行刪哪裡”的方法,把Mono中不支援或無法直接相容的地方進行刪除或修改。可以說,我們採用了一種“逆向”的方法來獲得一個Mono支援的MVC應用。說到這裡,各位讀者可能猜到,“既然有這種逆向的方法,應該也會有一種正向的辦法來部署”。近日我讀到了一篇題目名為《嘗試在 Mono 3.0 下執行 ASP.NET MVC 4》的文章,受到了一些啟發,發現還真的有讀者們所說的“正向”方法來獲得Mono支援MVC4應用程式。那就是不使用Visual Studio所提供的MVC模板,通過為Web應用程式新增必要的MVC庫檔案的方式手動的搭建起一個MVC應用程式。

在本小節中,我們將嘗試的通告手動的方法,獲得一個Mono支援的MVC4網站應用程式。在參照那篇文章的同時,結合我們“逆向”部署的方法與經驗,在Mono中部署我們想要的MVC4應用程式。

首先,我們新建一個空的Web應用程式(注意,不是MVC4應用程式):

然後通過NuGet管理工具,安裝上MVC4的庫檔案:

然後在手動的建立相應的資料夾和檔案:

這裡解析一下,有幾個檔案以及資料夾是必須建立的:

  (1)、Controller資料夾:用於存放控制器

  (2)、Views資料夾:用於存放模版

  (3)、Models資料夾:用於存放實體類檔案

  (4)、Global.asax檔案:用於應用程式啟動時初始化(註冊路由等)

在網站配置檔案中新增上MVC4需要用到的一些配置:

<configuration>

  <appSettings>
    <add key="webpages:Version" value="2.0.0.0"/>
    <add key="webpages:Enabled" value="false"/>
    <add key="PreserveLoginUrl" value="true"/>
    <add key="ClientValidationEnabled" value="true"/>
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
  </appSettings>
  
    <system.web>

      <globalization culture="zh-CN" uiCulture="en-US"/>
      
      <compilation debug="true" targetFramework="4.0" />
    </system.web>

</configuration>

剔除會在Mono中“作怪”的“Infrastructure”動態庫檔案,然後在全域性配置檔案的“Application_Start”方法中註冊上路由:

protected void Application_Start(object sender, EventArgs e)
{
   AreaRegistration.RegisterAllAreas();
   GlobalFilters.Filters.Add(new HandleErrorAttribute());
   RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

   RouteTable.Routes.MapRoute(
   name: "Default",
   url: "{controller}/{action}/{id}",
   defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
   );
}

 手動的在Controller和View中建立控制器和模板(這裡不詳講,只需注意要繼承相應MVC類),然後再發布到Mono中:

Controller找不到頁面了,我們打開發布後的目錄:

我們的Views資料夾不見了。其實,這是由於我們新建的是WebForm的應用程式,釋出時,我們的頁面會被嵌入到了bin目錄的程式集中,所以MVC的模版解析引擎無法在根目錄中找到VIews目錄以及裡面的所有模板。這個檔案的解決辦法也比較簡單,只需把Visual Studio中的Views資料夾整個的拷貝到網站根目錄中即可。

再次訪問:

OK~!!正常訪問!

這裡我有一點要宣告一下,Mono的HttpRuntime是支援targetFramework的,因此我們這裡並沒有把“targetFramework”去除(跟參考文章有所不同),各位要多加留意~!!

本回閤中,我們嘗試性的併成功把MVC3網站應用程式部署到Mono中,並根據MVC3的部署方式推演出了MVC4的部署方式,同時還介紹了相對於我們現有部署方式的Web應用程序升級為MVC4應用程式的方式部署。希望各位讀者在通讀全文之後能夠親自的動手實現一遍,“世上無難事,只怕有心人”,只要有恆心,所有的困難最終都不是困難。同時,如果各位讀者有一些更好的部署點子或對本文有任何的看法和建議,歡迎留言分享和指正。

好的,本回合暫時就到這裡了,這裡我就不作下回合的預告了,還沒有想到下回合具體會寫一些什麼。OK,咱們下回見。