将 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,一经查实,立即删除!

相关文章

[蓝桥杯2016初赛]密码脱落

题目描述 X星球的考古学家发现了一批古代留下来的密码。这些密码是由A、B、C、D 四种植物的种子串成的序列。 仔细分析发现&#xff0c;这些密码串当初应该是前后对称的&#xff08;也就是我们说的镜像串&#xff09;。 由于年代久远&#xff0c;其中许多种子脱落了&#xff0c…

python数据类型及使用方法_python 基本数据类型及方法

python的基本数据类型1.字符串str1.1作用不可变类型。主要是表示文本的数据类型&#xff0c;形容事物的属性。Python中最常用的类型之一。1.2方式主要有四种方式&#xff1a;文本内容。用单引号将内容包括。主要适用于单行。"文本内容"。用法同单引号。主要适用于单行…

AVL添加平衡二叉树,是一种二叉排序树,其中每个结点的左子树和右子树的高度差至多等于1。-icoding-数据结构-C-typedef struct node{ int val;

AVL添加 平衡二叉树&#xff0c;是一种二叉排序树&#xff0c;其中每个结点的左子树和右子树的高度差至多等于1。 它是一种高度平衡的二叉排序树。现二叉平衡树结点定义如下&#xff1a; typedef struct node {int val;struct node *left;struct node *right;struct node *par…

[蓝桥杯2015决赛]密文搜索

题目描述 福尔摩斯从X星收到一份资料&#xff0c;全部是小写字母组成。 他的助手提供了另一份资料&#xff1a;许多长度为8的密码列表。 福尔摩斯发现&#xff0c;这些密码是被打乱后隐藏在先前那份资料中的。 请你编写一个程序&#xff0c;从第一份资料中搜索可能隐藏密码的位…

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;直接上图上链接&…

堆辅助函数二叉堆是完全二叉树或者是近似完全二叉树。二叉堆有两种:最大堆和最小堆。“最小堆”的定义如下:typedef struct _otherInfo-icoding-C

堆辅助函数 二叉堆是完全二叉树或者是近似完全二叉树。二叉堆有两种&#xff1a;最大堆和最小堆。 最大堆(大顶堆)&#xff1a;父结点的键值总是大于或等于任何一个子节点的键值&#xff0c;即最大的元素在顶端&#xff1b; 最小堆(小顶堆)&#xff1a;父结点的键值总是小于或…

【要闻】Kubernetes不适合发行版模式、Windows业务无法达到营收指引

评论&#xff1a;发行版模式适用于Linux但不适用于Kubernetes人们经常将Kubernetes比喻成一种革命&#xff0c;众多相关公司纷纷涌现以利用其发展趋势证明了这一点。在从前&#xff0c;希望在Linux领域中赚钱的公司拿走了核心&#xff0c;将其与最佳实践和喜爱的应用程序捆绑在…

[蓝桥杯2015决赛]积分之迷-枚举(水题)

题目描述 小明开了个网上商店&#xff0c;卖风铃。共有3个品牌&#xff1a;A&#xff0c;B&#xff0c;C。 为了促销&#xff0c;每件商品都会返固定的积分。 小明开业第一天收到了三笔订单&#xff1a; 第一笔&#xff1a;3个A 7个B 1个C&#xff0c;共返积分&#xff1a;31…

python车辆识别硬件_Opencv python之车辆识别项目

图片车辆识别根据文章搭建好环境后开始进行做项目linkimport sysimport cv2from PyQt5.QtGui import *from PyQt5.QtWidgets import *from PyQt5.QtGui import QIcon, QPalette, QPixmap, QBrush, QRegExpValidatorclass mainWin(QWidget):def __init__(self):""&quo…

[蓝桥杯2016决赛]反幻方-next_permutation枚举

题目描述 我国古籍很早就记载着 2 9 4 7 5 3 6 1 8 这是一个三阶幻方。每行每列以及对角线上的数字相加都相等。 下面考虑一个相反的问题。 可不可以用 1~9 的数字填入九宫格&#xff0c;使得&#xff1a;每行每列每个对角线上的数字和都互不相等呢&#xff1f; 这应该能做到。…

堆初始化-二叉堆一般用数组来表示。例如,根节点在数组中的位置是0,第n个位置的子节点分别在2n+1和 2n+2-icoding-void init_min_heap(PMinHeap pq, int

堆初始化 二叉堆一般用数组来表示。例如&#xff0c;根节点在数组中的位置是0&#xff0c;第n个位置的子节点分别在2n1和 2n2。 因此&#xff0c;第0个位置的子节点在1和2&#xff0c;1的子节点在3和4。以此类推。这种存储方式便于寻找父节点和子节点。 在二叉堆上可以进行插入…

管理学定律--墨菲定律

如果有两种或两种以上的方式去做某件事情&#xff0c;而其中一种选择方式将导致灾难&#xff0c;则必定有人会做出这种选择。根本内容是&#xff1a;如果事情有变坏的可能&#xff0c;不管这种可能性有多小&#xff0c;它总会发生。一、墨菲定律来源1949年&#xff0c;一位名叫…

毕滢python小咖养成计划百度云_学技树-Python小咖养成计划

1.计算机操作基础.mp42.Python下载与配置.mp43.变量的概念.mp44.函数的调用和定义.mp45.数据的类型.mp46.字符串.mp47.if条件判断.mp48.while循环.mp49.for循环.mp410.列表.mp411.字典.mp412.类的概念.mp413.类的使用.mp4代码管理及答疑系统.pdf①项目一&#xff1a;数据分析(已…

[蓝桥杯2016决赛]平方末尾-数论,枚举

题目描述 能够表示为某个整数的平方的数字称为“平方数”。比如&#xff0c;25,64 虽然无法立即说出某个数是平方数&#xff0c;但经常可以断定某个数不是平方数。 因为平方数的末位只可能是&#xff1a;[0, 1, 4, 5, 6, 9] 这6个数字中的某个。 所以&#xff0c;4325435332必然…

数据结构-排序-分配类排序-知识点总结归纳3

分配类排序:核心是分配和收集,利用关键字的优先级进行排序的思想 高位优先排序:比如桥牌,先比较花色在比较面值;比如学号,比较级,院,班,号; 低位优先排序: 链式基数排序 思想:基于"分配"和"收集"的操作, 将单关键字转化为多关键字排序 将链表作为存储结…

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.直接插入排…