.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路由到激活的过程。
那么将面临两个问题:
自定义路由,首先要能让MVC认知AppService并能按照云ERP的模板规范进行路由。
路由到AppService后激活的方式得用服务工厂 ServiceFactory来创建,这样才能兼容二开的插件模式。(注:服务工厂中创建的是AppService的代理类的实例,携带二开定义的插件方法)
支撑多参数绑定
云ERP多参数绑定的解决方案是利用的ClownFish.net框架中的 ClownFish. Web.Serializer. JsonnetDataProvider 来解决的(ClownFish.net明源云的架构师FishLi多年前的作品,已在Github上开源)。
迁移到.NET Core MVC中就需要自己实现了,原理差不多,这里不多讲有兴趣的可以看源码。
四、解决思路
要在.NETCore MVC中兼容云ERP的MVC特性,核心要解决的就是以下三点:
自定义路由。
controller激活。
多参数绑定。
我们一个一个来解决。
自定义路由
首先我们得让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激活
所以分解任务就是:
创建 ClownFishControllerActivator 替换默认的Controller激活器实现
实现ERP自定义的激活器,用服务工厂创建AppService实例
把ClownFishControllerActivator加入服务列表中
代码比较简单:
这里值得一提的是,微软在MVC框架中确实实现了一个默认的激活器实现,但是如果你不去主动使用它,默认他是不使用的,会跳过。避免被坑,我截图说明了一下:
多参数绑定
多参数绑定实现起来比较费劲,主要是因为参数绑定的过程是封闭的,这里利用了篡改缓存的实现,用自定义的Lambad表达式构建了一个新的实例来替换掉默认的实现。
思路:
实现 IActionInvokerProvider 替换掉默认实现。
在Action执行时构建一个自定义的Bind函数替换掉缓存中的Bind函数,返回一个新的缓存对象。
自定义的Bind函数中就可以拿到HttpContext了,这样就可以为所欲为了,自己创建一个JsonTextReader来自由读取Body然后依次绑定到Controller的arguments列表中。
然后把新的缓存对象塞回缓存字典中。
代码如下:
四、总结
阅读官方文档发现 .NET Core MVC提供了丰富的扩展机制,这为上层框架的发展提供了可能,通过阅读MVC源码可以学习微软程序员的代码设计思想,思考并提炼应用到ERP的产品代码设计中,这也是开源的一种福利吧。
最后附上Demo源码地址:
https://github.com/zongzijie/study/tree/master/CSharp/SampleForAspNetCoreMvc
------ END ------
作者简介
伍同学: 研发工程师,目前负责售楼系统的相关设计开发工作。
也许您还想看
ERP缓存实践经验分享
.Net最小工作线程对应用程序性能的影响
记一次生产环境CPU100%排查实践
如何使用有序GUID提升数据库读写性能
.NET Core MVC扩展实践相关推荐
- ASP.NET Core MVC TagHelper实践HighchartsNET快速图表控件
ASP.NET Core MVC TagHelper最佳实践HighchartsNET快速图表控件支持ASP.NET Core. 曾经在WebForms上写过 HighchartsNET快速图表控件- ...
- ASP.NET Core MVC 授权的扩展:自定义 Authorize 和 IApplicationModelProvide
一.概述 ASP.NET Core MVC 提供了基于角色( Role ).声明( Chaim ) 和策略 ( Policy ) 等的授权方式.在实际应用中,可能采用部门( Department , ...
- 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 ...
- 使用NUnit和Moq测试ASP.NET Core MVC应用程序
目录 介绍 背景 使用代码 兴趣点 该文章总结了使用NUnit和Moq框架对ASP NET Core MVC控制器进行单元测试的最佳实践 Download netcoreapp2.0 unit tes ...
- 这本694页的程序员砖头书让你精通ASP.NET Core MVC
ASP.NET Core MVC是一个来自微软的Web应用程序开发框架,它结合了模型-视图-控制器(MVC)体系结构的有效性和整洁性.敏捷开发的想法和技术,以及.NET平台的最佳部分. 1.1 ASP ...
- ASP.NET Core MVC 项目 Autofac
目录 一:基本使用 二:简单理解Autofac容器 三:多种注册方式 四:构造函数注入 一:默认构造函数注入 二:选择一个构造函数参数的构造函数 五:属性注入 一:属性注入 二:属性注入扩展--指定属 ...
- 关于MVC与三层架构、个人总结网上杂七杂八得出的最终成果、asp.net (core) MVC、JavaWeb的MVC
阅读本文必须明白的事情 首先需要明白的是不同语言实现的MVC与三层架构对应的层是不一样的!!! 拿.net来说,.net实现MVC与其他语言的MVC具体实现是不同的,asp.net MVC与 MVC ...
- ASP.NET Core 入门教程 6、ASP.NET Core MVC 视图布局入门
一.前言 1.本教程主要内容 ASP.NET Core MVC (Razor)视图母版页教程 ASP.NET Core MVC (Razor)带有Section的视图母版页教程 ASP.NET Cor ...
- ASP.NET Core 入门教程 2、使用ASP.NET Core MVC框架构建Web应用
原文:ASP.NET Core 入门教程 2.使用ASP.NET Core MVC框架构建Web应用 一.前言 1.本文主要内容 使用dotnet cli创建基于解决方案(sln+csproj)的项目 ...
最新文章
- Python3.5模块‘OS’‘sys’
- 〔转〕Word域的应用和详解5_索引和目录
- 给ThinkPad E470C 换个高分屏(1080P)
- 2009年9月三级网络技术考前预测_填空题部分
- ios 导航栏(自己定义和使用系统方式)
- Master DNS服务的搭建
- P3288-[SCOI2014]方伯伯运椰子【0/1分数规划,负环】
- 除了默认的docker0网桥,启动Docker服务怎么指定使用的网桥
- python入门题目及答案_Python基础知识的一些练习与解答,python,部分,习题,及,答案...
- 比尔·盖茨推荐2020年度五本好书 你想读哪本?
- 发布npm时遇到的两个小问题,解决方法
- c语言汉诺塔动画程序,汉诺塔问题算法(c语言控制台动画演示版)
- 软件测试实例——总结
- 电工结业试卷_电工结业总结
- 什么是云服务器ECS?
- “换头术”所引发的“长生不死”
- 阈的粤语发音_新编粤语读音字典 - 粤语 | Cantonese | 白话 - 声同小语种论坛 - Powered by phpwind...
- mysql主从配置duxi_mysql 主从配置笔记
- Squirrel中的类与实例
- 平新乔《微观经济学十八讲》课后习题答案
热门文章
- Winform开发中另一种样式的OutLookBar工具条
- kali linux超级用户_如何优雅的在Linux上使用Powershell]
- 使用CADisplayLink实现UILabel动画特效
- zabbix邮件发不出去
- Linux文件锁学习-flock, lockf, fcntl
- [深入JUnit] 测试运行的入口
- Linux入门之进程管理(4)之进程与文件
- DCOS实践分享(6):基于DCOS的大数据应用分享
- 使用 HP 3PAR Peer Persistence 实现 vSphere Metro Storage Cluster (vMSC)
- C语言程序读写文件(文件内存一个十进制数,每读一次数值加一)