針對 IIS 部署 ASP.NET 5 應用程序的問題,在上面博文中主要採用兩種方式嘗試:css
VS2015 的 Publish 方式(成功)。web
手動複製文件的方式(失敗)。json
初步理解 ASP.NET 5 的編譯及部署問題。bootstrap
解決 ASP.NET 5 預編譯,併成功部署到 IIS 上。瀏覽器
首先,如今的 IIS 對於 ASP.NET 5 來講,其實已經沒有太大的關係了,用不用它都無所謂,ASP.NET 5 應用程序能夠採用 Self-Hosting(自寄宿)的方式,也就是本身看成 Web 服務器,實現方式只要在 project.json 中添加 Microsoft.AspNet.Hosting 程序包就能夠了,咱們知道,Web 服務器的做用其實就是監聽請求,並分發請求給相應模塊進行處理,最後再輸出處理結果,若是咱們把這個請求處理過程進行分化,交給不一樣的組件或模塊進行處理,咱們就能夠脫離集成化的 IIS,在 Owin 體系結構中,ASP.NET 5 應用程序部署到 IIS 上,這個 IIS 的做用就只是一個 Host(管理應用程序的線程,打開、關閉或加載組件),Server(如 Microsoft.AspNet.Server.WebListener)和 Middleware(如 Microsoft.AspNet.StaticFiles)都有相應的處理組件,不須要用到 IIS 的那一套東西,好比以前咱們須要在 IIS 中進行 HttpModule 配置等。服務器
既然咱們不使用 IIS 的那一套東西,若是將 ASP.NET 5 應用程序部署到 IIS 上,那就必須有個東西將 IIS 和 ASP.NET 5 獨立運行時(KRE)之間的通道(Pipeline)打通,這個東西就是 AspNet.Loader.dll(位置:application/wwwroot/bin),使用它的條件是在 project.json 中添加 Microsoft.AspNet.Server.IIS 程序包,並且只在 IIS 中才會出現,若是採用的是 Self-Hosting 方式,這個程序集將會「消失」,關於 AspNet.Loader.dll,一篇很是好的解答文章:AspNet.Loader.dll – what is this for?app
另外,在 IIS 中部署 ASP.NET 5 應用程序,不像咱們以前的方式,直接把相應的文件和程序集拷貝到站點目錄下,由於你會發現,在生成 ASP.NET 5 項目的時候沒有生成對應的程序集,只是在 Bin 目錄下有一個 AspNet.Loader.dll,dudu 已經試過在 ASP.NET 5 項目屬性頁的 Build 選項中,把「Produce outputs on build」選項打勾,就會生成相應的程序集文件(位置:../application/artifacts/bin),既然有了程序集,那是否是就能夠像以前部署站點的方式進行操做呢?答案固然不是,這也就是爲何手動複製文件會失敗,由於 ASP.NET 5 並沒想象中的那麼簡單,呵呵,採用 VS2015 的 Publish 方式部署是成功的,那咱們就從它下手,觀察下它究竟是怎麼回事,dudu 沒作完這步,咱們下面接着作。asp.net
用 VS2015 建立一個簡單的 ASP.NET 5 項目:ide
project.json 配置:組件化
{ "webroot": "wwwroot", "version": "1.0.0-*", "exclude": [ "wwwroot" ], "dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta1", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1", "HelloClassLibrary": "1.0.0-*" }, "commands": { /* Change the port number when you are self hosting this application */ "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000" }, "frameworks": { "aspnet50": { }, "aspnetcore50": { } } }
Startup.cs 代碼:
using Microsoft.AspNet.Builder; using Microsoft.AspNet.Http; namespace HelloAspNet5 { public class Startup { public void Configure(IApplicationBuilder app) { app.Run(context => context.Response.WriteAsync("Hello, ASP.NET 5 world! \{HelloClassLibrary.TestClass.testContent}")); } } }
爲了演示 ASP.NET 5 與依賴類庫之間的關係,咱們還建立了一個 HelloClassLibrary 項目,並在 Startup 中進行調用。在 project.json 中配置 commands 是爲了方便咱們經過 Publish 發佈出來的程序檢測是否能夠正常運行。
Publish 發佈文件結構:
approot 爲程序文件及程序包目錄,packages 下面是整個應用程序運行所須要的程序包,src 爲程序源代碼目錄,wwwroot 爲站點目錄(咱們等下 IIS 部署的時候,就是指向的這個目錄),裏面有一個 bin 目錄(只有一個 AspNet.Loader.dll)和一個 web.config 文件(裏面主要配置一些地址路徑,好比程序包的地址路徑)。web.cmd 是批處理文件,它其實就是咱們在 commands 中制定的命令(還能夠配置 EF 遷移的命令)。
上面是本地運行結果(注意,我並無安裝 IIS),你也能夠直接點擊 web.cmd 來啓動站點。
既然本機運行沒問題,那咱們就把它發佈到 IIS 上試試,可是卻報下面的錯誤:
錯誤信息:Couldn't find package 'KRE-CLR-amd64.1.0.0-beta1'. Locations probed,什麼意思?本機是 32 位系統,服務器是 64 位系統,發佈設置咱們選的是「KRE-CLR-x86.1.0.0-beta1」,不報錯纔怪,從新更改發佈設置爲「KRE-CLR-amd64.1.0.0-beta1」:
而後把發佈生成 HelloAspNet5.Web\approot\packages\KRE-CLR-amd64.1.0.0-beta1 下的文件,添加到服務器相應目錄下,從新刷新瀏覽器,運行成功:
Hello, ASP.NET 5 world! HeiHei
上面這些操做其實 dudu 已經完成了,而且也是成功的,但這並非咱們想要的,由於這時候,服務器運行的程序是「動態編譯」的,程序代碼地址就在 HelloAspNet5.Web\approot\src 目錄下,裏面直接是源代碼,並非生成的程序集文件,那該如何「預編譯」咱們的 ASP.NET 5 應用程序呢?
首先,咱們須要生成咱們的應用程序,就像咱們以前的 ASP.NET 應用程序同樣,而 ASP.NET 5 默認是「動態編譯」的,若是想設置成預編譯,須要咱們手動設置一下:
在項目屬性頁的 Build 選擇中,把「Produce outputs on build」打勾就能夠了,HelloClassLibrary 類庫項目一樣這樣設置,設置好了,從新生成項目,生成的程序集目錄爲:\HelloAspNet5\artifacts\bin\HelloAspNet5\Debug,在相應目錄下,就會看到咱們想要的兩個程序集文件:HelloAspNet5.dll 和 HelloClassLibrary.dll,既然項目程序集生成成功,那部署應該沒有什麼問題,但 dudu 已經嘗試過,是失敗的,問題出在哪?直接把相應的程序集文件拷貝過去不行嗎?固然不行,由於咱們使用 VS2015 Publish 的時候,運行環境是「動態編譯」,那怎麼使 Pulish 的時候預編譯呢?答案就在下面:
在 Publish 的時候,還有一個發佈選項「Precompile during publishing」,就是配置預編譯的,從新發布一下,你會發如今 packages 目錄下多了兩個文件夾:
這就是預編譯生成的項目文件地址,咱們再來看下 HelloAspNet5 的文件目錄:
一個是 lib 目錄,裏面就是生成的程序集文件,root 是程序的其餘類型文件,好比 MVC Views 文件就在這裏,而不是在 wwwroot 目錄下。另一個很是重要的地方就是,wwwroot 下的 web.config 變成了:
<?xml version="1.0" encoding="utf-8"?> <configuration> <appSettings> <add key="kpm-package-path" value="..\approot\packages" /> <add key="bootstrapper-version" value="1.0.0-beta1" /> <add key="kre-package-path" value="..\approot\packages" /> <add key="kre-version" value="1.0.0-beta1" /> <add key="kre-clr" value="CLR" /> <add key="kre-app-base" /> </appSettings> </configuration>
好像也沒怎麼變化?跟以前的自習對比一下,會發現 key(kre-app-base)的 value 值不見了,以前的配置爲
<add key="kre-app-base" value="..\approot\src\HelloAspNet5" />
看到這你應該懂了,沒錯,你能夠把 approot\src 目錄下的 HelloAspNet5 源代碼文件刪掉了,使用 k web 命令從新啓用項目,運行成功:
Hello, ASP.NET 5 world! HeiHei
接着咱們從新在服務器的 IIS 上也這樣搞,可是卻出現了下面的錯誤:
錯誤信息:Couldn't find package 'KRE-CLR-amd64.1.0.0-beta1',找不到「KRE-CLR-amd64.1.0.0-beta1」程序包,在 approot\packages 目錄下明明就有啊,查看下面的提示發現 IIS 並無從這個目錄下進行查找,怎麼辦?手動配置一下:
<add key="kre-app-base" value="..\approot\packages\HelloAspNet5\1.0.0\root"/>
須要注意的是,要配置到 root 目錄下,從新啓動項目,運行成功:
Hello, ASP.NET 5 world! HeiHei
咱們接下來修改代碼,而後經過編譯程序集上傳到 IIS 服務器。
app.Run(context => context.Response.WriteAsync("Hello, ASP.NET 5 world!!! \{HelloClassLibrary.TestClass.testContent}")); public static string testContent = " HeiHeiHei";
能夠看出,上面代碼和以前的代碼是有些不一樣的,以前有說過使用 VS2015 編譯的程序集地址爲 artifacts,咱們把相應的程序集文件上傳到服務器的 approot\packages 目錄下,奇怪的事,我運行後發現改的代碼並無效果,仍是以前的,這個問題搞了我好久,都快被搞死了,我覺得是生成的程序集文件有問題,沒有生成最新的,就各類設置生成測試,最後仍是沒有成功,而後無心間把 IIS 站點停掉,而後再進行上傳程序集文件,最後再啓動站點,刷新瀏覽器,你猜怎麼着?Oh, My God !!!,竟然出現了:
Hello, ASP.NET 5 world!!! HeiHeiHei
從上面整個配置過程當中能夠看出,ASP.NET 5 是如何在 IIS 進行運行的(只是從 Publish 上來看),首先,站點目錄爲 wwwroot,包含一個 bin 目錄的 AspNet.Loader.dll 文件(用來打通 IIS 和 Owin 組件之間的管道),還有一個 web.config 文件(主要配置程序包及應用程序路徑地址),除此以外,還有一些靜態文件(如 css、js 和圖片文件),若是是動態編譯站點,默認直接運行 approot\src 目錄下的源代碼文件,若是是預編譯站點,根據 kre-app-base 的路徑配置(如 approot\packages\HelloAspNet5\1.0.0\root),運行 ASP.NET 5 運行程序,注意在 root\project.json 文件中,有以下配置:"webroot": "..\..\..\..\..\wwwroot",這個指向的地址就是 IIS 站點。。。
其實,上面雖然只是一個簡單的 IIS 部署過程,但涉及到很是多的東西,也有不少的感觸,或許有些沒表達出來,總的來講,此次部署給我最重要的感覺是:ASP.NET 5 徹底的組件化,不僅是開發,部署也是如此,這樣的結果就是充滿着無限可能,看我七十二變!!!