注:本文为记录贴,如果错误,烦请指出
目标:把 .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(); });