.Net Core 2.2 升级到 .Net Core 3.1

这篇具有很好参考价值的文章主要介绍了.Net Core 2.2 升级到 .Net Core 3.1。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

微软在更新.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相应的版本,运行……

.Net Core 2.2 升级到 .Net Core 3.1

HTTP Error 500.30 – ANCM In-Process Start Failure

  直接cmd,进入到发布目录,执行:

E:\你的路径>dotnet xxx.dll

显示详细错误

.Net Core 2.2 升级到 .Net Core 3.1

而我的相应250代码行是:

services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
//原文地址:https://www.cnblogs.com/EminemJK/p/13206747.html
搜索最新的AutoMapper根本没更新或改变,所以不是这个组件的问题。

尝试下载补丁Windows6.1-KB974405-x64.msu ,无果……

卸载sdk重置,无果……

修改web.config,无果……

修改应用池32位,无果……

最后,查看发布:勾选上【删除现有文件】,解决……

.Net Core 2.2 升级到 .Net Core 3.1

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版本的组件,可以这样检查:

.Net Core 2.2 升级到 .Net Core 3.1

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

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)
                    {
                         //你的校验方式
                         //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 = 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文章来源地址https://www.toymoban.com/news/detail-498306.html

到了这里,关于.Net Core 2.2 升级到 .Net Core 3.1的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ASP.NET Core 3.1系列(16)——EFCore之Code First

    前一篇博客介绍了 EFCore 中的 DB First 开发模式,该模式可以根据数据库生成实体类和数据库上下文,因此适用于数据库已经存在的场景。而与之相对应的, Code First 主要是根据自定义的实体类和数据库上下文反向构建数据库,因此也可以看做是 DB First 的逆过程,下面开始介绍

    2024年01月17日
    浏览(59)
  • ASP.NET Core 3.1系列(4)——读写配置文件appsettings.json

    在大多数的应用程序中,一些参数需要写在配置文件里,以此增加系统的灵活性。在 ASP.NET 时代,配置参数一般会写在 web.config 文件中,其本质上是对 XML 文件的读取和写入。而在 ASP.NET Core 中,配置文件变成了 appsettings.json 文件。相较于 XML , JSON 文件更加轻量且灵活,下面

    2024年02月06日
    浏览(51)
  • visual studio 2022.NET Core 3.1 未显示在目标框架下拉列表中

    在Visual Studio 2022我已经安装了 .NET core 3.1 并验证可以运行 .NET core 3.1 应用程序,但当创建一个新项目时,目标框架的下拉列表只允许 .NET 6.0和7.0。而我在之前用的 Visual Studio 2019,可以正确地添加 .NET 核心项目。 运行 .NET Core 3.1 应用程序,需要 .NET Core 3.1 运行时 - 如果可以运

    2024年02月11日
    浏览(39)
  • .net core 3.1 出现 HTTP Error 500.31 - ANCM Failed to Find Native Dependencies

    我已经在服务器安装了dotnet-runtime-3.1.20-win-x64 和dotnet-hosting-3.1.20-win 但部署3.1项目遇到500.13错误 HTTP Error 500.31 - ANCM Failed to Find Native Dependencies Common solutions to this issue: The specified version of Microsoft.NetCore.App or Microsoft.AspNetCore.App was not found. Troubleshooting steps: Check the system event log fo

    2024年02月05日
    浏览(55)
  • 微软.NET、.NET Framework和.NET Core联系和区别

    我是荔园微风,作为一名在IT界整整25年的老兵,看到不少初学者在学习编程语言的过程中如此的痛苦,我决定做点什么,我小时候喜欢看小人书(连环画),在那个没有电视、没有手机的年代,这是为数不多的课余生活方式这一。我画的不好,但是如果能帮大家理解编程语言

    2024年01月16日
    浏览(60)
  • .net core3.1升级.net 7.0

    一、安装环境 安装7.0SDK和runtime 查看是否安装7.0sdk 下载安装或者升级VS2022 Visual Studio 支持 Visual Studio 2022 (v17.4) Visual Studio 2022 for Mac (v17.4) 二、修改项目下的所有csproj文件 3.1csproj 7.0csproj 支持的版本 下表跟踪 .NET 和 .NET Core 版本的发布和终止支持日期。 版本 原始发布日期 最新

    2024年02月04日
    浏览(32)
  • 关于微软NET家族族谱将讲解 关于 最全.NET Core、NET 5、NET 6和.NET 7简介和区别

    不知道从什么时候开始,.NET 出来了越来愈多的名词 ,Visual Studio 版本从2000 一直到了 现在2022 ,中间陆续出来十多个版本,到后面 vscode ,底层 .NET 名称也是越来越花里胡哨的 从.NET FrameWork 1.0到 .net core 到 .NET  5 ,还有各种SDK 啥玩意的,最主要的是 市面上用.NET的公司不多,

    2024年01月18日
    浏览(50)
  • 【.net core】【sqlsugar】批量更新方法

     官方文档:单表更新、更新数据 - SqlSugar 5x - .NET果糖网 泛型类中增加

    2024年04月23日
    浏览(36)
  • .NET 8 Preview 4 中的 ASP.NET Core 更新

    作者:Daniel Roth - Principal Program Manager, ASP.NET 翻译:Alan Wang 排版:Alan Wang .NET 8 Preview 4 现已可用,并包括了许多对 ASP.NET Core 的新改进。 以下是本预览版本中的新内容摘要: Blazor 使用 Blazor 组件进行流式渲染 使用 Blazor SSR 处理表单提交 在 Blazor 中路由到命名元素 Webcil 为 Bl

    2024年02月12日
    浏览(51)
  • .NET 8 Preview 7 中的 ASP.NET Core 更新

    作者:Daniel Roth 排版:Alan Wang .NET 8 Preview 7 现在已经发布,其中包括了对 ASP.NET Core 的许多重要更新。 以下是预览版本中新增功能的摘要: 服务器和中间件 防伪中间件 API 编写 最小 API 的防伪集成 Native AOT 请求委托生成器支持拦截器功能 Full TrimMode 用于启用修剪功能编译的

    2024年02月11日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包