.Net Core 2.2 升级到 .Net Core 3.1 填坑

时间:2020-03-23
本文章向大家介绍.Net Core 2.2 升级到 .Net Core 3.1 填坑,主要包括.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
        }

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

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

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

原文地址:https://www.cnblogs.com/gt1987/p/12552735.html