与时俱进 | 博客现已运行在 .NET Core 3.0 及 Azure 上
點(diǎn)擊上方藍(lán)字關(guān)注“汪宇杰博客”
導(dǎo)語(yǔ)
9月23日,微軟正式發(fā)布了 .NET Core 3.0,這個(gè)版本具有大量新功能和改進(jìn)。我也在第一時(shí)間將自己的博客網(wǎng)站更新到了 .NET Core 3.0,并且仍然跑在微軟智慧云 Azure 國(guó)際版的應(yīng)用服務(wù)上。本文總結(jié)了我在博客遷移過(guò)程中所有的要點(diǎn)。
從 .NET Core 3.0 Preview 8 開(kāi)始,我一直在研究博客從 .NET Core 2.2 到 .NET Core 3.0的遷移。大多數(shù)遷移路徑可以遵循微軟官方文檔。但眾所周知,常規(guī)ASP.NET 項(xiàng)目絕不會(huì)只使用來(lái)自微軟或 .NET 本身的 API 和包。有很多第三方包可能尚未更新以支持 .NET Core 3.0。某些庫(kù)仍將在 .NET Core 3.0 上運(yùn)行,但并不是每個(gè)庫(kù)都可以完全沒(méi)有任何問(wèn)題地運(yùn)行。
典型的 ASP.NET Core 項(xiàng)目的遷移可能卡在這些第三方包上,因此請(qǐng)?jiān)谶w移之前查看這些包是否有新版本發(fā)布。
我不會(huì)在這里重復(fù)微軟文檔中已有的遷移步驟。請(qǐng)按照正式文檔上的所有內(nèi)容首先將項(xiàng)目遷移到 .NET Core 3.0。但是到目前為止,以下內(nèi)容并不在文檔中,您可能需要注意。
微軟官方遷移文檔:https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio
運(yùn)行時(shí)及SDK
.NET Core 3.0 運(yùn)行時(shí)可以和舊版本同時(shí)安裝在一臺(tái)機(jī)器上。例如,你可以同時(shí)具有 1.1, 2.1, 2.2 以及 3.0 的運(yùn)行時(shí),互相不會(huì)干擾。
對(duì)于 SDK,從3.0開(kāi)始,安裝新版 SDK 會(huì)自動(dòng)卸載舊版本(僅3.0)的SDK,因此你的程序列表里不會(huì)出現(xiàn)一大坨SDK。
可以參閱微軟官方博客對(duì) SDK 安裝改進(jìn)的說(shuō)明:https://devblogs.microsoft.com/dotnet/improving-net-core-installation-in-visual-studio-and-on-windows/
要在 Windows Server 的 IIS 上承載一個(gè) .NET Core 3.0 應(yīng)用,你依然需要安裝 Runtime and Hosting Bundle (ANCM 模塊)。
Visual Studio 及工具
有許多朋友在微信群里問(wèn)過(guò),為啥安裝了 .NET Core 3.0 SDK,VS里依舊不顯示?這是因?yàn)橹挥凶钚碌?6.3版的VS2019才完整支持開(kāi)發(fā).NET Core 3.0程序。因此請(qǐng)確保你先升級(jí)到VS2019 16.3。
至于 Visual Studio Code,無(wú)需額外的處理,依舊運(yùn)行得很香。
C# 8 及工程文件
C# 8 與.NET Core 3.0同時(shí)發(fā)布,當(dāng)前的SDK及編譯器支持最新語(yǔ)法。因此以前我為了讓項(xiàng)目在編譯服務(wù)器上通過(guò)而采用的變通方案可以刪了:
?<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> ? ?<LangVersion>7.3</LangVersion> </PropertyGroup>
被砍的 ASP.NET Core 包
如果你針對(duì) .NET Core 2.x 或者 .NET Standard 2.x 寫(xiě)了個(gè)類庫(kù),正好用到了像這樣的 ASP.NET 包:
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
你是肯定找不到他們的3.0版本的,因?yàn)榇蠹姨矚g,所以砍了。
詳見(jiàn)官方說(shuō)明:https://github.com/aspnet/AspNetCore/issues/3756
然而仍然有一些漏網(wǎng)之魚(yú)是有3.0版本的,比如這個(gè):
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="3.0.0" />
因此,如果你找不到對(duì)應(yīng)包的3.0版本,現(xiàn)在的解決方式也很簡(jiǎn)單,直接將他們替換成一個(gè)單獨(dú)的 Microsoft.AspNetCore.App 的FrameworkRefrence,即可干掉一切ASP.NET Core的包,就算算有3.0版本也可以無(wú)視。?
<FrameworkReference Include="Microsoft.AspNetCore.App" />
Json.NET vs System.Text.Json
我個(gè)人是個(gè)極端微軟主義戰(zhàn)士,倡導(dǎo)盡可能遷移到 System.Text.Json。事實(shí)上,我博客除了引用庫(kù)依賴以外的用戶代碼里,已經(jīng)沒(méi)有任何 Json.NET 的痕跡了。但是,目前 System.Text.Json 有一些已知的限制和巨坑,比如我在 GitHub 上提出的這個(gè):https://github.com/dotnet/corefx/issues/41102 。諸如此類的問(wèn)題容易讓你的代碼瞬間爆炸,而你死活不知道為啥。
不拋出異常的代碼也不一定意味著能像以前一樣運(yùn)行。例如,有一些特殊字符會(huì)被轉(zhuǎn)義。這會(huì)讓你的API用戶或者前端程序員爆進(jìn)ICU。
var obj = new { Id = 1, BlowUp = @"Make \things blow / <up>" };
var jsonNetResult = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
var systemTextJsonResult = System.Text.Json.JsonSerializer.Serialize(obj);
這段代碼的結(jié)果竟然是:
jsonNetResult
{"Id":1,"BlowUp":"Make \\things blow / <up>"}
systemTextJsonResult
{"Id":1,"BlowUp":"Make \\things blow / \u003Cup\u003E"}
因此請(qǐng)格外小心這些轉(zhuǎn)義,一定要在發(fā)布到正式環(huán)境之前用足夠的數(shù)據(jù)完整測(cè)試你的代碼。
此外,不僅僅序列化會(huì)爆,反序列化也有行為上的差異,容易讓你996進(jìn)ICU。
class BlowUp
{
? ? public int Id { get; set; }
? ? public string Name { get; set; }
}
static void Main(string[] args)
{
? ? string rawJson = "{\"id\":1,\"name\":\"996ICU\"}";
? ? var obj1 = Newtonsoft.Json.JsonConvert.DeserializeObject<BlowUp>(rawJson);
? ? var obj2 = System.Text.Json.JsonSerializer.Deserialize<BlowUp>(rawJson);
? ? Console.WriteLine(obj1.Name);
? ? Console.WriteLine(obj2.Name);
}
猜猜結(jié)果是啥?
只有 obj1.Name 有值。因?yàn)?obj2 的所有屬性都是默認(rèn)值或null。
這是因?yàn)槲覀儌魅氲腏SON字符串用了小寫(xiě)開(kāi)頭的屬性名。Json.NET默認(rèn)會(huì)處理這種情況,但是 System.Text.Json 必須使用這樣的參數(shù):
var obj2 = System.Text.Json.JsonSerializer.Deserialize<BlowUp>(rawJson, new JsonSerializerOptions
{
? ? PropertyNameCaseInsensitive = true
});
在真實(shí)項(xiàng)目里,ASP.NET Core Web API 或者異教徒的API產(chǎn)品通常返回小寫(xiě)開(kāi)頭的JSON字符串。當(dāng)我們使用這些API時(shí),System.Text.Json 的默認(rèn)行為就會(huì)讓我們爆進(jìn)ICU。
就像剛才這兩個(gè)例子一樣,新版JSON API有太多意外行為,因此在遷移到 System.Text.Json 前,請(qǐng)確保你有充分的測(cè)試數(shù)據(jù)覆蓋所有情況再上線。
Azure 應(yīng)用程序監(jiān)控遷移
請(qǐng)參閱我之前的文章:Migrate Azure Application Insights to ASP.NET Core 3.0
https://edi.wang/post/2019/9/2/migrate-azure-application-insights-to-aspnet-core-30
(中文版還沒(méi)來(lái)得及翻譯,先湊合看看吧)
Azure DevOps 大爆炸
Azure DevOps 的編譯管線里還沒(méi)有部署 .NET Core 3.0,因此目前你提交一個(gè) .NET Core 3.0 的程序到CI管線里肯定編譯不過(guò)。解決方案是添加一個(gè)安裝 .NET Core 3.0 SDK的步驟。
Azure App Service 大爆炸
Azure App Service 也還沒(méi)有部署 .NET Core 3.0。因此如果你直接將項(xiàng)目用默認(rèn)編譯形式部署在Azure上,會(huì)直接產(chǎn)生一個(gè)ANCM的啟動(dòng)異常,爆進(jìn)ICU。解決方案是使用SCD部署。
如果你使用的是 Azure DevOps,修改發(fā)布參數(shù),添加 SCD 參數(shù),如:--self-contained -r win-x64
結(jié)束語(yǔ)
以上就是我遷移 .NET Core 3.0 時(shí)遇到的所有問(wèn)題及技巧。還有很多其他我沒(méi)遇到過(guò)的場(chǎng)景,歡迎大家留言補(bǔ)充。
總結(jié)
以上是生活随笔為你收集整理的与时俱进 | 博客现已运行在 .NET Core 3.0 及 Azure 上的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 推荐.neter常用优秀开源项目系列之二
- 下一篇: Asp.Net Core Mvc Raz