引言 "原文地址" 在這篇博客中我將探索一些關於Asp.net core 3.0應用的基礎功能——.csproj 項目文件和Program源文件。我將會描述他們從asp.net core 2.X在預設模版中是怎樣改變的,以及探討Aspnetcore3.0使用的Api的變化。 介紹 .Net core ...
引言
在這篇博客中我將探索一些關於Asp.net core 3.0應用的基礎功能——.csproj 項目文件和Program源文件。我將會描述他們從asp.net core 2.X在預設模版中是怎樣改變的,以及探討Aspnetcore3.0使用的Api的變化。
***
介紹
.Net core 3.0 會在九月23號的 NET Conf上發佈,但現在已經有一個支持的預覽版本(Preview 8)。最新的預覽版本與最終發佈版本不可能有太多的變化,所以現在是開始嘗試和查看3.0增加的功能的好時機。
Net core 3.0主要的更新是把windows桌面應用運行了Net core 上,但是Asp Net core 也增加了很多東西。也許最大的新特性就是服務端Blazor(我個人最感興趣的是客戶端的版本,但是現在還不可用),但是也有一些迭代的改變和新特性加入了Asp Net Core。
在這篇博客中,我將探索一些關於非常 “基礎” 的更新。
- Microsoft.AspNetCore.App metapackage在nuget已經不再可用
- Asp net core 已經選擇 GnericHost 來取代 WebHost
如果你打算把Asp net Core 2.X 軟體遷移到3.0 ,一定要查閱遷移指南
在這篇博客中,當你創建一個新的Asp Net core應用時,比如 你用dotnet new webapi,我將探索.csproj 文件和Program.cs文件。在文章的最後,我將比較StartUp文件相對於2.X版本是怎樣變化的,以及Asp Net core 中使用中的模版有什麼不同(比如 web,webapi,mvc)
***
新項目文件與共用框架的變化
當你創建完一個新的Asp Net core項目,然後打開.csproj文件,它基本上是如下的樣子:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
</Project>
如果你與Asp net core 2.X的項目文件做比較,主要有如下的相同點和不同點
<TargetFramework>
不再是netcoreapp2.1或者2.2 ,而是netcoreapp3.0了,這是因為我們把目標框架2.1/2.2 替換成了3.0<Project>
元素仍然是 Microsoft.Net.Sdk.Web,雖然已經更新成了ASP.NET Core 3.0,但是你的項目文件中的語法仍然是沒有變化- Microsoft.AspNetCore.App meta 包已經不存在。
這裡的最後一個有意思的變更。在我之前的博客中提到,在Asp Net core2.X你引用一個名叫Microsoft.AspNetCore.App的共用框架元數據包。這個共用框架提供了大量的好處,比如避免你在你的應用中手動安裝所有的獨立的程式包以及允許你使用 運行時的向前滾動更新的特性。
在Asp Net core3.0中,微軟已經不再以Nuget元數據包的形式發佈這個共用框架,也不存在3.0.0版本的Microsoft.AspNetCore.App。這個共用框架仍然和以前一樣通過Net core 安裝,但是在3.0中你的使用略有不同。
在Asp Net core2.X 中,為了引用這個共用框架,你會添加如下代碼到你的項目文件中:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
相反,在3.0中你要使用 <FrameworkReference>
元素
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
“但是停一下”,你說:“為什麼我的Asp Net Core 項目文件沒有這個?”
這是個好問題,答案是 Microsoft.Net.Sdk.Web
預設包含了。
***
不再有用於共用框架組件的包
在3.0中另外一個最大的變更是你不再需要獨立安裝共用框架的其他部分的Nuget程式包了。例如,在Asp Net Core 2.X中,你可以用 像 Microsoft.AspNetCore.Authentication或Microsoft.AspNetCore.Authentication這樣的獨立的程式包來替換依賴於整個框架的程式包:
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.1.0"/>
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.1.0"/>
</ItemGroup>
這通常對庫最有用,因為應用程式總是需要依賴於共用框架。然而,在 Net Core3.0中,這一切都不可能了。這些Nuget包不會在發佈了。相反,如果你需要在你的項目中引用其中的類庫,你必須添加這個 <FrameworkReference>
元素到你的項目中
例如EF Core和social authentication providers 這些程式包中另外一個需要註意的事情是它們也不再是共用框架的一部分了,如果你需要使用這些程式包,你必須手動從nuget上安裝到你的項目中。
對於這些程式包的完整清單,查閱這個Github issue
***
Program.cs 文件從 2.X到 3.0的變化
Asp Net Core 3.0中的Proram.cs文件第一眼看上去與2.X版本的非常相似。但是已經有許多類型發生了改變,這是因為在Net Core 3.0中,Asp Net Core為了運行在通用host上已經進行了重新構建,使用獨立的Web Host已經被替代。
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
通用Host是從2.1版本被髮布的,這是個非常好的想法,但是我發現關於它的各種問題,主要問題是它為類庫產生了太多的工作,值得慶幸的是,3.0中的這一變化應該可以解決這些問題。
很大程度上,這個變化產生的最終結果是和你過去使用的Net Core2.X版本基本相似,但是用於配置你的app的全部配置的方法WebHost.CreateDefaultBuilder()
被替換成了兩個邏輯步驟,這個兩個獨立的方法叫做:
Host.CreateDefaultBuilder()
,負責配置你的app配置、日誌以及依賴註入容器IHostBuilder.ConfigureWebHostDefaults()
,負責為經典的Asp Net Core 應用添加所需要的所有東西,比如:配置Kestrel和使用一個 Startup.cs用於配置你的DI容器和中間件管道
通用Host builder
正如我之前說的那樣,通用Host為Asp Net core 3.0的構建提供了基礎。它同樣也提供了你先前在Asp Net core應用中使用的基礎性的Microsoft.Extensions.* 元素,比如:日誌、配置和依賴註入。
下麵的代碼是一個簡化版本的 Host.CreateDefaultBuilder()
方法。它和2.X版本的 WebHost.CreateDefaultBuilder()
作用一樣。但是我會簡短說一下值得關註的變化。
public static IHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new HostBuilder();
builder.UseContentRoot(Directory.GetCurrentDirectory());
builder.ConfigureHostConfiguration(config =>
{
// Uses DOTNET_ environment variables and command line args
});
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
// JSON files, User secrets, environment variables and command line arguments
})
.ConfigureLogging((hostingContext, logging) =>
{
// Adds loggers for console, debug, event source, and EventLog (Windows only)
})
.UseDefaultServiceProvider((context, options) =>
{
// Configures DI provider validation
});
return builder;
}
簡而言之,這個方法與2.X版本的不同點如下:
- Hosting配置使用以
DOTNET_
為首碼的環境變數 - Hosting配置使用命令行變數
- 增加了
EventSourceLogger
和EventLogLogger
日誌提供者 - 可以選擇使用ServiceProvider驗證功能
- 沒有關於Web Hosting 的特定配置
第一個有意思的地方就是Host配置是如何設置的。對於Web Host而言,預設使用以 ASPNETCORE_
為首碼的環境變數作為配置。所以設置ASPNETCORE_ENVIRONMENT
環境變數將會設置 Environment
配置的值。對於 通用Host來說,這個首碼現在是DOTNET_
,和傳給應用運行時的任意命令行參數。
這個host配置起的作用好比是決定你的應用運行在什麼的主機環境,host配置與你應用配置(與IOptions介面一起使用的配置)是隔離開來的。
配置你的app設置的方法 ConfigureAppConfiguration()
與2.X相比是沒有變化的,所以它仍然使用appsettings.json文件、appsetting.ENV.json風格文件、用戶機密數據、環境變數以及命令行參數。
通用Host的日誌部分已經在3.0進行了擴展。它仍舊通過你的app配置來配置日誌等級過濾器,以及添加控制台和Debug日誌提供者。然而它同樣也添加來事件源日誌提供者,事件源日誌用於和像windows上的ETW、Linux上的LTTng這樣的系統日誌進行交互。另外,添加一個Event Log provider,只能在windows才會把日誌信息寫入Windows Event Log。
最後,當你的app運行在開發環境時,通用Host配置依賴註入容器的目的是它會驗證範圍(Scopes),這個操作和2.X一樣。這旨在抓取捕獲的依賴關係的實例,在這些實例中,你將一個範圍(Scopes)的服務註入到單例服務中。在3.0中,通用Host通用能啟動 ValidateOnBuild
的功能,我將會在下一篇博客中講到。
通用Host一個關鍵的點是他是通用的,它和Asp Net core 或者Http 工作負載沒有任何關聯。你可以像經典的Asp Net core 應用一樣把通用Host作為你的控制台app或者其他長運行服務的基石。在3.0中你只需要在你的Asp net core 層的頂部增加一個 ConfigureWebHostDefaults()
就可以搞定。
***
用ConfigureWebHostDefaults恢復Asp Net core功能
這篇博客已經很長了,所以在這裡我不想深入挖掘太多的細節,但是,對於添加Asp Net core “層”到 通用Host上面而言,ConfigureWebHostDefaults擴展方法是非常有用的。就簡單層面而言,調用這個方法會使Kestrel web 服務添加到這個host上面,但是這裡面也存在了大量的其他的改變。下麵是關於這個方法提供內容概覽,(包含了GenericWebHostBuilder提供的特性)
- 為Host 配置添加了
ASPNETCORE_
首碼的環境變數(除了DOTNET_
首碼的變數和命令行參數) - 增加了
GenericWebHostService
,這是一個IHostedService的實現,它通常運行在Asp Net core服務上,這是一個主要的特性,這個特性為Asp Net core 復用通用Host提供了可能。 - 增加了一個額外的app配置源,在RazorUI類庫中,這個
StaticWebAssetsLoader
與靜態文件(css/js)共同發揮作用。 - 使用預設Kestrel配置(與2.X一樣)
- 增加
HostFilteringStartupFilter
(和2.0一樣) - 增加
ForwardedHeadersStartupFilter
,如果ForwardedHeaders_Enabled
配置值是true,例如,如果ASPNETCORE_FORWARDEDHEADERS_ENABLED
環境變數的值是true。 - 啟動windows上的IIS集成
- 增加一個端點路由到DI容器中
大部分東西是和Asp net core2.x相同的,不同的地方是:app作為一個IHostService運行的基礎設施、端點路由和ForwardedHeadersStartupFilter
,其中端點路由在3.0是全局啟用的(不再像2.X局限於MVC/Razor頁面了)
ForwardedHeadersStartupFilter
在1.0已經出現了,當你的app運行在代理後面會用到它,是為了確保你的應用能處理SSL-負載和生成正確的URL。這麼設計的目的是你能僅僅通過設置一個環境變數去配置一個使用 X-Forwarded-For
和 X-Forwarded-Proto
請求頭的中間件。
***
總結
在這篇博客中我深挖了從Asp Net Core2.X到3.0中的僅僅兩個文件——.csproj文件和Program.cs文件的變化。從錶面上看,者僅僅是一些細微的變化,所有從2.X移植到3.0應該不會太難。這是天真地掩蓋了其中的巨大的變化——共用框架的明顯的變化,以及Asp Net core 已經在通用Host上重建了。
我認為大家遇到的最大的問題是Nuget 程式包的差異——一些app將要必須移除Asp Net Core 程式包的引用,同時要明確地引用其他的程式包。儘管解決這個問題是不太難,但是它會對不熟悉這個變化的用戶帶來困惑,所以應該第一時間審查這些變化