.NET Core MVC扩展实践

源宝导读:明源云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提升数据库读写性能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值