将 ASP.NET Core 2.1 升级到最新的长期支持版本ASP.NET Core 3.1

目录

  1. 前言

  2. Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 消失了

  3. 升级到 ASP.NET Core 3.1

    1. 项目文件(.csproj)

    2. Program.cs

    3. Startup.cs

  4. ViewBag 与 Razor Pages 第一次接触

  5. ViewBag 与 Razor Pages 第二次接触

  6. 小结(文件更改对比图)

  7. ASP.NET Core 3.1的确很棒,肉眼可见的快、快、快!

 前言

2019年的最后一个月,微软终于发布了.Net Core 3.1,这是 .Net Core 有史以来的第二个长期支持版本(至少 3 年的支持期限)。

作为一个大版本更新,.NET Core 3.0 引入了大量改进和新特性,例如新增加的 Windows Forms 和 WPF、新的 JSON API、对 ARM64 架构的支持,以及全面提升的性能。

所以升级是势在必行的,那么很多开发人员就面临一个问题:

如果从上一个长期支持版本 ASP.NET Core 2.1 升级到最新的 ASP.NET Core 3.1 ?

 .Net Core 版本列表:

From:https://dotnet.microsoft.com/download/dotnet-core

 

如果是之前的 .Net Framework,这个升级是非常平滑的,甚至不需要做任何改动(比如:.Net Framework 2.0 -> .Net Framework 4.5),但是 .Net Core 的升级却有点麻烦,微软给出了一系列的升级指南,不过都是从上一个版本到下一个紧邻版本:

ASP.NET Core 2.1 -> 2.2:https://docs.microsoft.com/zh-cn/aspnet/core/migration/21-to-22

ASP.NET Core 2.2 -> 3.0:https://docs.microsoft.com/zh-cn/aspnet/core/migration/22-to-30

ASP.NET Core 3.0 -> 3.1:https://docs.microsoft.com/zh-cn/aspnet/core/migration/30-to-31 

当然这个过程不仅仅是改个配置文件的问题,.Net Core 的版本升级中居然有很多 Breaking changes,也就是说如果你用的类在 .Net Core 3.1 中突然删除了,对不起,你只有调整自己代码的份了。 

Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 消失了

而且这个 Breaking changes 还不少,比如 FineUICore 之前的版本(支持ASP.NET Core 2.1)用到的 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 在 .Net Core 3.1 就被无情的删掉了:

 

那位说了,你为啥要用 .Internal 里面的类?

这是很正常的,FineUICore作为一个支持 ASP.NET Core 的控件库,需要一些底层操作,为了支持快速数据绑定,类似如下的形式:

  • 支持 TagHelpers 的页面代码:<f:DatePicker For="TheModel.StartDate"></f:DatePicker>

  • 支持 HtmlHelpers 的视图代码:F.DatePickerFor(m => m.TheModel.StartDate)

可以参考示例:https://pages.fineui.com/#/DataModel/UICompare

为了支持这个特性,我们就需要计算表达式的文本值,以及表达式所绑定的数据,因此就用到了如下两个静态类方法:

  • ExpressionHelper.GetExpressionText

  • ExpressionMetadataProvider.FromLambdaExpression

在 .Net Core 2.2 之前的版本,这两个方法是逃不过的。可惜不巧的是,微软却认为这些方法没有公开的价值,因此就武断的隐藏掉了(你让之前使用这些类的程序情何以堪!)。

网络上有很多类似的提问,但是阻挡不了微软隐藏几乎所有 .Internal 命名空间类的做法。

https://github.com/aspnet/AspNetCore/issues/8678

https://github.com/aspnet/Mvc/issues/8724

 

在 ASP.NET Core 3.1 虽然有替代的方法可以实现上述被删掉的功能,但是就做不到向后兼容了。FineUICore近期已经升级到 FineUICore v6.2.0,以便适用这个改动,升级之后支持 .Net Core 3.1+,不再对老版本提供支持了。

 

升级到 ASP.NET Core 3.1

下面我们会以 FineUICore.Examples 为例,讲解如果将 ASP.NET Core 2.1 升级到 ASP.NET Core 3.1,这里面的坑还真不少。

项目文件(.csproj)

 

这里面有几点需要注意:

