本文主要是以Visual Studio 2017 默認的 WebApi 模板做爲基架,基於Asp .Net Core 1.0,本文面向的是初學者,若是你有 ASP.NET Core 相關實踐經驗,歡迎在評論區補充。
與早期版本的 ASP.NET 對比,最顯著的變化之一就是配置應用程序的方式, Global.asax、FilterConfig.cs 和 RouteConfig.cs 通通消失了,取而代之的是 Program.cs 和 Startup.cs。Program.cs 做爲 Web 應用程序的默認入口,不作任何修改的狀況下,會調用同目錄下 Startup.cs 中的 ConfigureServices 方法 和 Configure 方法。html
對於初學者來講,第一次面對 Startup.cs 每每無從下手,本文將一步步介紹做者的經驗,可是不會涉入到內部的代碼實現以及相關的原理,那並非本文想要討論的範疇。編程
相信我,這將是你邁出構建靈活而強大的ASP.NET Core 應用程序的第一步。json
在官方文檔中提供多種方式來配置參數選項:windows
雖然提供了不少選擇,可是咱們只選擇其中的JSON文件和環境變量來提供配置參數。跨域
參考官方文檔的示例,咱們在 appsettings.json 加入以下的參數:安全
與此同時,咱們還須要一個類來映射這些配置參數:cookie
思考一下 subsection 應該是字典仍是一個對象?若是是字典,是否能夠爲<string,dynamic>或者<string,object>?app
好了,如今就差怎麼讓他們聯繫起來,只需在 ConfigureServices 方法中將他們配對:函數
services.Configure<MyOptions>(Configuration);
最後就是解決怎麼使用這些配置參數的問題了,舉個最簡單的例子,咱們能夠在某個控制器中把咱們的全部參數打印出來:性能
不知道你有沒有發現 MyOptions 類中有些屬性首字母大寫,有些屬性沒有,並非與json文件中徹底一致,也就是說能夠忽略大小寫的。
回到以前的匹配環節,咱們能夠發現 services.Configure 的方法中彷佛還有更多選擇,好比咱們把以前的那一行代碼替換爲:
services.Configure<MyOptions>(Configuration.GetSection("wizards"));//選擇wizards節點
咱們能夠發現返回的對象裏面的屬性都爲null,這是由於json中的 "wizards"的節點並不能與咱們的類匹配。
那麼問題來了,若是匹配的代碼以下,又會產生什麼樣的結果呢?先別急着回答,我會在下一節中給出答案。
環境變量,或者說系統變量,在windows中咱們能夠在系統屬性中配置:
在Linux環境中也有相應的配置,可是在開發過程當中,咱們能夠在 Visual Studio 中配置:
在這以前,咱們的Json文件中已經有 "option1" 和 "option2"的參數選項,那麼會產生什麼樣的結果呢?
顯然咱們能夠看到環境變量的參數覆蓋了Json文件的參數。而引發這種變化的緣由仍是須要回到Startup的初始化:
public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)//必須的json文件,而且自動重載 .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)//沒必要須的json文件 .AddEnvironmentVariables();//啓用環境變量 Configuration = builder.Build(); }
從中咱們能夠看出環境變量的配置在讀取 Json 文件參數以後,這樣就會覆蓋已經存在的同名參數,而已經從 Json 文件被匹配的參數並不會被清空(一樣適用於前一節提出的問題)。從另外一方面來講,若是你不須要環境變量,則須要去掉 "AddEnvironmentVariables() ",以避免覆蓋預期參數。
回到本節的中心,咱們爲何會須要環境變量呢?我我的會在Dockerfile中配置一些環境變量,好比某種服務的訪問地址、某中功能的開關等等。下面舉例說說兩個經常使用的環境變量:
ASPNETCORE_URLS 若是你沒有指定對應的 Url 監聽地址,能夠經過該參數修改,如設置爲 "http://*:80"。
ASPNETCORE_ENVIRONMENT 開發環境(Development)、預演環境(Staging)、生產環境(Production),將在工做環境一節中作詳細介紹。不一樣的工做環境將使得整個軟件流程變得清晰。
依賴注入在 ASP.NET Core 中無處不存在,在以前打印參數的例子中一樣用到。依賴注入好處都有啥?爲何咱們須要依賴注入?在 ASP .NET Core 中文文檔中依賴注入的章節 很好地解釋了:
你應該設計你的依賴注入服務來獲取它們的合做者。這意味着在你的服務中避免使用有狀態的靜態方法調用(代碼被稱爲 static cling)和直接實例化依賴的類型。當選擇實例化一個類型仍是經過依賴注入請求它時,它能夠幫助記住這句話, New is Glue。經過遵循 面向對象設計的 SOLID 原則,你的類將傾向於小、易於分解及易於測試。
爲了方便下一節測試,我準備三個文件,簡單的接口、該接口的實現類,擁有接口成員的類:
接下來,咱們使用 ASP.NET Core 自帶的 DI 來註冊服務:
能夠看到,註冊對象有不少種方法,而且咱們能夠管理對象的生命週期。註冊完對象,咱們就能夠在咱們須要的地方注入對應的對象了,仍是最簡單的例子——在控制器中使用:
對於控制器,咱們有三種方式注入對象:構造函數、控制器動做、屬性注入。然而,在通常的類中,使用自帶的 DI 只能是構造函數注入。究竟是哪一種方式好,見仁見智。
ASP.NET Core 服務能夠被配置爲如下生命週期:
咱們將經過逐步更改 IRepository 的生命週期來看看會發生什麼事情。
首先是瞬時:
接着是做用域:
最後是單例:
瞬時很好理解,相似每次都會new了一個對象。而對於做用域,若是一次請求中,有兩個甚至多個非單例對象引用到同一個做用域類型時,他們將會收穫同一個實例。單例也很好理解,從頭至尾都是同一個實例。
控制單一變量,若是隻是改變 ProductTotalizer 的生命週期而不是改變 IRepository 的生命週期的話,會發生什麼狀況呢?
在項目中咱們每每會添加許多擴展,好比用於API文檔說明的Swagger、計劃任務的Hangfire、壓縮響應的GZIP、跨域訪問、日誌擴展等等。他們的共同點就是須要先安裝相應的nuget包,而後在 ConfigureServices() 方法中配置服務,最後在 Configure() 方法中啓用。
咱們以Swagger爲例,首先是安裝對應的 nuget 包—— Swashbuckle。
接着是配置擴展:
最後就是啓用 Swagger 了:
咱們訪問 Swagger 的地址看看效果:
中間件是用於組成應用程序管道來處理請求和響應的組件。管道內的每個組件均可以選擇是否將請求交給下一個組件、並在管道中調用下一個組件以前和以後執行某些操做。請求委託被用來創建請求管道,請求委託處理每個 HTTP 請求。
舉一個簡單的例子(更復雜的能夠在中間件依賴注入對象),從 cookie 中獲取 token 並附加到請求頭中:
與啓用擴展同樣,咱們一樣是須要在 Configure()方法中啓用中間件:
app.UseMiddleware<JWTInHeaderMiddleware>();
若是咱們有多箇中間件呢,中間件的順序可能會影響到響應結果,但並非老是線性相關的。例如,咱們新增一個對響應狀態碼處理的中間件:
app.UseMiddleware<StatusCodeMiddleware>(); //.... app.UseMiddleware<JWTInHeaderMiddleware>();
雖然對狀態碼處理的中間件是最前面,但能夠在請求的最後關頭對請求結果進行處理。固然,若是中間有某個中間件短路了(沒有傳遞到下一個中間件),就會讓咱們前功盡棄。
與中間類似,過濾器一樣能夠對請求的先後執行特定代碼,可是過濾器能夠配置爲全局有效、僅對控制器有效或是僅對 Action 有效,比中間件更具備靈活性。
另外,過濾器從類型上還能分爲:受權過濾器、資源過濾器、Action過濾器、結果過濾器。很容易實現面向切面編程,下降了耦合。
這裏舉一個我最喜歡的過濾器——對請求的模型進行驗證:
固然,模型驗證的過濾器每每具備全局性,因此我通常是加在 services.AddMvc 中:
services.AddMvc(config=> { config.Filters.Add(new ValidateModel()); });
ASP.NET Core 提供了許多功能和約定來容許開發者更容易的控制在不一樣的環境中他們的應用程序的行爲。當發佈一個應用程序從開發到預演再到生產,爲環境設置適當的環境變量容許對應用程序的調試,測試或生產使用進行適當的優化。
在軟件開發的生命週期中,在不一樣的工做環境中每每是不一樣的狀態。好比說,在測試或者預演環境中,啓用Swagger擴展、控制檯打印日誌、容許跨域,而在生產環境中,每每處於安全、性能或者其餘考慮,這些功能是須要禁止的。對於 MVC 開發者來講,在開發過程當中會使用本地的JS、Css、圖片等文件,而在生產環境中這些文件每每是從CDN中獲取。
ASP.NET Core 提供了強大而靈活的配置機制,每一個點展開都像是一片新的天地。即便是經驗豐富的開發者,也不能自稱徹底掌握所有機制。隨着 .NET Core 的完善和發展,Startup.cs 也將愈來愈複雜。越是複雜,就越是要當心,如無須要,勿增實體!