从 ASP.NET Core 2.x Web API 迁移到 .Net Core 3.1
介绍
在本文中,我将引导您将现有的 .NET Core 2.x Web API 应用程序更新到 .NET Core 3.1。迁移到 .NET core 3.1 将帮助您利用 .NET core 3.1 的优势。
在这里,您将找到.NET core 3.1的新功能。
我将解释我为迁移我的一个项目所做的所有步骤。新版本中有很多重大更改。您可以在此处找到所有重大更改。
先决条件
Visual Studio 2019(因为 .NET core 3.x 适用于 VS 2019)
将目标框架从 .net core 2.x 更新到 3.1
转到您的项目属性并更改目标框架:

或者你可以搜索标签<TargetFramework>中。csproj文件并将其值更改为“ netcoreapp3.1 ”,如下所示:

删除已移除并移至共享库的 NuGet 包引用
从您的项目依赖项或 .csproj 文件中删除“Microsoft.AspNetCore.App”:
<PackageReference Include= "Microsoft.AspNetCore.App" />
从您的项目依赖项或 .csproj 文件中删除“Microsoft.AspNetCore.App.Razor.Design”:
<PackageReference Include= "Microsoft.AspNetCore.Razor.Design" 版本= "2.2.0" />
更新 NuGet 包引用(如果适用,在.csproj文件中或直接在您的项目Dependencies 中)
昂首阔步
它用于 API 文档。如果您正在使用然后更新到版本“Swashbuckle.AspNetCore”到版本 5.5.1.NET 核心 3.1 中的 Swagger 配置有很多变化
<PackageReference Include= "Swashbuckle.AspNetCore" Version= "5.5.1" />
NewtonSoft /任何 JSON 序列化程序
如果您正在使用任何 JSON 序列化程序,请添加 3.1.5 版本的“Microsoft.AspNetCore.Mvc.NewtonsoftJson”引用,因为在 .NET core 3.1 中,Microsoft 引入了内置更快的 JSON 序列化程序。
<PackageReference Include= "Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version= "3.1.5" />
Kestrel 网络服务器
Kestrel 是基于 Libuv 库(也用于 node.js)实现的首选 Web 服务器,如果您在应用程序中使用它,则将“Microsoft.ServiceFabric.AspNetCore.Kestrel”更新到版本 4.1.417
笔记
如果您在 Kestrel 网络服务器中使用Nagle 算法( NoDelay ) 来减少 TCP 网络上的数据包数量以提高效率,如下所示(在您的 kestrel 配置中)。
listenOptions.NoDelay = true ;
然后,您需要添加以下 Nuget 包,因为它被移动到单独的包
3.1.5 版本的“Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv”
修改 Startup.cs 的 ConfigureServices 方法
用 AddControllers 替换 AddMvc,微软用两个选项替换 AddMVC:
- Web 应用程序 (MVC) – 我们应该用 AddControllersWithViews 替换 AddMVC
- Web API – 我们应该用 AddControllers 替换 AddMVC,这里的动机是不加载与视图相关的库或组件
从:
services.AddMvc(options =>
到:
services.AddControllers(options =>
在 SetCompatibilityVersion 中将 .Net Core MVC Compatability 版本从 2.x 替换为 3.0
从:
services.AddControllers(options => {
options.Conventions.Add( new AddAuthorizeFiltersControllerConvention());
options.OutputFormatters.RemoveType < HttpNoContentOutputFormatter > ();
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
到:
services.AddControllers(options => {
options.Conventions.Add( new AddAuthorizeFiltersControllerConvention());
options.OutputFormatters.RemoveType < HttpNoContentOutputFormatter > ();
}).SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
用 AddNewtonsoftJson 替换 AddJsonOptions 它是内置的更快的 JSON 序列化程序,如#3.b 所述
从:
services.AddMvc(options => {
options.Conventions.Add( new AddAuthorizeFiltersControllerConvention());
options.OutputFormatters.RemoveType < HttpNoContentOutputFormatter > ();
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
});
到:
services.AddControllers(options => {
options.Conventions.Add( new AddAuthorizeFiltersControllerConvention());
options.OutputFormatters.RemoveType < HttpNoContentOutputFormatter > ();
}).SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddNewtonsoftJson(options => {
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
options.SerializerSettings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat;
});
如果您允许来自跨域或跨域的 HTTP 请求,则将 WithOrigins(“*”) 替换为 AllowAnyOrigin()
从:
services.AddCors(options => {
options.AddPolicy("CorsPolicy", builder => builder.WithOrigins("*")
到:
services.AddCors(options => {
options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin()
如果您将 Swagger 用于 API 文档,请更改以下粗体文本:
来自:
{
c.SwaggerDoc("v1", new Info {
Title = "Your API Title",
Version = "API Version Number",
Description = "Description of your API"
});
c.AddSecurityDefinition("Bearer", new ApiKeyScheme {
In = "header",
Description = "Please enter JWT with Bearer into field",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary < string, IEnumerable < string >> {
{
"Bearer",
Enumerable.Empty < string > ()
},
});
c.CustomSchemaIds(i => i.FullName);
c.OperationFilter < SwaggerParametersFilter > ();
到:
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo {
Title = " Your API Title ",
Version = "API Version Number",
Description = "Description of your API "
});
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
Description = "Please enter JWT with Bearer into field”
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement() {
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List < string > ()
}
});
c.CustomSchemaIds(i => i.FullName);
c.OperationFilter < SwaggerParametersFilter > ();
我将在 #6 中介绍 SwaggerParametersFilter。
在 Startup.cs 的配置方法中
将 IHostingEnvironment 替换为 IWebHostEnvironment HostingEnviorment现在已过时,它将从 .net 核心的未来版本中删除。它被注入控制器并提供应用程序网络托管环境的信息。
从:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider services)
到:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider services)
使用 #4.d 中定义的 CORS 策略名称,而不是在此处定义规则:
从:
app.UseCors(builder => builder.WithOrigins( "*" )
到:
app.UseCors( "CorsPolicy" );
这里 CorsPolicy 是 cors 策略的名称。
将 app.UseMvc() 替换为EndPoint Routing,如下所示,
从:
app.UseMvc();
到:
app.UseRouting();
app.UseEndpoints(endpoints => {
endpoints.MapDefaultControllerRoute();
endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
在 .NET Core 中,EndPoint路由是引入的新功能,它在您的请求管道的中间件中提供路由信息。
所以,AddMVC和EndPoint路由的区别在于,AddMVC在你的请求管道的中间件完成后提供路由信息,所以我们中间件中没有路由信息。在端点路由中,我们正在配置它并将其放入中间件请求管道中。
如果您使用 Swagger 操作过滤器在所有操作方法或端点上全局应用某些逻辑,请更改下面的粗体文本:
从:
public class SwaggerParametersFilter: IOperationFilter {
public void Apply(Operation operation, OperationFilterContext context) {
if (operation.Parameters == null) operation.Parameters = new List < IParameter > ();
operation.Parameters.Add(new NonBodyParameter {
Name = "HeaderName",
In = "header",
Type = "string",
Required = true
});
到:
public class SwaggerParametersFilter: IOperationFilter {
public void Apply(OpenApiOperation operation, OperationFilterContext context) {
if (operation.Parameters == null) operation.Parameters = new List < OpenApiParameter > ();
operation.Parameters.Add(new OpenApiParameter {
Name = " HeaderName",
In = ParameterLocation.Header,
Required = true
});
如果您使用的是带有 Kestrel 的无状态服务,那么在 CreateServiceInstanceListeners 方法中,如果您使用的是listenOptions.NoDelay =true; (为了提高效率,它使用了在 #3.c 部分中介绍的 Nagle)
从:
return new WebHostBuilder().UseKestrel(opt => {
int Httpsport = serviceContext.CodePackageActivationContext.GetEndpoint("1HttpsEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, Httpsport, listenOptions => {
listenOptions.UseHttps(GetCertificateFromStore());
listenOptions.NoDelay = true;
});
到(去掉蓝色粗体,添加如下配置“UseLibuv ” ),
return new WebHostBuilder().UseKestrel(opt => {
int Httpsport = serviceContext.CodePackageActivationContext.GetEndpoint("1HttpsEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, Httpsport, listenOptions => {
listenOptions.UseHttps(GetCertificateFromStore());
});
}).UseLibuv(opts => {
opts.NoDelay = true;
})
如果您使用 Service Fabric 托管 API/微服务,请使用最新版本更新 Service Fabric 群集。
结论
我试图涵盖人们通常在 API 实现中使用的几乎所有基本内容。好消息是 .NET Core 3.1 有长期支持(直到 2022 年 12 月 3 日)。
感谢您阅读这篇文章!
常见问题FAQ
- 程序仅供学习研究,请勿用于非法用途,不得违反国家法律,否则后果自负,一切法律责任与本站无关。
- 请仔细阅读以上条款再购买,拍下即代表同意条款并遵守约定,谢谢大家支持理解!