1. TargetFramework 改为 netcoreapp3.1

2. 删除 Microsoft.AspNetCore.App 的引用,这个会默认包含在框架 Sdk=Microsoft.NET.Sdk.Web 中

3. 添加 Microsoft.AspNetCore.Mvc.NewtonsoftJson 的引用

 

有一点需要特别注意, .Net Core 3.0 已经从共享框架中删除了 Newtonsoft.Json,并引入新的 System.Text.Json 类库。

但是我们的 FineUICore 示例代码很多地方都依赖了 Newtonsoft.Json 的特性,因此需要引入 Microsoft.AspNetCore.Mvc.NewtonsoftJson,这个引用会自动包含 Newtonsoft.Json 库,可以求证于编译时的 Debug 文件夹,位于项目的 \bin\Debug\netcoreapp3.1:

 完整的项目工程文件:

<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>netcoreapp3.1</TargetFramework><MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish></PropertyGroup><ItemGroup><PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.0" /></ItemGroup><ItemGroup><ProjectReference Include="..\FineUICore\FineUICore.csproj" /></ItemGroup></Project>

Program.cs

需要注意的几点:

1. 将 IWebHostBuilder 改为  IHostBuilder

2. 将 Web 服务器的启动代码放到 ConfigureWebHostDefaults 中

 

当然,这些改动我们不需要特别关心,简单的照做就行了。

完整的 Progam.cs 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;namespace FineUICore.Examples
{public class Program{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();});}
}

Startup.cs

这里的改动有点多,我们分两个截图分别说明 ConfigureServices 和 Configure 的改动:

 

这里有几点需要调整:

1. 用 AddControllersWithViews 替代 AddMvc

2. 对参数 ModelBinderProviders 更改放到 AddMvcOptions 中

3. 添加 AddNewtonsoftJson 用来使用老的 Newtonsoft.Json 来序列化 JSON 数据

 

ASP.NET Core 3.1 添加了三个新的服务注册方法来代替之前的 AddMvc:

  • AddRazorPages:添加对 Razor Pages 的支持

  • AddControllersWithViews:添加对控制器和视图的支持

  • AddControllers:添加对控制器的支持

这些方法可以组合,比如如下代码等效于之前版本的 AddMvc:

services.AddControllersWithViews();
services.AddRazorPages();

这个方法的完整代码:

public void ConfigureServices(IServiceCollection services)
{services.AddDistributedMemoryCache();services.AddSession();// 配置请求参数限制services.Configure<FormOptions>(x =>{x.ValueCountLimit = 1024;   // 请求参数的个数限制(默认值:1024)x.ValueLengthLimit = 4194304;   // 单个请求参数值的长度限制(默认值:4194304 = 1024 * 1024 * 4)});// FineUI 服务services.AddFineUI(Configuration);services.AddControllersWithViews().AddMvcOptions(options =>{// 自定义模型绑定(Newtonsoft.Json)options.ModelBinderProviders.Insert(0, new JsonModelBinderProvider());}).AddNewtonsoftJson();
}

下面来看下 Configure 方法:

这里面有几点重要改动:

1. 将 IHostingEnvironment 改为 IWebHostEnvironment

2. 添加 app.UseRouting();app.UseAuthorization();,注意添加的位置,要放到 UseStaticFiles 的后面

3. UseMvc 改为 UseEndpoints

完整的函数代码:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();app.UseSession();app.UseRouting();app.UseAuthorization();// FineUI 中间件(确保 UseFineUI 位于 UseEndpoints 的前面)app.UseFineUI();app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(name: "area",pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");});}

对于支持 Razor Pages 的项目,这里的 UseEndpoints 代码要改为:

app.UseEndpoints(endpoints =>
{endpoints.MapRazorPages();
});

 

ViewBag 与 Razor Pages 第一次接触

在传统的 Controller/Model/View 的 MVC 架构中,我们可以在控制器中使用 ViewBag 将数据传递到 视图中,虽然 ViewBag 只是字典类 ViewData 的一个动态封装,但是写法更简单:

然而在 Razor Pages 的页面模型类中,却少了对 ViewBag 的支持,因此在 ASP.NET Core 2.2 之前的版本里,我们通过在基类中新增一个 ViewBag 属性来解决:

