Asp.net core 是一個開源和跨平台的框架,用於構建如WEB應用,物聯網(IoT)應用和移動后端應用等連接到互聯網的基於雲的現代應用程序。asp.net core 應用可運行.net和。netframework之上。
它由最小開銷的模塊化的組件構成,因此在構建解決方案的同時可以保持靈活性。Asp.net Core不再基於System.Web.dll。當前它基於一系列顆粒化的,並且有良好構建的NuGet包。
1.Asp.net Core應用
Asp.net Core應用實際上是一個在Main方法中創建一個Web服務器的簡單控制台應用程序。
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args) .Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
Main方法調用WebHost.CreateDefaultBuilder,后者按照生成器的模式來創建Web應用程序主機。生成器提供定義Web服務器(如UseKestrel)和啟動類的方法(UseStartup)。上面的代碼,自動分配了Kestrel Web服務器。Asp.Net Core的web服務器(如Http.sys),可通過調用相應的擴展方法使用。
IWebHostBuilde是WebHost.CreateDefaultBuilde調用的返回類型,它提供了許多可選方法,包括用於在Http.sys中托管應用的UseHttpSys,以及用於指定根內容目錄UseConyenRoot。Build和Run方法生成IWebHost對象,該對象托管應用並開始偵聽HTTP請求。
2.Startup
(1)Startup 類
如上面代碼,IWebHostBuilder的UseStartup方法為應用指定Startup類。
ASP.NET Core為應用程序提供了處理每個請求的完整控制。Startup類是應用程序的入口,這個類可以設置配置,可用來定義請求處理管道(該管道將用於處理應用程序的所以請求)和配置應用需要的服務(並且將應用程序將要使用的服務連接起來)。
Startup類必須是公開的,並且必須包含下面的方法:
public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IHostingEnvironment env,) { }
ConfigureServices方法用於定義應用所使用的服務(如MVC,EF,以及自定義的服務),Configure方法用於定義你的請求管道中的中間件。
所有的應用程序中都有Startup類,可能會存在特定環境的啟動類和方法,但無論如何,Startup類都將被充當為應用程序的啟動點。ASP.NET會在主程序集中搜索名為Startup的類(在任何命名空間下)。你也可以指定一個其他程序集用於檢索,只需使用
Hosting:Application配置鍵。
Startup類能夠選擇性地在構造函數中接受通過依賴注入提供的依賴項。一般而言,將要被配置的應用程序的方法應定義於Startup類的構造函數中,如Configuration。Startup類必須定義Configure方法,可選擇定義一個ConfigureServices方法,
這些方法在應用程序啟動時被調用。
(2)Configure 方法
Configure方法用於指定ASP.NET應用程序將如何響應每一個HTTP請求。簡單來說,你可以配置每個請求都接受相同的響應。但是,大多數應用程序都需要更多的功能。更復雜的管道配置可以封裝在中間件(middleware)中,並通過擴展方法添加到IApplicationBuilder上。
Configure方法必須接受一個IApplicationBuilder參數。一些額外服務,比如IHostingEnviroment或ILoggerFactory也可以被指定,在他們可用的情況下,這些服務將會被服務器注入。下面是默認的Web站點模板,多個擴展方法被用於配置管道,以支持BrowserLink,錯誤頁,靜態文件,MVC.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
每個Use擴展方法都會把一個中間件加入請求管道。例如,UseMvc擴展方法增加了路由中間件請求管道,並配置MVC為默認處理程序。
(3)ConfigureServices方法
像Configure一樣,可以在IServicesCollection上使用擴展方法來包裝需要大量配置細節的ConfigureServices。例如下面默認的Web模板代碼,使用幾個Add[Something]擴展方法用於應用程序,用來使用Session,MVC。
public void ConfigureServices(IServiceCollection services) { services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(10); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
通過依賴注入可將服務以及自定義服務加入服務容器,使其在應用程序中使用。就像Startup類能夠將指定依賴項作為其方法參數,而不是硬編碼來實例化,中間件,控制器類以及其他類都可以做到。
(4)一些服務
ASP.NET Core在應用程序啟動時提供了一些應用服務和對象。只要在Startup類的構造函數中包含適合的接口,或者在它的Configure方法,ConfigureServices方法中包含合適的接口即可。
IApplicationBuilder:
被用於構建應用程序的請求管道。只能在Startup中的Configure方法中使用。
IApplicationEnvironment:
提供了訪問應用程序屬性,類似於ApplicationName,ApplicationVersion以及ApplicationBasePath。可以在Startup的構造函數和Configure方法中使用。
ILoggerFactory:
提供了創建日志的機制。可以在Startup的構造函數或Configure方法中使用。
IServiceCollection:
當前容器中各服務的配置集合。只能在ConfigureServices方法中使用。只用在ConfigureServices方法中配置后,此服務在應用程序中才能使用。
3.服務
服務是應用中用於通用調用的組件。服務必須通過依賴注入(DI)獲取並使用。ASP.NET Core內置了一個簡單的控制反轉(IoC)容器,它默認支持構造函數注入,同時也可以替換成別的IoC容器。
4.中間件
在ASP.NET Core中,可以使用中間件構建自己的請求處理管道。ASP.NET Core中間件為一個HttpContext執行異步邏輯,然后按順序調用下一個中間件或直接終止請求。一般情況,要想使用一個中間件,只需在Configure方法里調用IApplicationBuilder
上一個對應的UseXYZ擴展方法即可。比如,內置的中間件:
靜態文件(Static files)
路由(Route)
身份驗證(Authentication)
當然也可以創建自定義的中間件,以及在ASP.NET Core中使用基於任何OWIN的中間件。
中間件是用於組成應用程序管道來處理請求和響應的組件。管道內的每一個組件都可以選擇是否將請求交給下一個組件,並在管道中調用下一個組件之前和之后執行一些操作。請求委托被用來建立請求管道,請求委托處理每一個HTTP請求。
請求委托通過使用IApplicationBuilder類型的Run,Map以及Use擴展方法來配置,並在Startup類中傳給Congigure方法。每個單獨的請求委托可以編寫為一個內嵌的方法,或定義在一個可重用的類中。這些可重用的類就叫作“中間件"或“中間組件“。每個位於請求管道內的中間件負責執行某些操作以及調用管道中下一個組件,或適時短路。
ASP.NET請求管道由一系列的請求委托構成:
每一個委托在下一個委托之前和之后都有機會執行操作,任何委托都能選擇停止傳遞到下一個委托,轉而自己處理該請求,這就是請求管道的短路,而且是一種有意義的設計,因為這樣可以避免不必要的工作。比如,一個授權中間件只有在通過身份驗證之后才能調用下一個委托,否則就短路。
異常處理委托需要在管道的早期被調用,這樣它們就能夠捕捉到發生在管道內所有的異常。
下面是Web項目默認模板代碼:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseAuthentication(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
上面的代碼在非開發環境下,UseExceptionHandler是第一個被加入到管道中的中間件,因此將會捕獲之后代碼中出現的任何異常,然后跳轉到設置的異常頁。
接着是靜態文件中間件,靜態文件中間件不提供授權檢查,由它提供的任何文件,包括那些位於wwwroot下的文件都是公開可被訪問的。
如果想基於授權來提供這些文件:
首先將文件放置到wwwroot外面以及任何靜態文件中間件都可以訪問到的目錄,在控制器中判斷授權是否允許訪問,如果允許則通過FileResult來提供文件。
然后被靜態文件中間件處理的請求會在管道中被短路。如果請求不是由靜態文件模塊處理,就會傳給洗一個中間件Identity模塊執行身份驗證。如果未通過身份驗證,則管道短路。否則,執行后面的MVC框架。
最簡單的ASP.NET應用程序可以使用單個請求委托來處理請求。在這種情況下,並不存在所謂的管道,調用單個匿名函數以應對每個HTTP請求。
app.Run(async context=> { await context.Response.WriteAsync("Hello World!"); });
短路示例:第一個Run委托短路管道,只有第一個委托會返回”Hello,World!“
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.Run(async context=> { await context.Response.WriteAsync("Hello,World!"); }); app.Run(async context => { await context.Response.WriteAsync("Hello,World,Again!"); }); }
多個請求委托鏈接示例:next參數表示管道內下一個請求委托。在管道中可以通過不調用next參數來短路。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.Use(async (context,next)=> { await context.Response.WriteAsync("Hello,World!\n"); await next.Invoke(); await context.Response.WriteAsync("Hello,World,End!\n"); }); app.Run(async context => { await context.Response.WriteAsync("Hello,World,Again!\n"); }); }
Run,Map與Use方法
可以使用Run,Map,和Use方法配置HTTP管道。Run方法會短路管道,因為它不會調用next請求委托。因此Run方法一般只在管道底部被調用。Run方法是一種慣例,有些中間件組件可能會暴露自己的Run[Middleware]方法,而這些方法只能在管道末尾運行。
Use方法前面已經介紹,Use方法中沒有使用next參數和Run方法是等價的:
app.Use(async (context,next)=> { await context.Response.WriteAsync("Hello,World!"); }); app.Run(async context => { await context.Response.WriteAsync("Hello,World!"); });
ASP.NET Core中約定Map*擴展方法被用於分支管道。當前的實現支持基於請求路徑或使用謂詞來進入分支。Map擴展方法用於匹配基於請求路徑的請求委托。Map只接受路徑,並配置單獨的中間件管道功能。
下面的例子,任何基於/maptest的請求都會被管道中所配置的HandleMapTest方法處理:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.Map("/maptest", HandleMapTest); } private static void HandleMapTest(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map test"); }); }
除了基於路徑的映射外,MapWhen方法還支持基於謂詞的中間件分支,允許構建單獨的管道。任何Func<HttpContext,bool>類型的謂語都可被用於將請求映射到新的管道分支。
示例:檢測查詢字符串中變量branch是否存在
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.MapWhen(context=> { return context.Request.Query.ContainsKey("branch"); }, HandleBranch); } private static void HandleBranch(IApplicationBuilder app) { app.Run(async context=> { await context.Response.WriteAsync("Branch used."); }); }
在Map方法中需要短路管道,因為會進入分支。
在map中還可以嵌套。
自定義中間件
中間件遵循顯示依賴原則,並在其構造函數中暴露所有依賴項。中間件能夠利用UseMiddleware<T>擴展方法的優勢,直接通過他們的構造函數注入服務。依賴注入服務是自動填充的,擴展所用到的params參數數組被用於非注入參數。
自定義日志中間件
5.服務器
ASP.NET Core托管模式並不直接監聽請求,而是依賴於一個HTTP Sever實現來轉發請求到應用程序。這個轉發的請求會以一組feature接口的形式被包裝,然后被應用程序組合到一個HttpContext中去。
ASP.NET Core包含一個托管的跨平台Web服務器:Kestrel,它往往會被運行在一個如IIS或者Nginx的生產Web服務器之后。
6.內容根目錄
內容根目錄是應用程序所用到的所有內容的根路徑,比如views和web內容。默認情況下,內容根目錄與宿主應用的可執行程序的應用根目錄相同;其他位置可以通過WebHostBuilder來設置。
7.網站根目錄
應用程序的Web根目錄是項目中類似於CSS,JS和圖片文件公開,靜態的資源的目錄。靜態文件中間件將默認只讀取Web根目錄和其子目錄中的文件。Web根目錄默認為<contentroot>/wwwwroot,但是可以通過WebHostBuilder來指定另一個地址。
8.靜態文件
靜態文件中間件
9.配置
ASP.NET Core使用一個新的配置模型,用來處理簡單的鍵值對。新的配置模型不是基於System.Configuration或者web.config;它是一個有序拉取數據的配置providers。內置的構造提供支持多種不同的文件格式,XML,JSON,INI和用於支持基於環境的
配置環境變量。同樣也可以編寫自定義的配置providers。
配置文件
9.環境
環境