ASP.NET Core是微软新推出支持跨平台、高性能、开源的开发框架,相比起原有的ASP.NET来说,ASP.NET Core更适合开发现代应用程序,如跨平台、Dorker的支持、集成现代前端开发框架(如npm、bower、gulp等等)。另外相比ASP.NET它的性能更好,还内置了依赖注入等功能对开发方式进行了优化。但它们之间也有很多相同或相似的地方,如都使用C#进行开发、都提供了MVC、Entity Framework、Identity等组件来快速构建应用程序。
本文将通过迁移一个简单的ASP.NET应用为例,来介绍ASP.NET与ASP.NET Core之间的异同,其主要内容有:
● .Net Core & ASP.NET Core & .Net Standard
● ASP.NET应用迁移分析
● 类库项目迁移
○ 通过创建新项目完成类库迁移
○ 迁移EntityFramework
● 迁移ASP.NET MVC
○ 创建一个新的ASP.NET Core MVC项目
○ 路由迁移
○ 过滤器迁移
○ 依赖注入迁移
○ Web静态资源及View迁移
● 小结
注:本文使用的VS2017为15.6.4版本,.Net Core SDK版本为2.1.103。
.Net Core & ASP.NET Core & .Net Standard
在介绍如何迁移ASP.NET应用之前,先了解一下新框架.Net Core和ASP.NET Core,.Net Core是一个全新开发平台,新的运行时、SDK、类库、工具(编译工具、项目模板生成工具等等),而ASP.NET Core则是基于.Net Core的一个Web应用开发框架,它们的关系实际上与.Net Framework和ASP.NET是一样的。
但是在使用.Net开发的时候出现了一个新的名词.Net Standard,.Net Standard是一个可用于所有.Net程序的API标准,换句话说就是如果使用.Net开发的API(类库)符合.Net Standard,那么该类库将可以用于所有的.Net应用。如下表所示,如果开发的类库是以.Net Standard2.0标准开发的,那么该类库将可应用到.Net Core2.0、.Net Framework4.6.1(需要.NET Core2.0的SDK支持)、Mono5.4、Xamarin、UWP等平台的应用上。
更多关于.Net Standard的内容可参考文档:https://docs.microsoft.com/en-us/dotnet/standard/net-standard
ASP.NET应用迁移分析
.Net Core虽然是一个全新的开发平台(新运行时、新SDK、新类库、新工具),但是它毕竟是以.Net Framework为基础,所以对于部分API来说它仍然是参照且兼容.Net Framework的,所以在迁移.Net Core应用时可以先对代码进行分析。
1、使用工具分析代码:
有一个名为.Net Portability Analyzer的工具专门用于分析代码和引用程序集在.Net不同平台上的支持情况,该工具可以在VS的拓展管理中搜索并安装,或者到页面上下载VS插件双击安装(https://marketplace.visualstudio.com/items?itemName=ConnieYau.NETPortabilityAnalyzer):
安装完成后在VS的解决方案窗口中右键解决方案或者项目就可以看到下图两个菜单项,分别用于分析程序集的可移植性和对移植分析器的配置:
移植分析器的配置主要是对目标平台和报表输出类型进行配置:
下图是对My Blog应用进行可移植性分析的Excel报表(部分):
可移植性总结:
问题细节:
缺失的程序集:
注:没找到更多关于缺少程序集的解释,不确定是无法解析还是无兼容性,本文暂时将这些程序集理解为仅支持.Net Framework平台。
从分析报告中可以看出,除了MVC项目,其它类库项目与.Net Core或者.Net standard标准的兼容程度均为100%。
2、根据实际情况对项目引用进行分析:
工具对代码的分析仅可参考,毕竟使用.Net Framework开发的应用可能引用了很多第三方类库,这些类库可能不支持其它平台,有些类库可能支持,但是对于原有版本有了很多Break Changes,使用方法与原先不一致了,所以在进行代码迁移之前对项目引用进行分析,从技术上分析代码迁移是否可行。
本例中仓储的实现依赖了Entity Framework、EF MySQL、Autofac、Identity等组件,这些组件在.Net Core下也是有相应实现,虽然API会有改动,但技术上是没有问题的可以迁移。接下来就开始介绍如何完成迁移。
类库项目迁移
现在.Net Core项目与.Net Framework项目一样都是使用MSBuild格式的csproj文件来管理项目的相关属性,如名称、版本号、包依赖、项目依赖等等,所以实际上项目的迁移最大的改动就是将csproj的内容改为.Net Core的即可(.Net Core的csproj文件详情参考文档:https://docs.microsoft.com/en-us/dotnet/core/tools/csproj),改动csproj文件有两种方法,如果熟悉文件格式,那么直接改动原有文件即可,如果不熟悉那么可以通过重新创建项目的方式,让VS来完成创建/修改工作。
通过创建新项目完成类库迁移
本文将通过重新创建项目的方式来完成项目迁移,以保证csproj配置文件的正确性。
首先通过VS创建一个.Net Standard的类库项目:
然后把相应的代码复制到新建项目的目录下,删除不存在的命名空间即可。
注:.Net Core会自动识别项目目录下的代码文件,而原来的.Net Fx项目需要在csporj文件中引入,所以这里直接复制代码文件即可识别到项目中。
迁移EntityFramework
本例程序中用于实现仓储的类库依赖了EF,而实现MySQL EF的类库还依赖了My SQL的EF相关组件。
另外随着.Net Core的推出,EF也推出了EFCore,另外新版本的.Net大量引入了Options模式来对程序进行配置,关于Options模式可参考文档:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1
中文文档:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/configuration/?tabs=basicconfiguration
所以在迁移EF的时候,除了创建新的项目,还需要安装新的Nuget包并且修改相应的配置代码:
1. 安装EFCore组件:
安装Microsoft.EntityFrameworkCore:
2.处理EFCore的配置:
EFCore配置文档:https://docs.microsoft.com/zh-cn/ef/core/miscellaneous/configuring-dbcontext
注:EFCore针对不同数据库的配置信息通过DbContextOptions对象完成,所以构造方法不再是一个简单的连接字符串,另外EFCore提供了针对ASP.NET Core容器的依赖注入方法,为了利用依赖注入可以把DbContext配置交由ASP.NET Core项目完成,包括对不同数据源的支持。
通过上面的方法即可把例子中的类库项目完成迁移,接下来进行MVC项目的迁移工作。
迁移ASP.NET MVC
ASP.NET Core是一项变革,除了跨平台之外,它还改变了原先ASP.NET的思想和开发方式,如MVC及API的Controller合二为一、拥抱现代前端开发方式方法、Dorcker支持等,接下来将通过介绍其迁移过程来了解ASP.NET与ASP.NET Core的异同。
创建一个新的ASP.NET Core MVC项目
相对与类库来说MVC项目的迁移要复杂的多,因为新的ASP.NET在项目文件结构、程序启动、开发方式等方面都有了区别,这里仍然使用创建新项目的方式完成ASP.NET MVC应用的迁移:
创建一个ASP.NET Core MVC应用:
下面是新项目的目录结构:
ASP.NET Core MVC与原先ASP.NET MVC类似核心仍然是Controllers、Models、Views三个目录,另外通过wwwroot目录对HTML资源进行了整合、配置文件变更为Json格式、删除了Global.asax取而代之的是Program.cs和Startup.cs文件。
ASP.NET开发的Web应用程序需要IIS作为宿主才可以运行,而ASP.NET Core作为一种可跨平台的Web应用开发框架其应用必定是与IIS完全解耦的,所以它的启动方式也完全不一样。
ASP.NET Core中引入了Program类型,如Console应用一样通过Main方法来运行程序,而ASP.NET Core的Main方法主要内容是指明一个Startup类型完成Web服务器的创建。而Startup类型则负责了整个应用的配置和HTTP请求管道搭建的任务,所以首先要完成的工作就是将原先Global及Owin Startup文件中的内容移植到Startup文件中,下面就开始详细介绍ASP.NET Core MVC的变化及迁移方法。
MVC除了包含Controller、Model、View等文件外,还需要进行路由、过滤器等功能配置,所以首先需要将原项目的相关文件(controller、model、view等注:因为原项目和ASP.NET Core的MVC都依赖Identity实现用户管理功能,所以涉及到用户管理的部分不需要复制)复制到新项目中,修改命名空间引用如:System.Web.Mvc->Microsoft.AspNetCore.Mvc并修复其它命名空间引用错误。
接下来完成其它几个重要方面的迁移。
路由迁移
将原有的路由配置包含Area的路由配置转移至Startup类型的Configure方法中:
注:本例存在Controller名称重名情况,但ASP.NET Core MVC没有提供如ASP.NET中通过命名空间区别的方式区别Controller重名,本例通过修改名称解决问题,如需命名空间区分Controller可参考:https://stackoverflow.com/questions/34306891/restrict-route-to-controller-namespace-in-asp-net-core
过滤器迁移
全局过滤器的配置则是由原来的通过FilterConfig对象注册改为Startup的ConfigureServices方法中对MVC进行配置:
依赖注入迁移
ASP.NET Core内置了依赖注入功能,甚至一些组件都提供了专门的拓展方法将其服务添加到容器中,如EFCore、Identity、MVC。
上图为ASP.NET Core默认的为将DbContext、Identity以及MVC相关服务添加到容器的代码,除此之外为了顺应依赖注入思想,这里将原有代码的仓储和服务类型均注册到容器中,其依赖通过构造方法进行注入。
仓储代码:
业务代码:
控制器代码:
服务注册代码:
注:本例中实现依赖的是实现而非抽象,这不符合依赖倒置原则,所以此处仅作为ASP.NET Core依赖注入使用示例。另外为了让EFCore支持MySQL,所以需要在项目中添加Pomelo.EntityFrameworkCore.MySql组件:
Web静态资源及View迁移
ASP.NET的页面是基于HTML实现的,一个ASP.NET的页面除了HTML代码外还会引用一些外部静态资源,如css、js、image、font等内容,而ASP.NET中专门提供了Bundle技术来管理这些资源(可参考:《ASP.NET没有魔法——ASP.NET MVC界面美化及使用Bundle完成静态资源管理》),那么ASP.NET Core是如何管理这些资源的呢?
首先要处理ASP.NET Core中静态文件的访问问题,在ASP.NET中由于它依赖IIS,而静态文件访问已经被IIS处理了,所以程序中无需关心,但ASP.NET Core不一样,需要在其请求管道中添加相应的处理中间件:
注:ASP.NET Core项目模板默认添加该中间件。
对于静态资源的管理ASP.NET Core通过bundleconfig.json配置文件进行配置取代了原先的BundleConfig类型。把原先的资源文件复制到ASP.NET Core的wwwroot目录下,然后在bundleconfig.json文件下进行配置,如下图(部分):
完成配置后还需要在项目中添加一个BuildBundlerMinifier的组件:
引入BuildBundlerMinifier后编译项目就会触发资源绑定和最小化操作:
注:和ASP.NET不同,Core里面的静态资源管理是在编译过程中处理的,并且通过一个json配置文件完成处理定义,除了BuildBundlerMinifier外还可以使用Gulp等工具完成资源的优化,关于Gulp的使用可参考:https://docs.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?view=aspnetcore-2.0&tabs=visual-studio%2Caspnetcore2x#consume-bundleconfigjson-from-gulp
完成静态资源迁移后因为Bundle机制的改变还需要对View中资源引用进行修改(ASP.NET Core中不再提供@Scripts和@Styles类型来渲染样式和脚本引用):
运行结果:
小结
.Net Core是一个新的开发框架,2.0版本的.Net Core已经相对完善,本文介绍了一个简单的ASP.NET MVC迁移至.Net Core的例子,从例子中可以看出新的开发平台已经实现了原有的所有功能和解决方案,甚至在原有基础上进行了改进。另外.Net Core作为新框架它是开源的并且相对于.Net Framework来说它的文档更全面(中文文档相对落后),所以.Net Core更容易学习和使用。
对于迁移来说,首先还是看需求和目的,为什么要进行迁移?为了容器化?跨平台部署?在真实项目中迁移一个项目是非常复杂且具有风险的,所以如果要进行迁移需要慎重考虑,考虑迁移是否是最好的解决方案。
参考:
http://crbtech.in/Dot-Net-Training/9-things-know-converting-asp-dot-net-to-dot-net-core/
https://docs.microsoft.com/en-us/dotnet/core/tools/project-json-to-csproj
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1
https://docs.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?view=aspnetcore-2.1&tabs=visual-studio%2Caspnetcore2x
https://stackoverflow.com/questions/34306891/restrict-route-to-controller-namespace-in-asp-net-core
https://docs.microsoft.com/en-us/aspnet/core/migration/proper-to-2x/?view=aspnetcore-2.1