可以看出,这里的 ViewBag 其实是一个 dynamic 类型,内部存储单元还是 ViewData,这段代码来自:https://forums.asp.net/t/2128012.aspx?Razor+Pages+ViewBag+has+gone+

 

这么一个看似很技巧的东西其实来自微软某位程序员的自(zi)信(da),如果你留意观察,就会发现一个奇怪的逻辑:

  • Controller 基类 和 View 视图中支持 ViewBag

  • Razor Pages的后台模型类中不支持 ViewBag,然后 Razor Pages的页面中支持 ViewBag

说白了,微软的逻辑是:你可以在 Razor Pages 中使用 ViewBag(尽管也可以设置) ,但是别在模型类中设置 ViewBag。

 

这位大虾(DamianEdwards)在一个 Github 的 issue 中提到这样一个观点:

We purposefully didn't add ViewBag because I wanted to discourage its use. As @pranavkm points out you can add it back easily enough if you wish but I don't have plans to add it back to the built-in base class.

原文:https://github.com/aspnet/Mvc/issues/6754 

我带点感情色彩的翻译一下哈:

我就看 ViewBag 不顺眼了,所以故意不添加 ViewBag。并且我也不准备在以后的版本中把 ViewBag 加回来,你非要用的话自己弄吧!

在另一个回复中,DamianEdwards提到了 ViewBag 可能有性能问题:

ViewBag uses dynamic which in our testing introduces a measurable performance impact on the processing of pages or views that use it.

不过,这个决定权不能留给用户自己吗?如果我只是想通过 ViewBag 传递两三个数据,绝对不会遇到什么性能问题,并且这应该是 90% 的应用场景。

 

最终,吐槽归吐槽,代码是你写的,你想咋搞就咋搞。

 

ViewBag 与 Razor Pages 第二次接触

然而,在升级到 ASP.NET Core 3.1 之后,这个地方又报错了。

原因我们前面提过,对 ViewBag 的封装用到了 DynamicViewData,这个类是定义在 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 里面的。而在 ASP.NET Core 3.1 中,微软删除 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal 的公开访问权限。

 

在实际项目中,我们还是要遵循微软的建议,使用 ViewData 而不是 ViewBag。

然而我们的 FineUICore 示例项目有 750 多个页面,很多地方都用到了 ViewBag,为了和之前的版本兼容,我们还是要把 ViewBag 找回来。

既然 DymaicViewData 不见了,就自己创建一个 DymaicViewData:

public class DynamicViewData : DynamicObject
{private ViewDataDictionary ViewData;public DynamicViewData(ViewDataDictionary viewData){ViewData = viewData;}/// <summary>/// 获取所有key/// </summary>public override IEnumerable<string> GetDynamicMemberNames(){return ViewData.Keys;}/// <summary>/// 调用 ViewBag.key; 时执行/// </summary>public override bool TryGetMember(GetMemberBinder binder, out object result){result = ViewData[binder.Name];return true;}/// <summary>/// 调用 ViewBag.key = "value"; 时执行/// </summary>public override bool TrySetMember(SetMemberBinder binder, object value){ViewData[binder.Name] = value;return true;}
}

在后台模型类基类中,调用方法改为:

private DynamicViewData _viewBag;public dynamic ViewBag
{get{if (_viewBag == null){_viewBag = new DynamicViewData(ViewData);}return _viewBag;}
}

小结(文件改动对比图)

综上所述,升级到 ASP.NET Core 3.1 主要改动三个项目文件,其他地方基本没有变化。

为了更直观的查看这三个文件的改动,我们做了下面三幅对比图片(以FineUICore.EmptyProject项目为例)。

1. 项目工程文件(FineUICore.EmptyProject.csproj)

 

2. Program.cs

 

3. Startup.cs

 

 

ASP.NET Core 3.1的确很棒,肉眼可见的快、快、快!

刚把 FineUICore 的官网示例部署到服务器时,管理员是这么给我说的:

 

之前一直没有注意,看来 ASP.NET Core 的性能的确是要好一些。

我对比了 FineUIPro(WebForms) 和 FineUICore(ASP.NET Core) 的在线示例网站,发现 ASP.NET Core 3.1 的确比 WebForms 快多了。

