.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
- 微信小程序左右滑动切换图片酷炫效果(附效果)
- Facebook推出用于android数据加密的开源API
- Android 表单验证框架:AValidations
- 推荐系统介绍
- Android WebView 上传文件支持全解析
- 网站管理软件 – AspxSpy2014 Final
- 特性分支与特性开关哪家强?
- Android快速开发框架 roboguice
- 悄悄的干活,打枪的不要!勒索+比特币挖矿木马
- 拥有可移动头像的折叠Android工具栏:CollapsingAvatarToolbar
- Android平台下的第一个Tor木马
- 利用代码实现自定义圆角+阴影按钮 android-flat-button
- 周末阅读:程序员的《权利法案》
- 对利用Adobe 0day – CVE-2014-0502进行攻击的行为分析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 动画:什么是基数排序?
- 一个有意思的分钱模拟问题
- 如何快速的开发一个完整的直播购物源码,基础篇
- 「拥抱开源」Nacos 实战篇
- 仅2M!免费软件又一次干掉了付费版
- python爬虫学习 爬取幽默笑话网站
- 如何用Python快速优雅的批量修改Word文档样式?
- 为什么MySQL不推荐使用uuid或者雪花id作为主键?
- 用Python打造一款文件搜索工具,所有功能自己定义!
- 用Python绘制诱人的桑基图,一眼看透熬夜和狗粮的秘密
- magento换域名和服务器要怎么操作
- 从零搭建SpringBoot+MyBatis+MySQL工程
- 从零搭建SpringBoot+MyBatis+MySQL
- Typescript 使用日志(干货)
- 22+ 高频实用的 JavaScript 片段 (2020年)