.Net Core 2.2 升级到 .Net Core 3.1

news/2024/7/24 13:13:11/

微软在更新.Net Core版本的时候,动作往往很大,使得每次更新版本的时候都得小心翼翼,坑实在是太多。往往是悄咪咪的移除了某项功能或者组件,或者不在支持XX方法,这就很花时间去找回需要的东西了,下面是个人在迁移.Net Core WebApi项目过程中遇到的问题汇总:

1. 修改*.csproj项目文件

<TargetFramework>netcoreapp2.2</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.
  顺利可以启动项目之后,发现有些接口:

2020-06-29 10:02:23,357 [14] 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 => ……

编译或发布代码分析器在控制台输出警告:
CSC : warning AD0001: Analyzer 'Microsoft.AspNetCore.Mvc.Analyzers.TopLevelParameterNameAnalyzer' threw an exception of type 'System.NullReferenceException' with message 'Object reference not set to an instance of an object.'.
原因是你的项目中,还残留.net core 2.2版本的组件,可以这样检查:

卸载再安装或直接升级最新的版本即可。

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.5
然后添加引用

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){//你的校验方式//todocontext.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 = 202 };//不要调用 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(5),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 = 1024;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 = 0;while (hasRead < contentLength){if (context.RequestAborted.IsCancellationRequested){break;}buffer = new byte[bufferSize];//从下载文件中读取bufferSize(1024字节)大小的内容到服务器内存中int currentRead = fs.Read(buffer, 0, bufferSize);context.Response.Body.Write(buffer, 0, currentRead);context.Response.Body.Flush();hasRead += currentRead;}}}}

下载的时候发现以下错误:Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.


2020-06-29 14:18:38,898 [109] 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, 0, currentRead);
context.Response.Body.FlushAsync();
这才顺利完成了更新。真的太坑了,不过也感觉微软的抽象化做得很好,按需引入,减少项目的冗余。

更多升级指南请参考:从 ASP.NET Core 2.2 迁移到 3.0 | Microsoft Learn


http://www.ppmy.cn/news/434777.html

相关文章

安卓手机免root权限恢复微信聊天记录(以vivo手机为例)

到vivo官方网站下载vivo手机助手。 下载链接&#xff1a; http://zs.vivo.com.cn/(点击新窗口打开) 2. 通过数据线将手机和电脑连接&#xff0c;按照手机助手的提示连接成功。连接成功后&#xff0c;点击"数据备份"。 3. 弹出"vivo备份恢复"界面中&#…

Android 记账软件

推荐初学者的账本app代码下载地址https://download.csdn.net/download/u013766436/9494857

《家庭记账软件》

最近学习的JavaSE入门的一些知识&#xff0c;我们做一个小小的程序练习。 以下是程序需求。 以下为参考代码。 import java.util.Scanner; public class Demo {public static void main(String[] args) {Scanner sc new Scanner(System.in);String s"";int money …

模拟记账软件

模拟实现一个基于文本界面的记账软件 掌握初步的编程技巧和调试技巧 主要涉及以下知识点&#xff1a; 变量的定义 基本数据类型的使用 循环语句 分支语句 方法声明、调用和返回值的接收 简单的屏幕输出格式控制 该软件能够记录家庭的收入、支出&#xff0c;并能够打印收支明…

计算机和专用软件能整体入账吗,好用的电脑记账软件有哪些?

好用的电脑记账软件有哪些&#xff1f; 于2019年9月29日2019年9月29日由editor3发布 如今在很多家庭和企业中&#xff0c;都不会少有电脑的配备&#xff0c;因为电脑已经和我们的生活、工作和学习密不可分。当然&#xff0c;在学习上&#xff0c;主要还是针对大学生是密不可分的…

分享好用的日常记账软件

花钱如流水的我们&#xff0c;是不是还在烦恼着记账的这个问题&#xff1f;现在的年轻人没有存钱的观念&#xff0c;也不清楚自己的钱都花在哪里了&#xff0c;所以记账就很有必要了。根据对比后&#xff0c;推荐你使用【晨曦记账本】 晨曦记账本下载后在电脑上打开&#xff0…

家庭记账软件(项目一)

目 标 • 模拟实现一个基于文本界面的《家庭记账软件》 • 掌握初步的编程技巧和调试技巧 • 主要涉及以下知识点&#xff1a;    变量的定义    基本数据类型的使用    循环语句    分支语句    方法声明、调用和返回值的接收    简单的屏幕输出格式控…

android个人记账软件(附上源码)

2019独角兽企业重金招聘Python工程师标准>>> 介绍&#xff1a;这是一款比较简单的个人记账软件源码&#xff0c;UI比较简陋&#xff0c;功能比较单一&#xff0c;可供大家学习参考。   运行环境&#xff1a; 在android 2.3.3 测试运行通过。   源码下载 转载:ht…