肉眼可见的快、快、快,下面两个动画图片可见一斑:

 

https://pro.fineui.com/

 

 

 

https://core.fineui.com/

 

这两个站点部署在同一台服务器的同一个IIS里面,为了便于区分,FineUICore(ASP.NET Core)为深色主题,FineUIPro(WebForms)为浅色主题。 

注:由于是共享服务器,所以服务器资源在不同时刻会有变化,并且网络环境也是不断变化的,可以在同一时刻(测试间隔小于1s)多次测试两个网站。 

当然每个人测出来的结果会不尽相同,欢迎分享你的测试截图.... 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311522.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WTM系列视频教程:View和Taghelper

文字摘要&#xff1a;“又到了老刘胡说的时间了&#xff0c;今天我们主要聊一下View和TagHelper。在前后端不分离的模式下&#xff0c;View还是很重的一块。”“前几课有朋友反馈说收获很大&#xff0c;也有朋友反应基础内容太多&#xff0c;众口难调啊。这个系列教程还是希望有…

sketch里的ios控件_30个让你眼前一亮的iOS Swift UI控件!

前言笔者接触 iOS 开发有一段时间了&#xff0c;尤其特别喜欢UI部分&#xff0c;特意收集整理了30个让你惊艳的第三方开源控件&#xff08;swift&#xff09;&#xff0c;无论是应用到项目中还是用来学习都能让你大呼过瘾&#xff0c;废话不多说&#xff0c;直接上图上链接&…

Magicodes.IE基础教程之导出Pdf

说明本教程主要说明如何使用Magicodes.IE.Pdf完成Pdf收据导出要点导出PDF数据自定义PDF模板导出单据如何批量导出单据导出特性说明PdfExporterAttributePdfExporterAttribute特性用于设置Pdf导出的总体设置&#xff0c;比如方向、纸张等。主要包含如下设置&#xff1a;Name:文档…

mysql查询语句能否让一个字段不显示出来_天天写order by,你知道Mysql底层如何执行吗?

作者&#xff1a;不才陈某前言在实际的开发中一定会碰到根据某个字段进行排序后来显示结果的需求&#xff0c;但是你真的理解order by在 Mysql 底层是如何执行的吗&#xff1f;假设你要查询城市是苏州的所有人名字&#xff0c;并且按照姓名进行排序返回前 1000 个人的姓名、年龄…

排序-总结

排序 排序:重点在于对于记录的关键字进行排序,得到按关键字有序记录序列 分为: A.内部排序: 排序过程在内存中进行 B.外部排序: 待排序记录数据量过大,需要借助外部存储设备 排序的稳定性:排序后有相同关键字的记录顺序不变就是稳定的排序 插入类排序: 1.直接插入排…

.NET Core开发实战(第10课:环境变量配置提供程序)--学习笔记

10 | 环境变量配置提供程序&#xff1a;容器环境下配置注入的最佳途径环境变量的配置提供程序主要适应场景&#xff1a;1、在 Docker 中运行时2、在 Kubernetes 中运行时3、需要设置 ASP.NET Core 的一些内置特殊配置时环境变量和命令行这两个提供程序在早期是没有容器化的&…

dotnetcore3.1 WPF 实现多语言

dotnetcore3.1 WPF 实现多语言Intro最近把 DbTool 从 WinForm 迁移到了 WPF&#xff0c;并更新到了 dotnet core 3.1&#xff0c;并实现了基于 Microsoft.Extensions.Localization 实现了基本的多语言支持。下面来分享一下如何来实现服务注册如果不熟悉如何在 WPF 中使用依赖注…

卸载chrome_Chrome 浏览器必备“扩展管理工具”,一键管理 Chrome 扩展

前言丰富的扩展插件可以说是 Chrome 浏览器的灵魂了&#xff0c;但是扩展安装的多了&#xff0c;难免会引起卡顿&#xff0c;而且每次打开/关闭扩展都要进入扩展程序页面&#xff0c;切换起来很不方便。下面分享的三款 Chrome 扩展管理工具&#xff0c;可以让我们更便捷地管理 …

面试官:你连HTTP请求Post和Get都不了解?

