.Net Core 2.2升级3.1的避坑指南

写在前面
微软在更新.Net Core版本的时候,动作往往很大,使得每次更新版本的时候都得小心翼翼,坑实在是太多。往往是悄咪咪的移除了某项功能或者组件,或者不在支持XX方法,这就很花时间去找回需要的东西了,下面是个人在迁移.Net Core WebApi项目过程中遇到的问题汇总:
开始迁移
1. 修改*.csproj项目文件
<TargetFramework>netcoreapp2.</TargetFramework> 修改为 <TargetFramework>netcoreapp3.1</TargetFramework>
2 修改Program
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
} public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>().ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile($"你的json文件.json", optional: true, reloadOnChange: true);
}
);
修改为
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
} public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>()
.ConfigureAppConfiguration((hostingContext, config)=>
{
config.AddJsonFile($"你的json文件.json", optional: true, reloadOnChange: true);
});
});
3.1 修改Startup.ConfigureServices
services.AddMvc(); 修改为 services.AddControllers();
3.2 修改Startup.Configure
public void Configure(IApplicationBuilder app, IHostingEnvironment env) 修改为
using Microsoft.Extensions.Hosting;
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
IHostingEnvironment在3.0之后已被标记弃用。
路由配置:
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areas",
template: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
); routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
}); 修改为 app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute(
name: "areas",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
你以为结束了?还没。
坑
这时候你以为结束了,兴高采烈的去服务器装好runningTime和hosting相应的版本,运行……

HTTP Error 500.30 – ANCM In-Process Start Failure
直接cmd,进入到发布目录,执行:
E:\你的路径>dotnet xxx.dll
显示详细错误

而我的相应250代码行是:
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
//原文地址:https://www.cnblogs.com/EminemJK/p/13206747.html
搜索最新的AutoMapper根本没更新或改变,所以不是这个组件的问题。
尝试下载补丁Windows6.1-KB974405-x64.msu ,无果……
卸载sdk重置,无果……
修改web.config,无果……
修改应用池32位,无果……
最后,查看发布:勾选上【删除现有文件】,解决……

Endpoint contains CORS metadata, but a middleware was not found that supports CORS.
顺利可以启动项目之后,发现有些接口:
-- ::, [] ERROR System.String - 全局异常捕捉:异常:Endpoint contains CORS metadata, but a middleware was not found that supports CORS.
Configure your application startup by adding app.UseCors() inside the call to Configure(..) in the application startup code. The call to app.UseAuthorization() must appear between app.UseRouting() and app.UseEndpoints(...).
提示很明显,在.net core 2.2 的时候
app.UseCors();
不是需要强制在指定位置的,在3.0之后需要设置在app.UseRouting和app.UseEndpoints 之间
app.UseRouting();
//跨域
app.UseCors(one);
app.UseCors(two);
……
app.UseEndpoints(endpoints => ……
The JSON value could not be converted to System.Int32. Path……
运行之后,有些接口没有数据返回,而有些之间报错了。原因又是爸爸把Newtonsoft.Json移除,使用内置的System.Text.Json,所以依赖于Newtonsoft.Json的组件将不可用,那么,只能手动添加。
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson -Version 3.1.
然后添加引用
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddNewtonsoftJson();
}
目前还不太建议你使用内置的序列化,因为实在太多功能或方法不支持,详细对比请参考 https://docs.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json-migrate-from-newtonsoft-how-to
授权相关
基于策略授权,我想在座的加班狗都是大同小异,在2.2以前:

public class PolicyHandler : AuthorizationHandler<PolicyRequirement>
{
/// <summary>
/// 授权方式(cookie, bearer, oauth, openid)
/// </summary>
public IAuthenticationSchemeProvider Schemes { get; set; } private IConfiguration _configuration; /// <summary>
/// ctor
/// </summary>
/// <param name="configuration"></param>
/// <param name="schemes"></param>
/// <param name="jwtApp"></param>
public PolicyHandler(IConfiguration configuration, IAuthenticationSchemeProvider schemes)
{
Schemes = schemes;
_jwtApp = jwtApp;
_configuration = configuration;
} /// <summary>
/// 授权处理
/// </summary>
/// <param name="context"></param>
/// <param name="requirement"></param>
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PolicyRequirement requirement)
{
var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext; //获取授权方式
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
//验证签发的用户信息
var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);
if (result.Succeeded)
{
httpContext.User = result.Principal; //判断是否过期
var expirationTime = DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration).Value);
if (expirationTime >= DateTime.UtcNow)
{
//你的校验方式
//todo
context.Succeed(requirement);
}
else
{
HandleBlocked(context, requirement);
}
return;
}
}
HandleBlocked(context, requirement);
} /// <summary>
/// 验证失败返回
/// </summary>
private void HandleBlocked(AuthorizationHandlerContext context, PolicyRequirement requirement)
{
var authorizationFilterContext = context.Resource as AuthorizationFilterContext;
authorizationFilterContext.Result = new Microsoft.AspNetCore.Mvc.JsonResult(new UnAuthorizativeResponse()) { StatusCode = };
//不要调用 context.Fail(),设置为403会显示不了自定义信息,改为Accepted202,由客户端处理,;
context.Succeed(requirement);
}
}
然后发现升级到3.0之后,
var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;
3.0不再支持返回AuthorizationFilterContext,而是返回的是RouteEndpoint,这句代码就会报错,所以修改的方式就是注入IHttpContextAccessor,从里面获取HttpContext,这里就不用演示了吧。
并修改PolicyHandler校验失败时候调用的方法:
/// <summary>
/// 验证失败返回
/// </summary>
private void HandleBlocked(AuthorizationHandlerContext context, PolicyRequirement requirement)
{
context.Fail();
}
并在Startup.ConfigureServices修改
services.AddHttpContextAccessor();
在AddJwtBearer中
.AddJwtBearer(s =>
{
//3、添加 Jwt bearer
s.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = issuer,
ValidAudience = audience,
IssuerSigningKey = key,
//允许的服务器时间偏差的偏移量
ClockSkew = TimeSpan.FromSeconds(),
ValidateLifetime = true
};
s.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
//Token 过期
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
},
OnChallenge = context =>
{
context.HandleResponse();
context.Response.StatusCode = StatusCodes.Status200OK;
context.Response.ContentType = "application/json";
//无授权返回自定义信息
context.Response.WriteAsync(JsonConvert.SerializeObject(new UnAuthorizativeResponse()));
return Task.CompletedTask;
}
};
});
UnAuthorizativeResponse 是自定义返回的内容。
Startup.Configure中启用Authentication,注意顺序
app.UseRouting();
//跨域
app.UseCors(one);
app.UseCors(two);
……
//启用 Authentication
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints => ……
也必须在app.UseRouting和app.UseEndpoints 之间。
文件下载
单独封装的HttpContext下载方法:
public static void DownLoadFile(this HttpContext context,string fileName, byte[] fileByte, string contentType = "application/octet-stream")
{
int bufferSize = ; context.Response.ContentType = contentType;
context.Response.Headers.Append("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName));
context.Response.Headers.Append("Charset", "utf-8");
context.Response.Headers.Append("Access-Control-Expose-Headers", "Content-Disposition"); //context.Response.Headers.Append("Access-Control-Allow-Origin", "*");
//使用FileStream开始循环读取要下载文件的内容
using (Stream fs = new MemoryStream(fileByte))
{
using (context.Response.Body)
{
long contentLength = fs.Length;
context.Response.ContentLength = contentLength; byte[] buffer;
long hasRead = ;
while (hasRead < contentLength)
{
if (context.RequestAborted.IsCancellationRequested)
{
break;
} buffer = new byte[bufferSize];
//从下载文件中读取bufferSize(1024字节)大小的内容到服务器内存中
int currentRead = fs.Read(buffer, , bufferSize);
context.Response.Body.Write(buffer, , currentRead);
context.Response.Body.Flush();
hasRead += currentRead;
}
}
}
}
下载的时候发现以下错误:Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
-- ::, [] ERROR System.String - System.InvalidOperationException: Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.
at Microsoft.AspNetCore.Server.IIS.Core.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at Microsoft.AspNetCore.Server.IIS.Core.WrappingStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at DigitalCertificateSystem.Common.Extensions.HttpContextExtension.DownLoadFile(HttpContext context, String fileName, Byte[] fileByte, String contentType) in
……
意思不运行同步操作,修改为
context.Response.Body.WriteAsync(buffer, , currentRead);
这才顺利完成了更新。真的太坑了,不过也感觉微软的抽象化做得很好,按需引入,减少项目的冗余。
更多升级指南请参考“孙子兵法”:https://docs.microsoft.com/zh-cn/aspnet/core/migration/22-to-30?view=aspnetcore-2.1&tabs=visual-studio
本文已独家授权给DotNetGeek(ID:dotNetGeek)公众号发布
.Net Core 2.2升级3.1的避坑指南的更多相关文章
- Dolphin Scheduler 1.1.0升级1.2.0避坑指南
本文章经授权转载 组件介绍 Apache Dolphin Scheduler是一个分布式易扩展的可视化DAG工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开 ...
- Asp.Net Core 轻松学-HttpClient的演进和避坑
前言 在 Asp.Net Core 1.0 时代,由于设计上的问题, HttpClient 给开发者带来了无尽的困扰,用 Asp.Net Core 开发团队的话来说就是:我们注意到,HttpC ...
- Spark 1.6升级2.x防踩坑指南
原创文章,谢绝转载 Spark 2.x自2.0.0发布到目前的2.2.0已经有一年多的时间了,2.x宣称有诸多的性能改进,相信不少使用Spark的同学还停留在1.6.x或者更低的版本上,没有升级到2. ...
- ASP.NET Core 3.0 迁移避坑指南
一.前言 .NET Core 3.0将会在 .NET Conf 大会上正式发布,截止今日发布了9个预览版,改动也是不少,由于没有持续关注,今天将前面开源的动态WebApi项目迁移到.NET Core ...
- 将 ASP.NET Core 2.1 升级到最新的长期支持版本ASP.NET Core 3.1
目录 前言 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 消失了 升级到 ASP.NET Core 3.1 项目文件(.csproj) Program. ...
- .Net Core 2.1 升级3.1 问题整理
随着技术的不断拓展更新,我们所使用的技术也在不断地升级优化,项目的框架也在不断地升级,本次讲解 .net core 2.1 升级到3.1所需要注意的事项: 当项目框架升级后,所有的Nuget引用也会 ...
- C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式
C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...
- Entity Framework Core 1.1 升级通告
原文地址:https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-entity-framework-core-1-1/ 翻译:杨晓东 ...
- asp.net core 1.1 升级后,操作mysql出错的解决办法。
遇到问题 core的版本从1.0升级到1.1,操作mysql数据库,查询数据时遇到MissingMethodException问题,更新.插入操作没有问题. 如果你也遇到这个问题,请参照以下步骤进行升 ...
随机推荐
- 从大厂DevOps工具链部署,看现代产品的生命周期管理
目录 1. 认识DevOps 1.1. DevOps工具链 1.2. CI 持续集成(Continuous Integration) 1.3. CD(持续交付 & 持续部署) 1.4. Agi ...
- 今天抠图,Python实现一键换底片!想换什么换什么(附源码)
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 生活中我们会拍很多的证件照,有的要求红底,有的是白底,有的是蓝底,今天不通 ...
- 数据湖&数据仓库,别再傻傻分不清了
摘要:什么是数据湖?它有什么作用?今天将由华为云技术专家从理论出发,将问题抽丝剥茧,从技术维度娓娓道来. 什么是数据湖 如果需要给数据湖下一个定义,可以定义为这样:数据湖是一个存储企业的各种各样原始数 ...
- mysql字符串类型(char,varchar)
原文链接:https://blog.csdn.net/puqutogether/article/details/45648879 MySQL中的字符串有两个常用的类型:char和varchar,二者各 ...
- mysql explain的type的
导语 很多情况下,有很多人用各种select语句查询到了他们想要的数据后,往往便以为工作圆满结束了.这些事情往往发生在一些学生亦或刚入职场但之前又没有很好数据库基础的小白身上,但所谓闻道有先后,只要我 ...
- git 本机链接多库配置
git config --list 查看所有配置 // 提交时读取用户名称及邮箱优先级 --local > --global > --system // 全局配置用户名称及邮箱 git c ...
- 商城06——solr索引库搭建&solr搜索功能实现&图片显示问题解决
1. 课程计划 1.搜索工程的搭建 2.linux下solr服务的搭建 3.Solrj使用测试 4.把数据库中的数据导入索引库 5.搜索功能的实现 2. 搜索工程搭建 要实现搜索功能,需要搭建 ...
- rust 支持的CPU架构
Available CPUs for this target: native - Select the CPU of the current host (currently haswell). amd ...
- JavaWeb网上图书商城完整项目--day02-28.查询所有分类功能之left页面使用Q6MenuBar组件显示手风琴式下拉菜单
首先页面去加载的时候,会去加载main.js文件,我们在加载left.jsp.top.jsp body.jsp,现在我们修改main.jsp的代码,让它去请求的时候去访问的是不在直接去访问left.j ...
- Pytorch入门——手把手带你配置云服务器环境
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天这篇是Pytorch专题第一篇文章. 大家好,由于我最近自己在学习Pytorch框架的运用,并且也是为了响应许多读者的需求,推出了这个P ...