开始做一个简单的记账工具

用VScode做一个简单的记账工具 内容保存在 https://leonchan0608.coding.net/public/bookkeeping/bookkeeping/git 下班学习&#xff0c;奋斗一年&#xff0c;逃离贫困国企&#xff0c;卷起来&#xff01; 想一下怎么做 用pyqt做软件界面&#xff0c;python写后台逻辑&#x…

记帐软件

昨天跟女朋友谈起开销问题&#xff0c;发现半个月就用了差不多2000块&#xff0c;相对现在的收入&#xff0c;不是个小数目&#xff0c;而且关键是钱不知道花到哪里去了。相信很多人跟我一样的情况&#xff0c;因此产生做一个记账软件的想法。上午花了一个多小时&#xff0c;把…

android简单记账软件,简洁记账app

简洁记账app&#xff0c;为用户带来最为简洁却又不失美观的记账应用&#xff0c;让你对自己的开支有个更好地掌控&#xff0c;快来下载试试吧 简洁记账app介绍 一款记账类app&#xff0c;除了基本记账&#xff0c;显示功能外。还可以进行数据的本地备份&#xff0c;导入以及导出…

基于Android开发的记账软件(附带源码)

该app实现了用户添加删除、用户切换、收入记录、支出记录、查询等功能&#xff0c;适合新手学习。搭建方法请可查看主页中的android相关视频教程。 记账软件文件&#xff1a;url80.ctfile.com/f/25127180-738830071-d2178c?p551685 (访问密码: 551685) 开发语言: java 技术…

安卓练习之——记账软件

这是一个简单的账本&#xff0c;目前的功能可以实现记账&#xff0c;显示总的支出、收入、结余&#xff0c;查看账单以及删除不想要的账单。后续功能慢慢完善。那么就开始代码和图演示。 如果有不足的地方&#xff0c;希望看到的大神给予指点建议&#xff0c;不胜感激&#xf…

简账(开源记账软件)-功能介绍

文章目录 简账(开源记账软件)-功能介绍前言一、主要技术栈简介二、主要功能三、项目难点四、总结 简账(开源记账软件)-功能介绍 前言 由于自己有记账的需求&#xff0c;在尝试使用过市面上的记账软件后&#xff0c;发现大多数都有以下几个问题 广告比较多&#xff0c;主要分为…

奚记--最简洁的记账软件

最近几天一直在开发个人的第一个应用--奚记。在昨天我的第一个Android应用终于在豌豆荚平台上架了&#xff0c;真的是激动万分啊&#xff0c;今天就不要脸的来推广介绍下我的软件&#xff0c;让各位见笑我的幼稚的作品了。 奚记&#xff0c;是一款最简洁的记账软件&#xff01…

简单记账本-android版

Android开发也自学了一段时间&#xff0c;家里的pc机上安装了一个家庭理财软件&#xff0c;所以趁着业余时间就用android做了个迷你账本。主要功能其实很简单&#xff1a;账目的添加、修改、删除以及一些统计功能&#xff0c;比如一年的所有收支项统计&#xff0c;一年各月的收…

记账软件哪个好用,亲测有效

当人们从超前消费的狂风中清醒之后&#xff0c;开始对自己的资产重新重视起来了&#xff0c;开始学习记账就成了大家省钱的第一步&#xff0c;但是手写账本非常浪费时间&#xff0c;记起来也比较繁琐&#xff0c;下面就给大家分享几个好用的记账技巧。 电脑端——晨曦记账本 一…

三款好用的记账软件推荐

花钱如流水的我们&#xff0c;是不是还在烦恼记账问题&#xff1f;实际上现在的很多年轻人不仅不爱存钱&#xff0c;也不清楚花的钱都去了哪儿了&#xff0c;这就需要记账了。 根据对比推荐几款用的比较多的免费记账软件&#xff1a;随手记、小鱼记账、松鼠记账。 分别介绍一…

Python网络爬虫开发:使用PyQt5和WebKit构建可定制的爬虫

部分数据来源:ChatGPT 引言 在网络爬虫开发中,使用Web浏览器模拟用户行为是非常重要的。而在这个过程中,基于 WebKit 的框架可以提供比其他技术更紧密的浏览器集成,以及更高效、更多样化的页面交互方式。 在本文中,我们将通过一个使用基于 WebKit 的爬虫示例,并与类似…

实验篇(7.2) 16. 站对站安全隧道 - 通过聚合隧道走对方上网(FortiGate-IPsec) ❀ 远程访问

【简介】前面所有实验基本上是由向导来完成的&#xff0c;只有隧道聚合实验是手动设置的。那么远程访问经常用到的走对方宽带上网功能&#xff0c;需要怎样手动配置呢&#xff1f; 实验要求与环境 OldMei集团深圳总部防火墙现在有三条宽带了&#xff0c;二条普通宽带用来上网及…