IT界知名的程序员曾说&#xff1a;对于那些月薪三万以下&#xff0c;自称IT工程师的码农们&#xff0c;其实我们从来没有把他们归为我们IT工程师的队伍。他们虽然总是以IT工程师自居&#xff0c;但只是他们一厢情愿罢了。此话一出&#xff0c;不知激起了多少(码农)程序员的愤怒…

运维进化论:微盟“删库跑路”给我们的启示

作者&#xff1a;茹炳晟&#xff0c;软件质量和研发工程效能专家事件背景微盟是国内移动互联网营销引领者&#xff0c;中国最大的微信公众智能服务平台&#xff0c;基于微信为企业提供开发、运营、培训、推广一体化解决方案&#xff0c;帮助企业实现线上线下互通&#xff0c;社…

拦截器如何获取@requestbody_分布式系统中如何优雅地追踪日志(原理篇)

分布式系统中日志追踪需要考虑的几个点&#xff1f;需要一个全服务唯一的id&#xff0c;即traceId&#xff0c;如何保证&#xff1f;traceId如何在服务间传递&#xff1f;traceId如何在服务内部传递&#xff1f;traceId如何在多线程中传递&#xff1f;我们一一来解答&#xff1…

.NET Core开发实战(第11课:文件配置提供程序)--学习笔记

11 | 文件配置提供程序&#xff1a;自由选择配置的格式文件配置提供程序Microsoft.Extensions.Configuration.IniMicrosoft.Extensions.Configuration.JsonMicrosoft.Extensions.Configuration.NewtonsoftJsonMicrosoft.Extensions.Configuration.XmlMicrosoft.Extensions.Conf…

前端demo_【前端3分钟】Script Error产生的原因和解法

Script Error对于前端开发者相信都不陌生&#xff0c;而且由于没有具体错误堆栈和代码行列号&#xff0c;成为可能是最神秘的错误之一。下面介绍Script Error产生的原理和解决办法。1、Script Error是如何产生的跨域资源引用假如&#xff1a;abc.com 下的页面引用了属于 http:/…

基于Abp VNext框架设计 - Masstransit分布式消息

abp 通过IDistributedEventBus接口集成自IEventBus实现分布式事件消息的发布订阅。IEventBus在什么时机触发PublishAsync?当前UnitOfWork完成时&#xff0c;触发IEventBus的PublishAsync在没有事务环境下&#xff0c;同步调用IEventBus的PublishAsyncabp 默认实现基于RabbitMq…

16进制数用空格分开 tcp_面试时,你是否被问到过TCP/IP协议?

点击蓝字关注我们看到这句话&#xff0c;有没有感到很熟悉呀&#xff1f;相信很多人在面试的时候都被要求&#xff0c;很多人会觉得我们在实际开发中一般用不到这些知识&#xff0c;所以对这些东西不屑一顾。但是小编认为想要成为一个完美的网工,那么对这些基础知识必须要有一定…

直接使用汇编编写 .NET Standard 库

前言Common Language Runtime&#xff08;CLR&#xff09;是一个很强大的运行时&#xff0c;它接收 Common Intermediate Language&#xff08;CIL&#xff09; 的输入并最终产生机器代码并执行。CIL 在 CLR 上相当于 ASM 汇编代码的存在。CLR 之上的语言 C#、F#、VB.NET 等语言…

[蓝桥杯2016决赛]七星填数-next_permutation枚举

题目描述 如下图所示&#xff1a; 在七角星的14个节点上填入1~14 的数字&#xff0c;不重复&#xff0c;不遗漏。要求每条直线上的四个数字之和必须相等。 图中已经给出了3个数字。请计算其它位置要填充的数字&#xff0c;答案唯一。 填好后&#xff0c;请提交绿色节点的4个数…

系统蓝屏的几种姿势,确定不了解下么?

前言在 蓝屏&#xff08;BSOD&#xff09;转储设置&#xff0c;看本文就够了&#xff01;这篇文章里比较详细的介绍了蓝屏转储设置。做好设置后&#xff0c;我们就可以在需要的时候使系统蓝屏了。本文介绍几种使系统蓝屏的办法&#xff0c;当然肯定还有其它办法&#xff0c;如果…