源宝导读:明源云ERP的底层架构正在向.Net Core跨平台迁移,我们在过程中遇到了部分不兼容的问题。本文将介绍技术团队如何解决.Net Core与已有MVC框架不兼容问题的解决方案。

一、背景

云ERP的建模平台是基于.NET Framework构建的,在向.NET Core迁移的过程中会遇到各种问题,向下兼容是一定要考虑的,框架本身的特性兼容交给微软,但是还有很多的特性可能是旧版建模平台需要支持的特性,比如多参数绑定、服务工厂Controller激活。今天就聊聊在向.NET Core迁移时如何兼容以上两个特性。

二、概念解释

  • 服务工厂

    • 云ERP的服务工厂是建模平台的内部服务管理实现,用于创建ERP各个领域服务类实例,在创建服务对象的过程中会进行加工,根据二开模式(Before/After/Override)动态创建携带插件方法的代理类型,以达到易二开的技术特性。

  • 应用服务

    • 应用服务是云ERP的入口,它们是由一系列后缀名为AppService的Class组成的,概念上相当于MVC的Controller,作用也一样。

  • 自定义路由

    • 云ERP的路由中添加了命名空间地址,官方的模板格式无法满足,本文利用ControllerModelConvention在Apply时为每一个Action批量配置路由。路由格式: `api/ {controller.ControllerType.FullName} /{action.ActionName}.aspx`

  • Controller激活

    • 云ERP也是基于MVC构建的,Controller也是服务,也是需要可扩展,自然需要通过服务工厂去创建,这就需要找到.NET Core MVC中Controller激活的时机,使用服务工厂创建替换掉默认的类实例化过程。

  • 多参数绑定

    • .NET Core MVC 中天生是不支持将[FromBody]数据源绑定到Action的多个参数上的。这一特性在微软官方文档中有解释(参考:微软对FromBody的参数绑定限制说明)。由于这个限制,我们必须在向.NET Core MVC迁移时尝试解决这个问题,思路与Controller激活的差不多,就是找到参数绑定的默认实现,替换掉它。

为了大家能统一语言,请提前了解下.NET Core MVC的基本特性,这里就不再阐述,需要了解的读者请点击传送门。

三、面临的问题

让MVC路由到云ERP的AppService

.NET Framework MVC 升级到 .NET Core MVC 在实现原理上有很大不同,由服务管线变成了中间件管道,无法直接使用HttpHandler实现了,必须重新实现Controller路由到激活的过程。

那么将面临两个问题:

  1. 自定义路由,首先要能让MVC认知AppService并能按照云ERP的模板规范进行路由。

  2. 路由到AppService后激活的方式得用服务工厂 ServiceFactory来创建,这样才能兼容二开的插件模式。(注:服务工厂中创建的是AppService的代理类的实例,携带二开定义的插件方法)

支撑多参数绑定

云ERP多参数绑定的解决方案是利用的ClownFish.net框架中的  ClownFish. Web.Serializer. JsonnetDataProvider 来解决的(ClownFish.net明源云的架构师FishLi多年前的作品,已在Github上开源)。

迁移到.NET Core MVC中就需要自己实现了,原理差不多,这里不多讲有兴趣的可以看源码。

四、解决思路

要在.NETCore MVC中兼容云ERP的MVC特性,核心要解决的就是以下三点:

  1. 自定义路由。

  2. controller激活。

  3. 多参数绑定。

我们一个一个来解决。

自定义路由

首先我们得让MVC认识AppService,不然无法做后面的事情。创建一个 AppServiceFeatureProvider 继承 ControllerFeatureProvider 用来将AppService提供给MVC框架作为控制器使用。并且将AppServiceFeatureProvider提供程序加入MVC的特性提供者集合中。最后在 ConfigureServices 中调用 AddClownFish()。

接下来,就是要给每一个AppService的方法(Action)设置自定义路由。这里利用的是.NET Core MVC的一个Convention 特性,不了解的读者先阅读一下微软文档。

