zoukankan      html  css  js  c++  java
  • .Net Core 2.2 升级到 .Net Core 3.1 填坑

    今天尝试将自己的小项目从.net core 2.2 升级到 3.1,发现并不是简单的 一键升级 这么简单(惭愧)!!记录下升级的步骤以及过程中遇到的问题。

     

    所有项目目标框架选择为.net core 3.1

    发现项目依赖项的包中出现黄色感叹号,编译成功,但是项目启动后显示警告。

    原因警告已经说的很清楚了,移除Microsoft.AspNetCore.App和Razor.Design引用。

    项目启动更改

    原启动方式

            public static void Main(string[] args)
            {
                CreateWebHostBuilder(args).Build().Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .ConfigureLogging((hostingContext,logging)=> {
                        logging.ClearProviders();
                        logging.AddConsole();
                        logging.AddNLog();
                    })
                    .UseStartup<Startup>();

    现启动方式,注意,采用了更通用的Host替代了原来的WebHost

            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                    .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseStartup<Startup>()
                                    .ConfigureLogging((hostingContext, logging) =>
                                    {
                                        logging.ClearProviders();
                                        logging.AddConsole();
                                        logging.AddNLog();
                                    });
                        });

    更新所有Nuget包至最新

    mvc项目异常来了!

    Application startup exception: System.InvalidOperationException: Endpoint Routing does not support 'IApplicationBuilder.UseMvc(...)'. To use 'IApplicationBuilder.UseMvc' set 'MvcOptions.EnableEndpointRouting = false' inside 'ConfigureServices(...).

    原本MVC注册方式发生变化,不再支持 app.UserMcv();

    修改成以下方式

            public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllers();
            }
    
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }

    当然网上也提供了支持原类似的注册方式,可参考 https://www.cnblogs.com/tianma3798/p/11909293.html

    部分依赖组件注册方式也发生了变化。例如Autofac,原因是ConfigureServices不再支持返回System.IServiceProvider。

    原本的注册方式

            public IContainer ApplicationContainer { get; private set; }
            private IServiceProvider ConfigureInjectionsWithAutofac(IServiceCollection services)
            {
                var builder = new ContainerBuilder();
                //very import
                //正常返回IServiceProvider 并不能替代原IServicePrivder。还需要自定义ServiceScopeFactory保证RequestServices返回的也是你自定义的ServiceProvider。
                //详细见https://www.cnblogs.com/artech/p/3rd-party-di-integration.html
                //此处autofac做了特殊处理
                builder.Populate(services);
    
                //TODO 如何支持多个数据库链接DbContext?
                //具体的 Repository,可以依赖具体的 DbContext
                builder.RegisterType<MyDataContext>().As<DbContext>().InstancePerLifetimeScope();
    
                #region repository
    
                builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerLifetimeScope();
    
                #endregion
    
                #region domainService
    
                builder.RegisterType<UserDomainService>().As<IUserDomainService>().InstancePerLifetimeScope();
    
                #endregion
    
                #region appService
    
                builder.RegisterType<UserAppService>().As<IUserAppService>().InstancePerLifetimeScope();
    
                #endregion
    
                #region middlerware
    
                builder.RegisterType<GlobalExceptionMiddleware>().AsSelf().InstancePerLifetimeScope();
                builder.RegisterType<GlobalApiLoggingMiddleware>().AsSelf().InstancePerLifetimeScope();
    
                #endregion
    
                ApplicationContainer = builder.Build();
    
                return new AutofacServiceProvider(ApplicationContainer);
            }

    现在的注册方式,在program.cs类中 UseServiceProviderFactory

            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                    .ConfigureWebHostDefaults(webBuilder =>
                        {
                            webBuilder.UseStartup<Startup>()
                                    .ConfigureLogging((hostingContext, logging) =>
                                    {
                                        logging.ClearProviders();
                                        logging.AddConsole();
                                        logging.AddNLog();
                                    });
                        });

    在Startup.cs类中新增 ConfigureContainer

            public void ConfigureContainer(ContainerBuilder builder)
            {
                #region repository
    
                builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerLifetimeScope();
    
                #endregion
    
                #region domainService
    
                builder.RegisterType<UserDomainService>().As<IUserDomainService>().InstancePerLifetimeScope();
    
                #endregion
    
                #region appService
    
                builder.RegisterType<UserAppService>().As<IUserAppService>().InstancePerLifetimeScope();
    
                #endregion
    
                #region middlerware
    
                builder.RegisterType<GlobalExceptionMiddleware>().AsSelf().InstancePerLifetimeScope();
                builder.RegisterType<GlobalApiLoggingMiddleware>().AsSelf().InstancePerLifetimeScope();
    
                #endregion
            }

    webapi返回值问题。我正好有个接口返回的是JObject。升级到3.1后报 System.NotSupportedException: The collection type 'Newtonsoft.Json.Linq.JObject' is not supported。原代码如下

            [Route("headclaims")]
            [HttpGet]
            public IActionResult HeadClaims()
            {
                var claimTypes = new List<string> { "name", "phone", "userId", "introduce","client_id" };
                var claimHeads = Request.Headers.Where(x => claimTypes.Contains(x.Key));
                var user = Request.HttpContext.User;
                if (claimHeads == null) return Ok();
                var returnObj = new JObject();
                foreach (var ch in claimHeads)
                {
                    returnObj.Add(ch.Key, ch.Value.ToString());
                }
                return Ok(returnObj);
            }

    最后返回要修改成这样,才能正确返回。

                return Ok(returnObj.ToString());

    Entityframework 问题。下面代码在2.2是可以运行的,但是3.0会报linq错误。

            public async Task<UserEntity> GetUserAsync(string name, string password)
            {
                return await _dbSet.FirstOrDefaultAsync(x => string.Equals(x.Name, name, StringComparison.CurrentCultureIgnoreCase)
                       && string.Equals(x.Password, password, StringComparison.CurrentCultureIgnoreCase));
            }

    修正为

            public async Task<UserEntity> GetUserAsync(string name, string password)
            {
                return await _dbSet.FirstOrDefaultAsync(x => x.Name == name
                       && x.Password == password);
            }

    原因应该在这里能解释:https://docs.microsoft.com/zh-cn/ef/core/querying/client-eval。

    至此,我的小项目正确运行起来!!

    最后贴下官方的迁移指引,我承认之前没看~~~。一定要看一下!!!

    https://docs.microsoft.com/zh-cn/aspnet/core/migration/22-to-30?view=aspnetcore-3.1&tabs=visual-studio

  • 相关阅读:
    Oracle 循环语句
    IDEA---SpringBoot同一个项目多端口启动
    Maven引入oracle驱动包
    Linux安装 PostgreSQL
    Oracle备份及备份策略
    Oracle优化的几个简单步骤
    Oracle RMAN备份策略
    常见的几种索引扫描类型
    插槽内容
    分布式系统session同步解决方案
  • 原文地址:https://www.cnblogs.com/gt1987/p/12552735.html
Copyright © 2011-2022 走看看