[干货分享] .NET项目迁移到.NET Core操作指南

这篇文章,汇集了大量优秀作者写的关于".NET迁移到.NET Core"资料文章以及微软官方教程文档。也是我在迁移公司框架项目到.NET Core和.NET Standard时遇到的问题,并将相关资料整理成这篇文章。记录如何一步一步把项目迁移到.NET Core。 

为什么要从.NET迁移到.NET Core?

.NET Core提供的特性

  • 开源协议

  • .NET Core从属于.NET基金会,由微软进行官方支持。使用最宽松的MIT和Apache 2开源协议,文档协议遵循CC-BY。这将允许任何人任何组织和企业任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版权和许可提示,后者协议将会除了为用户提供版权许可之外,还有专利许可,并且授权是免费,无排他性的(任何个人和企业都能获得授权)并且永久不可撤销,用户使用.NET Core完全不用担心收费问题,你可以很自由的部署在任何地方.

  • 轻量级、跨平台

  • 组件化、模块化、IOC+Nuget、中间件

  • 高性能

  • 统一了MVC和WebAPI编程模型

  1. 比如:NET Core 中MVC 和Web API 直接或间接继承同一个基类 ControllerBase,提供可使用的API也一致化

  2. 比如:旧NET时代,写全局filter需要针对MVC 和Web API 分别编写代码,但在ASP.NET Core,直接使用一套中间件代码即可

  • 可测试性

  • 微服务、容器化支持

  • 标准化 .NET API 规范- .NET STANDARD,整体架构如下图:

  • image.png

    .NET Core性能提升

    • TechEmpower机构

      image.png

      TechEmpower机构会定期对各语言主流的web框架做性能测试

      https://www.techempower.com/benchmarks/

    • 博客园博主、微软MVP – 杨晓东,做的 “Hello World”性能测试

    ASP.NET Core 1.1性能对比评测(ASP.NET,Python,Java,NodeJS)

    编号

    对比方

    系统环境

    宿主环境

    测试结果(QPS)

    1

    ASP.NET Core vs ASP.NET Core

    Windows

    Kestrel vs IIS

    45.6k vs 15.2k

    2

    ASP.NET Core vs ASP.NET

    Windows

    IIS vs IIS

    15.2k vs 18.2k

    3

    ASP.NET Core vs ASP.NET

    Windows

    Kestrel vs IIS

    45.6k vs 18.2k

    4

    ASP.NET Core vs Python Django

    Linux

    Kestrel vs uwsgi

    26.7k vs 1.57k

    5

    ASP.NET Core vs Java Servlet

    Linux

    Kestrel vs Tomcat

    26.7k vs 18.3k

    6-1

    ASP.NET Core vs NodeJS Express

    Linux

    Kestrel vs self host

    26.7k vs 15.6k

    6-2

    ASP.NET Core vs NodeJS Koa

    Linux

    Kestrel vs self host

    26.7k vs 17.5

    性能测试工具:

        微软出品:Benchmarks

        https://github.com/aspnet/benchmarks

    其他阅读:

       是什么优化让 .NET Core 2.0性能飙升?

        .NET Core 3中的性能提升(译文)

        Java(11,12) 与 .NET Core(2.2,3.0)的性能对比测试 

    .NET如何迁移到.NET Core?

    迁移工作量评估(API兼容性分析)

    度量.net framework 迁移到.net core的工作量

    可移植性分析工具:.NET Portability Analyzer

     【Cli 版本】  【Visual Studio Extension 版本】

      评估会给出类似如下报告:

      .NET Standard Versions

    迁移方案制定

    微软官方《组织项目以支持 .NET Framework 和 .NET Core》文章中,有介绍两种迁移方案:

    方案一、将现有项目和 .NET Core 项目合并为单个项目(多目标框架)

    方案二、将现有项目和新的 .NET Core 项目分离(拷贝到新项目)   

    通过类名、命名空间,查询API的实现信息

    迁移过程中,有类库命名空间被调整,nuget归属包被调整,具体类库在.NET Core哪个版本中被实现也不是很清楚,通过下面两个查询助手,即可解决这些问题。

    1、查询命名空间、类库在哪个nuget package包中定义(第一次查询比较慢)

    2、查询 NET API 在各版本中实现

    结果图如下:

     

    类库项目、应用项目如何选择框架类型


    • .NetStandard;.netCore;FX(.NetFrameWork)之间引用关系

    在 .NET Standard 2.0中,我们使在 .NET Standard 库中通过一个兼容层去引用已有的 .NET Framework 的库成为可能。当然,这只对那些只使用了适用于 .NET Standard API 的 .NET Framework 库有效。

    FX引用.NetCore:不通过

    .NetStandard引用.NetCore:不通过 

    .NetCore引用FX:通过

    .NetCore引用.NetStandard:通过

    .NetStandard引用FX:通过

    FX引用.NetStandard:通过

     

           ASP.NET Core可以在“.NET Framework 和 .NET Core”上运行,但ASP.NET Core 3.0 以及更高版本只能在 .NET Core 中运行

    具体参见:

      【译】介绍 .NET Standard -- 【原文】

      关于.net core 和 .net fx相互引用的问题

    .NetStandard;.netCore;FX(.NetFrameWork)之间引用关系

    • 项目支持多目标框架

    支持多目标框架,并解决第三方库引用差异的问题(在 csproj 文件中指定包含条件)

    目标框架名称列表 (命名全小写)

    如何调试多目标框架类库?

    NET Standard/Core项目使用条件判断输出多版本xml注释文档

    • 多目标框架中共享代码方案

    • 【首选】.NET Standard,需要目标SDK支持对应的 .NET Standard 版本。

    • 共享项目。直接共享了源码,只要在目标项目中指定了条件编译符,那么源码便能针对各种不同的目标框架进行分别编译。

    • [add as link]使用链接共享 Visual Studio 中的代码文件

    • 条件编译符号 (命名全大写)

    指令: #if #elif #else #endif (||、&&、!)

    因为目标框架提供的API不相同。故必要时可添加条件编译符号以便支持不同的运行时版本。

    微软有针对各个目标框架有预定义预处理器符号,vs编译时会自动识别到这些框架条件编译符号。

    .NET Framework 4.5 --> NET45

    .NET Framework 4.6 --> NET46

    .NET Framework 4.6.1 --> NET461

    .NET Standard 1.0 --> NETSTANDARD1_0

    .NET Standard 1.6 --> NETSTANDARD1_6

    .NETCOREAPP 2.0 --> NETCOREAPP2_0

    参考:

    #if指令文档

    如何将条件编译符号(DefineConstants)传递给m****uild

     

    迁移到.NET Core,但只运行在windows平台上

    使用 Windows 兼容性包将代码移植到 .NET Core

    如何:将 Windows 窗体桌面应用程序移植到 .NET Core

    如何:将 WPF 桌面应用移植到 .NET Core 

    兼容.NET Core或.NET Standard API

    迁移HttpHandler与HttpModule到 ASP.NET Core 中间件

    .NET CORE 2.0 踩坑记录之ConfigurationManager

    .NET Core/Standard 2.0 编译时报“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”错误

    ASP.NET Core开发之HttpContext

    .net core 使用JsonConvert替代JavaScriptSerializer

    ASP.NET Core 中重复读取 Request.Body 的正确姿势

    JsonRequestBehavior在core中被移除的问题


    • [ASP.NET Core]core中不会抛出AllowGet异常,对于DenyGet则使用[HttpPost]代替

    https://stackoverflow.com/questions/38578463/asp-net-core-the-name-jsonrequestbehavior-does-not-exist-in-the-current-cont

    https://stackoverflow.com/questions/8464677/why-is-jsonrequestbehavior-needed?r=SearchResults

    获取ASP.NET Core中的Web根路径和内容根路径(移除的MapPath)

    为什么我的会话状态在ASP.NET Core中不工作了?

    由于ASP.NET Core 2.1中引入的Cookie同意和非必要cookie的GDPR功能引起。(GDPR,即General Data Protection Regulation,《通用数据保护条例》)


    在ASP.NET4.5和ASP.NET Core中共享cookies认证信息(加解密方式不一致问题)

       .NET跨平台之旅:ASP.NET Core从传统ASP.NET的Cookie中读取用户登录信息

       开源方案:[git]idunno.CookieSharing

    ASP.NET Core如何获取客户端IP地址(被移除的ServerVariables对象)

    如何获取项目依赖的所有程序集

       方案一:AppDomain.CurrentDomain.GetAssemblies(),此办法不能获取到所有依赖的程序集,因为.Net有延迟加载程序集机制

       方案二:适用于传统ASP.NET项目,System.Web.Compilation.BuildManager.GetReferencedAssemblies();

       方案三:适用于ASP.NET Core项目,DependencyContext.Default.CompileLibraries,具体代码参考下面



    var dlls = DependencyContext.Default.CompileLibraries

        .SelectMany(x => x.ResolveReferencePaths())

        .Distinct()

        .Where(x => x.Contains(Directory.GetCurrentDirectory()))

        .ToList();

    foreach (var item in dlls)

    {

        try

        {

            AssemblyLoadContext.Default.LoadFromAssemblyPath(item);

        }

        catch (System.IO.FileLoadException loadEx)

        {

        } // The Assembly has already been loaded.

        catch (BadImageFormatException imgEx)

        {

        } // If a BadImageFormatException exception is thrown, the file is not an assembly.

        catch (Exception ex)

        {

        }

    }

    参考:

            AppDomain.CurrentDomain.GetAssemblies()

            Is there an alternative for BuildManager.GetReferencedAssemblies() in ASP.NET Core?

    .NET Core 2.0迁移System.Runtime.Caching

    .NET Core 2.0升级到3.0实战方案

      从.NET CORE2.2升级到3.0过程及遇到的一些问题

    迁移EF框架

    【微软官方】从 EF6 到 EF Core的迁移系列

    【微软官方】EF Core 版本升级迁移系列 

    修改为 ASP.NET Core 风格的应用

      按照上面的方式修改API兼容性后,框架类库可以顺利迁移到.NET Core,编译通过,代码运行也正常。但是ASP.NET Core风格的应用,其写法也是有很多变化的。具体参考下面文档:

    将传统 ASP.NET 应用迁移到 .NET Core

    【微软官方】ASP.NET 迁移到 ASP.NET Core教程系列

    【微软官方】ASP.NET Core 版本升级迁移系列


    推荐阅读:

      .NET Core 学习资料精选:入门

      .NET Core 学习资料精选:进阶