1.1. 概述
在ASP.NET Core之前,ASP.NET Framework應用程序由IIS加載。Web應用程序的入口點由InetMgr.exe創建並調用託管。以初始化過程中觸發HttpApplication.Application_Start()事件。開發人員第一次執行代碼的機會是處理Application_StartGlobal.asax中的事件。在ASP.NET Core中,Global.asax文件不再可用,已被新的初始化過程替代。
ASP.NET Core 應用程序是在.NET Core 控制檯程序下調用特定的庫,這是ASP.NET Core應用程序開發的根本變化。所有的ASP.NET託管庫都是從Program
開始執行,而不是由IIS託管。也就是說.NET工具鏈可以同時用於.NET Core控制檯應用程序和ASP.NET Core應用程序。
using System;
using Microsoft.AspNetCore.Hosting;
namespace aspnetcoreapp
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel() //指定宿主程序爲Kestrel
.UseStartup<Startup>()// 調用Startup.cs類下的Configure 和 ConfigureServices
.Build();
host.Run();
}
}
}
以上是Program
類中Main
方法的示例代碼,Main
方法負責初始化Web主機,調用Startup和執行應用程序。主機將調用Startup
類下面的Configure
和ConfigureServices
方法。
1.2. 文件配置
1.2.1. Starup文件配置
對於一個ASP.NET Core 程序而言,Startup
類是必須的。ASP.NET Core在程序啓動時會從Program
類中開始執行,然後再找到UseStartup<Startup>
中找到配置的Startup
的類,如果不指定Startup
類會導致啓動失敗。
在Startup
中必須定義Configure
方法,而ConfigureServices
方法則是可選的,方法會在程序第一次啓動時被調用,類似傳統的ASP.NET MVC的路由和應用程序狀態均可在Startup
中配置,也可以在此初始化所需中間件。
Configure
在ASP.NET Core 應用程序中Configure
方法用於指定中間件以什麼樣的形式響應HTTP請求。
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
namespace aspnetcoreapp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles(); //允許應用程序提供靜態資源
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
}); //將MVC添加到管道並允許配置路由
}
}
}
ASP.NET Core是通過對IApplicationBuilder進行擴展來構建中間件的, 上面代碼中每個use擴展方法都是將中間件添加到請求管道。也可以給Configure
方法附加服務(如:IHostingEnvironment)這些服務在ConfigureServices
方法中被初始化。
用ASP.NET Core項目模板添加的應用程序,默認添加的幾個中間件:
-
UseStaticFiles 允許應用程序提供靜態資源。
-
UseMvc 將MVC添加到管道並允許配置路由。
ConfigureServices
ConfigureServices
方法是應用程序運行時將服務添加到容器中,用ASP.NET Core項目模板的時候默認會將MVC的服務添加到容器中:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
接下來舉一個例子,在實際應用中ConfigureServices
方法和Configure
方法配合使用,在ASP.NET Core中有一個UI開發框架 Telerik UI for ASP.NET Core,它有60多個UI組件,不僅支持ASP.NET Core的跨平臺佈署模式,而且還支持前端自適應渲染。
當在項目中應用 Telerik UI
的時候,首先在項目中引用相關的包,然後再在ConfigureServices
方法中將 Kendo UI
服務添加到容器中:
public void ConfigureServices(IServiceCollection services)
{
services.AddKendo();
}
接下來,在Configure
中設置Kendo UI
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseKendo(env);
}
1.2.2. appsetting.json配置
Configuration API 提供了一個基於鍵-值對來配置應用程序的方法,在運行時可以從多個來源來讀取配置。鍵-值對可以分組形成多層結構。鍵-值對可以配置在不同的地方,如:文件、內存等,其中放在內存中不能持久化,這裏筆者選擇將其配置在appsetting.json文件裏面。
配置appsetting文件
{
"key1": "字符串",
"key2": 2,
"key3":true,
"parentObj": {
"key1": "sub-key1"
},
"members": [
{
"name": "Lily",
"age": "18"
},
{
"name": "Lucy",
"age": "17"
}
]}
一個分層結構的 JSON 文件,鍵(如:key1)作爲索引器,值作爲參數,類型可以爲:字符串、數字、布爾、對象、數組。下面具體來看下在應用中怎樣使用。
在應用程序加載和應用配置文件
public static IConfigurationRoot Configuration { get; set; }
public static void Main(string[] args = null)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
Console.WriteLine($"key1 = {Configuration["key1"]}");
Console.WriteLine($"key2 = {Configuration["key2"]}");
Console.WriteLine($"subkey1 = {Configuration["parentObj:key1"]}");
Console.WriteLine();
Console.WriteLine("members:");
Console.Write($"{Configuration["members:0:name"]}, ");
Console.WriteLine($"age {Configuration["members:0:age"]}");
Console.Write($"{Configuration["members:1:name"]}, ");
Console.WriteLine($"age {Configuration["members:1:age"]}");
Console.WriteLine();
Console.WriteLine("Press a key...");
Console.ReadKey();
}
由於加載的是一個JSON文件,所以文件加載進來以後程序可以直接將它當作一個JSON對象來使用。如果有過動態語言使用經驗的同學來說這種方式就比較熟悉了。只在這裏訪問屬性的時候將平時常見的.
變成了:
,這和寫的JSON對象更接近。
1.3. 處理管道(中間件)
在ASP.NET Core應用程序中使用中間件,應用程序所做的任何事情(包括服務器中的靜態文件)都是由中間件來完成的。沒有任何中間件的應用程序在請求的出錯時候簡單返回404 Not Found
。中間件可以讓您完全控制請求的處理方式,並且讓您的應用程序更加精簡。
當接收到一個請求時,請求會交給中間件構成的中間件管道進行處理,管道就是由多箇中間件構成,請求從一箇中間件的一端進入,從中間件的另一端出來,每個中間件都可以對HttpContext
請求開始和結束進行處理。
在ASP.NET Core中可以用Run、Map和Use三種方式來配置HTTP管道。
Run 方法稱爲短路管道(因爲它不會調用 next 請求委託)。因此,Run方法一般在管道尾部被調用。Run 是一種慣例,有些中間件組件可能會暴露他們自己的 Run方法,而這些方法只能在管道末尾處運行。下面兩段代碼是等效的,因爲Use沒有調用next方法
Run方法示例代碼
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Run(async context =>
{
await context.Response.WriteAsync("environment " + env);
});
}
Use方法不執行next時示例代碼
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("environment " + env);
});
}
在.NET Core 中約定了 Map* 擴展被用於分支管道,當前的實現已支持基於請求路徑或使用謂詞來進入分支。Map
擴展方法用於匹配基於請求路徑的請求委託。Map
只接受路徑,並配置單獨的中間件管道的功能。
private static void HandleMapUrl(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Url Test Successful");
});
}
public void ConfigureMapping(IApplicationBuilder app, IHostingEnvironment env)
{
app.Map("/mapurl", HandleMapUrl);
}
上例中是一個用Map
方法來接受路徑進入分支管道,也就是說所有基於 /mapurl 路徑請求都會被管道中的 HandleMapUrl
方法所處理;如果想用謂詞來進入中間件分支,則要使用 MapThen
方法。MapThen
方法允許以一種非常靈活的方式構建中間管道。比如可以檢測查詢字符串是否具有 “branch” 來進入分支:
private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Branch used.");
});
}
public void Configure(IApplicationBuilder app)
{
app.MapWhen(context =>
{
return context.Request.Query.ContainsKey("branch");
}
, HandleBranch);
}
1.4 總結
- 這節講解了 ASP.NET Core 在運行時首先加載
Program
類下面的Main
方法,在Main
方法中指定託管服務器,並調用Startup
類中的Configure
和ConfigureServices
方法等完成初始化; - 在 ASP.NET Core 中 HTTP 請求是以中間件管道的形式進行處理,每個中間件都可以在 HTTP 請求開始和結束對它進行處理;
- ASP.NET Core 可以構建跨平臺應用,服務運行在 Http.Sys(僅適用於Windows平臺)和 Kestrel 上,不需要用IIS進行託管,所以相比傳統 ASP.NET 來說性能更高效也更加靈活。