注:本文為記錄貼,如果錯誤,煩請指出
目標:把 .net core2.2 項目升級為 .net core 3.1
一、Program.cs的變更
.net core 2.2版本:

public class Program { public static void Main(string[] args) { BuildWebHost().Run(); } public static IWebHost BuildWebHost() { var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, true) .AddJsonFile("hosting.json", true, true) //配置域名/端口 .Build(); var host = new WebHostBuilder() .UseKestrel() .UseConfiguration(config) .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build(); return host; } }
.net core 3.1版

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>(); }); }
代碼分析:
差異1:
2.2版本的Mian()函數調用的創建Host方法,返回的對象為:IWebHost
3.1版本的 Mian()函數調用的創建Host方法,返回的對象為:IHostBuilder
差異2:
3.1版本無需使用代碼手動加載 appsettings.json 這個配置文件
二、Startup.cs 類的變更
1.swagger注入變化
.net core 2.2版

public void ConfigureServices(IServiceCollection services) { #region Swagger配置 services.AddSwaggerGen(); services.ConfigureSwaggerGen(options => { options.SingleApiVersion(new Swashbuckle.Swagger.Model.Info { Version = "v1", Title = "XXX", Description = "XXXX", TermsOfService = "None" }); options.IncludeXmlComments(Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, "OpenApi.xml")); options.DescribeAllEnumsAsStrings(); }); #endregion } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseSwagger(); app.UseSwaggerUi(); }
.net core 3.1版本

public void ConfigureServices(IServiceCollection services) { #region Swagger配置 services.AddSwaggerGen(); services.ConfigureSwaggerGen(options => { options.SwaggerDoc("Api", new OpenApiInfo { Title = "Api", Version = "V1", Description = "XXX" }); options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml")); options.EnableAnnotations(); }); #endregion } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/Api/swagger.json", "API文檔"); c.RoutePrefix = string.Empty; }); }
2.配置跨域處理
錯誤提示:The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time. Configure the CORS policy by listing individual origins if credentials needs to be supported.”
3.路由和終結點配置差異
.net core 2.2

public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //app.UseHttpsRedirection(); app.UseMvcWithDefaultRoute(); }
.net core 3.1

public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(endpoints=> { endpoints.MapControllers(); }); }
--------------------------------------------------------基礎文件的更改到此結束 -------------------------------------------------------------------
三、關於.net core 3.1的Json更改
場景:接口中帶有 DateTime 類型的參數,部分日期格式的參數來請求時,進入方法失敗。
原因:.net core3.1 請求時參數都是字符串格式,進入方法之前,系統會用默認的 dll 自動做一個反序列化為入參對象,在做反序列化的時候,部分日期格式,不被識別為正確的日期格式,則產生錯誤。
解決方式:
在Startup類的 ConfigureServices(IServiceCollection services)方法中,強制定義反序列化工具為:NewtonsoftJson
services.AddControllers().AddNewtonsoftJson();
四、關於.net core 3.1中的IO 流
1.3.1不默認支持同步IO流

private string GetHttpBody() { using (var reader = new StreamReader(Request.Body)) { var result = reader.ReadToEnd(); return result; } }
此方法會報錯。
解決方案:在 Startup.cs的 ConfigureServices()方法中手動添加對同步IO流的支持
services.Configure<KestrelServerOptions>(options=> { options.AllowSynchronousIO = true; });
2..net core 3.1在讀取 Request.Body時不支持 Request.Body.Position = 0的設置
ASP.NET Core 中的 Request.Body 雖然是一個 Stream ,但它是一個與眾不同的 Stream —— 不允許 Request.Body.Position=0 ,這就意味着只能讀取一次,要想多次讀取,需要借助 MemoryStream
在 .net core 3.0中修復了這個問題,只要啟用倒帶功能,就可以讓 Request.Body 回歸正常 Stream 。
需要引入程序集:Microsoft.AspNetCore.Http
使用方式:
在Startup.cs中定義Middleware,設置緩存Http請求的Body數據
app.Use(async (context, next) => { context.Request.EnableBuffering(); await next.Invoke(); });