(https://docs.microsoft.com/zh-cn/aspnet/core/mvc/controllers/application-model?view=aspnetcore-3.0#conventions)。

创建一个 AppServiceModelConvention 类型 实现 IControllerModelConvention的Apply 接口。为ControllerModel的每一个Action创建属性路由(AttributeRouteModel),代码如下,为了保证理解容易,我隐藏了部分不重要的代码,文末有Demo源代码链接可以下载。在AddClownFish扩展方法中把AppServiceModelConvention加如MVC的约定列表。

Controller激活

所以分解任务就是:

  1. 创建 ClownFishControllerActivator 替换默认的Controller激活器实现

  2. 实现ERP自定义的激活器,用服务工厂创建AppService实例

  3. 把ClownFishControllerActivator加入服务列表中

代码比较简单:

这里值得一提的是,微软在MVC框架中确实实现了一个默认的激活器实现,但是如果你不去主动使用它,默认他是不使用的,会跳过。避免被坑,我截图说明了一下:

多参数绑定

多参数绑定实现起来比较费劲,主要是因为参数绑定的过程是封闭的,这里利用了篡改缓存的实现,用自定义的Lambad表达式构建了一个新的实例来替换掉默认的实现。

思路:

  1. 实现 IActionInvokerProvider 替换掉默认实现。

  2. 在Action执行时构建一个自定义的Bind函数替换掉缓存中的Bind函数,返回一个新的缓存对象。

  3. 自定义的Bind函数中就可以拿到HttpContext了,这样就可以为所欲为了,自己创建一个JsonTextReader来自由读取Body然后依次绑定到Controller的arguments列表中。

  4. 然后把新的缓存对象塞回缓存字典中。

代码如下:

四、总结

阅读官方文档发现 .NET Core MVC提供了丰富的扩展机制,这为上层框架的发展提供了可能,通过阅读MVC源码可以学习微软程序员的代码设计思想,思考并提炼应用到ERP的产品代码设计中,这也是开源的一种福利吧。

最后附上Demo源码地址:

https://github.com/zongzijie/study/tree/master/CSharp/SampleForAspNetCoreMvc

------ END ------

作者简介

伍同学: 研发工程师,目前负责售楼系统的相关设计开发工作。

也许您还想看

ERP缓存实践经验分享

.Net最小工作线程对应用程序性能的影响

记一次生产环境CPU100%排查实践

如何使用有序GUID提升数据库读写性能

.NET Core MVC扩展实践相关推荐

  1. ASP.NET Core MVC TagHelper实践HighchartsNET快速图表控件

    ASP.NET Core MVC TagHelper最佳实践HighchartsNET快速图表控件支持ASP.NET Core. 曾经在WebForms上写过 HighchartsNET快速图表控件- ...

  2. ASP.NET Core MVC 授权的扩展:自定义 Authorize 和 IApplicationModelProvide

    一.概述 ASP.NET Core MVC 提供了基于角色( Role ).声明( Chaim ) 和策略 ( Policy ) 等的授权方式.在实际应用中,可能采用部门( Department , ...

  3. 007.Adding a view to an ASP.NET Core MVC app -- 【在asp.net core mvc中添加视图】

    索引: 目录索引 Adding a view to an ASP.NET Core MVC app 在asp.net core mvc中添加视图 2017-3-4 7 分钟阅读时长 本文内容 1.Ch ...

  4. 使用NUnit和Moq测试ASP.NET Core MVC应用程序

    目录 介绍 背景 使用代码 兴趣点 该文章总结了使用NUnit和Moq框架对ASP NET Core MVC控制器进行单元测试的最佳实践 Download netcoreapp2.0 unit tes ...

  5. 这本694页的程序员砖头书让你精通ASP.NET Core MVC

    ASP.NET Core MVC是一个来自微软的Web应用程序开发框架,它结合了模型-视图-控制器(MVC)体系结构的有效性和整洁性.敏捷开发的想法和技术,以及.NET平台的最佳部分. 1.1 ASP ...

  6. ASP.NET Core MVC 项目 Autofac

    目录 一:基本使用 二:简单理解Autofac容器 三:多种注册方式 四:构造函数注入 一:默认构造函数注入 二:选择一个构造函数参数的构造函数 五:属性注入 一:属性注入 二:属性注入扩展--指定属 ...

  7. 关于MVC与三层架构、个人总结网上杂七杂八得出的最终成果、asp.net (core) MVC、JavaWeb的MVC

    阅读本文必须明白的事情 首先需要明白的是不同语言实现的MVC与三层架构对应的层是不一样的!!! 拿.net来说,.net实现MVC与其他语言的MVC具体实现是不同的,asp.net MVC与 MVC ...

  8. ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门

    一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...

  9. ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用

    原文:ASP.NET Core 入门教程 2.使用ASP.NET Core MVC框架构建Web应用 一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 ...

最新文章

  1. Python3.5模块‘OS’‘sys’
  2. 〔转〕Word域的应用和详解5_索引和目录
  3. 给ThinkPad E470C 换个高分屏(1080P)
  4. 2009年9月三级网络技术考前预测_填空题部分
  5. ios 导航栏(自己定义和使用系统方式)
  6. Master DNS服务的搭建
  7. P3288-[SCOI2014]方伯伯运椰子【0/1分数规划,负环】
  8. 除了默认的docker0网桥,启动Docker服务怎么指定使用的网桥
  9. python入门题目及答案_Python基础知识的一些练习与解答,python,部分,习题,及,答案...
  10. 比尔·盖茨推荐2020年度五本好书 你想读哪本?
  11. 发布npm时遇到的两个小问题,解决方法
  12. c语言汉诺塔动画程序,汉诺塔问题算法(c语言控制台动画演示版)
  13. 软件测试实例——总结
  14. 电工结业试卷_电工结业总结
  15. 什么是云服务器ECS?
  16. “换头术”所引发的“长生不死”
  17. 阈的粤语发音_新编粤语读音字典 - 粤语 | Cantonese | 白话 - 声同小语种论坛 - Powered by phpwind...
  18. mysql主从配置duxi_mysql 主从配置笔记
  19. Squirrel中的类与实例
  20. 平新乔《微观经济学十八讲》课后习题答案

热门文章

  1. Winform开发中另一种样式的OutLookBar工具条
  2. kali linux超级用户_如何优雅的在Linux上使用Powershell]
  3. 使用CADisplayLink实现UILabel动画特效
  4. zabbix邮件发不出去
  5. Linux文件锁学习-flock, lockf, fcntl
  6. [深入JUnit] 测试运行的入口
  7. Linux入门之进程管理(4)之进程与文件
  8. DCOS实践分享(6):基于DCOS的大数据应用分享
  9. 使用 HP 3PAR Peer Persistence 实现 vSphere Metro Storage Cluster (vMSC)
  10. C语言程序读写文件(文件内存一个十进制数,每读一次数值加一)