【复杂系统迁移 .NET Core平台系列】之界面层

源宝导读:微软跨平台技术框架—.NET Core已经日趋成熟,已经具备了支撑大型系统稳定运行的条件。本文将介绍明源云ERP平台从.NET Framework向.NET Core迁移过程中的实践经验。

一、背景

    随着ERP的产品线越来越多,业务关联也日益复杂,应用间依赖关系也变得错综复杂,单体架构的弱点日趋明显。19年初,由于平台底层支持了分应用部署模式,将ERP从应用子系统层面进行了切割分离,迈出了从单体架构向微服务架构转型的坚实一步。不久的将来,ERP会进一步将各业务拆分成众多的微服务,而微服务势必需要进行容器化部署和运行管理,这就要求ERP技术底层必须支持跨平台,所以将现有ERP系统从.NET Framework迁移到 .NET Core平台势在必行。

    上一篇《【复杂系统迁移 .NET Core平台系列】之迁移项目工程》的文章中,我们分享了在改造.NET Core工程和类库过程中的经验,本文我们将分享在界面层改造过程中遇到的问题和解决思路。

    ERP目前使用的是Asp.Net WebForm框架,在.NET Core中已经被废弃了,那么这部分就只有采用重写的方式。在Asp.Net Core Mvc中RazorPage的访问方式跟WebForm基于物理路径的访问提供了类似的机制;并且PageModel也跟Aspx的CodeBehind的方式类似。就是基于这样类似的方式,提供了结构和逻辑复用的可能性。基于这个起点,本篇将从如下步骤讲述界面层的改造过程:

  1. 页面路由:改造Url重定向的逻辑,定位到页面;

  2. Aspx页面:改造Aspx页面为cshtml页面;

  3. 模板页面:改造Master为Layout页面;

  4. 服务端控件:改造服务端用户Ascx页面。

二、页面路由改造

    ERP的页面有两种,一种是由建模配置出来的叫标准页面,由平台托管来提供功能;另一种是自定义页面,自己写Aspx实现所有业务逻辑。标准页面使用Url重写,而自定义页面直接用路径访问。在Asp.Net Core MVC中从Url映射到RazorPage是通过路由模块来实现的,为了支持以前的访问Url不变,我们需要对路由进行扩展。

    区别于传统Asp.Net Mvc的页面通过路径加载,然后运行时编译不同,在.NET Core中默认是直接将*.cshtml页面编译到DLL中,然后通过AssemblyPart加载到MVC框架中,默认RazorPage的路径是DLL中相对于Page文件夹的路径。

    例如下图所示的页面访问路径为“/PubPlatform/Nav/Home/Default”:

1、标准页面路由

   举一个平台的标准页面Url的例子:“/std/00002212/822952a2-5091-e711-9bda-001583b5bd1a.aspx”。这个Url可以通过HttpModule重写为:

“/_frontend/templates/pages/Grid/template.aspx?FunctionCode=00002212&_pagename=822952a2-5091-e711-9bda-001583b5bd1a”。重写主要目的是找到“822952a2-5091-e711-9bda-001583b5bd1a”这个ID对应页面元数据内容,然后通过配置映射到物理路径的template.aspx页面。

 RazorPage是通过IPageRouteModel Convention来提供路由的扩展的,提供了PageRouteModelConvention和FolderRoute ModelConvention类来实现扩展,这两种使用方式可以通过内置的AddPageRoute和AddFolderRouteModelConvention方法来实现,下面是平台使用文件夹路由转换的代码示例:

    在上述代码中我们为所有/templates/pages路径下的页面,添加三个路由参数:

  1. AppConst.FunctionCodeKey(FucntionCode):模块代码 对应上述Url中的00002212;

  2. AppConst.PageNameKey(PageName):元数据标识 对应上述Url中的822952a2-5091-e711-9bda-001583b5bd1a;

  3. AppConst.PageKey(Page):RazorPage页面的相对于Page文件夹的路径(框架自带)。

    TemplateConstraint实现IActionConstraint用于在路由系统中决定URL是否匹配当前页面,还是仿照之前HttpModule中Url重写逻辑来做路由匹配即可实现Url路由到对应的RazorPage。

2、自定义页面路由

    我们先看看改造前和改造后页面的组织结构对比:

  在改造自定义页面路由的时候我们使用IPageRouteModelProvider扩展OnProviders Executing,扩展代码如下:

    在标准页面中我们使用了MVC自带的扩展机制,自定义页面我们使用IPageRoute ModelProvider扩展OnProvidersExecuting,因为在标准页面中我们使用路径来做匹配,但是自定义页面中需要兼容产品页面路径和项目页面路径,使用了类似于黑名单和白名单的区别,所以分别采用了不同的策略。另外这里我们扩展了OnProvidersExecuted的方法,在所有路由加载完之后来进行路由替换,来实现项目页面替换产品页面。

三、页面改造

    解决了路由访问的问题,接下来就要进行Aspx页面改造成cshtml了。首先我们简单介绍下RazorPage的一些基本特性:

  1. 前端通过cshmtl来渲染Html;

  2. 后端通过PageModel来处理业务逻辑;

  3. 通过OnGet或者OnPost来提供访问;

  4. 通过PageModel属性和BindProperty来实现参数到模型的绑定;

  5. 通过PageModel属性实现PageModel到cshtml页面的数据传递。

    ERP所有的Aspx都没有*.cs的后台代码。这里简单介绍下ERP对Aspx页面的使用规范:

  1. 实现Html渲染逻辑;

  2. OnLoad方法重写实现取数等简单后台操作;

  3. 页面回传请求通过Ajax处理 从功能特性可以发现我们不用处理传统Aspx的回传的请求。Aspx的OnLoad可以使用RazorPag的OnGet方法中来替换,然后赋值给PageModel的属性来传递给cshtml来绑定数据,页面中只需要将Aspx语法替换成Razor的语法即可。

    语法转换工具可以从这里找到:https://github.com/telerik/razor-converter。

    在之前ERP中由于缺少了继承自Page的基类所以在页面中会有重复代码,在新版本改造中我们将一些通用方法进行了抽取,做了如下的继承层级的改造:

    有了这一层之后就能对一些例如权限、多语言、多时区等进行通用代码的封装。并且为以后通用逻辑等定义一个可扩展的地方。但是封装之后还有一个问题如果每个页面都需要去设置继承关系就会显得有些重复,并且容易犯错,在MVC中提供了如下两种简洁的方式:

  1. _ViewStart中定义的逻辑全部页面生效;

  2. _ViewImport按照目录优先级,路径靠近_ViewImport会重写上层的逻辑,对下层的页面生效。

四、模板页面改造

    我们在做页面的时候一般都是需要使用Master页面来做布局封装的,首先我们来一张看看平台Aspx和cshtml的布局层级对比图 :

1、顶层Layout页面

    原来的Master页面中有大量的重复代码,所以这里做了一层抽象。顶层Layout页面用来定义Html结构,通常html中将css部分放在header中,将script部分放在body的最下面。另外css和js分别可以分类为,第三方css/js,通用css/js,文件引用的css/js,系统自定义输出到界面的css/js和用户自定义的css和js,这些都是通过MVC的RenderSection方法,提供类似与类中virutal方法一样可以由页面重写。下面是示例代码:

2、模板页面

    Nav模板页面定义Body结构,包括不同的页面布局:

  • _Nav.cshtml 用来定义带导航的页面;

  • _Json.cshtml 用来定义json页面;

  • _Content.cshtml 用来定义无导航的内容页面;

  • _Dialog.cshtml 用来定义弹框页面。

3、模板页面设置

    在ERP中因为标准页面可以挂载到不同的模板中,例如常见的表单页面可以加载到带导航的页面中,也可以加载到弹出框中。而且指定模板的方式不是通过直接跟路径关联.由于使用了预编译的机制,并且页面的路径希望对其他引用者屏蔽,所以用名字代替页面路径来设置模板,从而让模板页面路径和使用者解耦。通过如下逻辑来替换:

  1. 在自定义页面中我们直接使用名字指定;

  2. 在标准建模页面中我们使用元数据中配置的名字来指定;

  3. 在url中通过_mp参数来指定模板的名字,兼容一些图书兼容场景,例如页面嵌套的业务场景;

  4. 最终为了兼容一套名称和路径对应关系,兼容Framework和Core我们使用了类似如下的映射方式。

五、服务端控件ascx改造

    在Aspx的使用中为了提高代码的复用程度,一般都会使用Ascx的自定义控件,在MVC中有多种的替代方式,在比较单纯的数据绑定页面中我们使用了PartialView来替代,这部分主要在布局页面中使用,有如下模板:

  1. Collapse.cshtml分类组件页面,默认收起左侧导航;

  2. Footer.cshtml 底部组件,用于返回顶部;

  3. Holder.cshtml 内容部件;

  4. Navbar.cshtml 顶部导航组件,用于显示用户相关设置通知等信息;

  5. Sidebar.cshtml 用于显示左边菜单。

    为了将CSS,JS等资源加载更加集中化,我们也将布局页面中一些资源按照功能加载进行了加载。如下:

  1. 模块化sea.js;

  2. 默认的一些输出到界面的js变量,如用户名,时区,页面元数据等;

  3. 权限事件脚本等,(之前这部分可能会放在后台cs代码中,现在也放在部分页里面加载)。

    除了这些简单逻辑之外,还有一些组件会直接使用后台的服务取数据,然后渲染页面这部分使用Core的Component(视图组件)来加载 例如tab页面的加载,这里需要取得上下文中用户信息,从而获取权限然后判断是否加载。

    在标准页面中会用到列表,树列表等大控件,这类控件的逻辑在后台配合RazorEngine来渲染的,这部分对Asp.NET Core MVC正好兼容,在原来是通过自定义控件来提供访问,在Asp.NET MVC中是通过Html.XXXFor类似方法提供访问,在Core中为了让cshtml可读性更好,提供了TagHelper的方式,这里也将访问方式通过了TagHelper封装,代码示例:

六、总结

    在Framework中有很多前端代码和后端代码糅合在一个Aspx页面中。有了RazorPage之后可以用cshtml来渲染界面,使用PageModel来处理数据,这样做到前端逻辑和后端逻辑的分离,并且根据职责将之前的不同功能的界面渲染需求,进行封装和职责的分离,使前端渲染逻辑更加清晰也更容易维护。在下一篇分享中,我们将介绍针对页面资源文件引用(例如CSS、JS文件)的迁移过程,大家敬请期待。

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

作者简介

熊同学: 研发工程师,目前负责ERP运行平台的设计与开发工作。

也许您还想看

【复杂系统迁移 .NET Core平台系列】之迁移项目工程

.NET Core MVC扩展实践

分布式锁的实现与探索

ERP缓存实践经验分享

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312427.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET Core MVC扩展实践

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

matlab title多个标题_MATLAB中的直方图处理及均衡化

直方图是多种空间域处理技术的基础。仿图操作能有效地用于图像增强,直方图固有的信息在其他图像处理应用中也是非常有用的,如图像压缩与分割。訪图在软件中易于计算,也适用于商用硬件设备,因此直方图成为实时图像处理的一个流行工…

成本计算引擎动态规则解析技术详解

源宝导读:随着企业数字系统应用的越来越深入,业务计算方式也变的越来越复杂,灵活度要求也越来越高。本文将介绍通过将配置动态转换成可执行代码的方式,解决业务计算高度灵活化配置的技术方案。一、背景ERP本质上是一种“业务密集型…

Kubernetes,多云和低代码数据科学:2020年最热门的数据管理趋势

新兴技术为我们的数据之旅铺平了道路。我们已经看到Kubernetes在应用程序自动化方面处于领先地位,越来越多的公司将赌注押在了云上,以及当今的企业对数据科学的依赖程度正不断提,再加上对大数据的人工智能高级分析,可以看到数据管…

matlab光盘映像文件可以删除吗_DVD-Cloner 2020 for mac(DVD光盘刻录工具) 7.00.715

DVD-Cloner Gold 2020版是功能强大的DVD光盘刻录工具,DVD-Cloner Gold 2020版可以轻松刻录光盘以及蓝光光盘,用户可以将任何的文件刻录到DVD光盘中,并可以制作为蓝光光盘,可以很方便地录入视频到光盘中进行保存,刻录好…

性能优化 = 改改代码?

大家好,我是Z哥。好久没写技术文章了,最近正好有进行一些思考,顺手写出来分享给大家。如果不是程序员的话,可以快速扫一眼正文的几个小标题,快速略过即可,毕竟思路和专业无关,很多是相通的。&am…

使用refs获取节点_闲庭信步聊前端 - 原来你是这样的Refs

一、refs 的由来什么是refsrefs是拿到真实的DOM节点和React元素实例的一种方法。在React官方文档中有提到Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。 React是单向的数据流,父子组件的交互是通过props。修改子组件…

从TimeSpan说起

小编在编写WPF程序时,需要做一个判断:定时使用Modbus协议使用Quartz.net 定时任务读取设备中的数据,同时也使用定时任务判断是否长时间获取不到数据的情况,如果程序中超过一分钟没有获取到数据(数据没有更新&#xff0…

如何维持手机电池寿命_延长手机电池寿命终极技巧教学,iPhone和安卓手机皆适合...

每隔一阵子就开始有不少用户询问,iPhone电池健康度又剩下多少了,怎么朋友的还维持在100%,是不是我手机电池出问题,引起不少用户翻白眼。会有电池健康度,最主要是要让大家了解目前手机电池当前寿命,只要电池…

2020年了,再不会Https就老了

合格的web后端程序员,除搬砖技能,还必须会给各种web服务器启用Https,本文结合ASP.NET Core部署模型聊一聊启用Https的方式。温故知新目前常见的Http请求明文传输,请求可能被篡改,访问的站点可能被伪造。HTTPS是HTTP加上…

c语言枚举类型例题_[开源资讯]Zig 0.6.0 发布,想要挑战 C 语言

Zig 0.6.0 已发布,这是一门通用编程语言,专为稳定性、可维护性和性能而设计,追求替代 C 语言在系统编程上的最佳地位。Zig 具有以下值得关注的特性:手动管理内存与 C 语言竞争而非依赖它,Zig 标准库不依赖于 libc轻量而…

【实战 Ids4】║ 给授权服务器加个锁——HTTPS配置

在上篇文章《【实战 Ids4】║客户端、服务端、授权中心全线打通!》中,我们正式的将三站打通,发布过后,有小伙伴反馈,可能Nginx对配置HTTPS安全协议有点儿问题,我也就半夜趁着没人打扰,疯狂的研究…

快速幂 a*b%c

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 在CSDN上传博客方便复习。 //wecccccccc //2020.12.30 #include <iostream> using namespace std; typedef long long int ll;ll fast_power(ll a, ll b, ll c) {ll ans 1;a % c;//防止一开始输入的值过…

thinkphp 助手函数url不生成https_如何用ThinkPHP框架写一个快递查询接口

ThinkPHP是php程序员们经常使用的框架之一&#xff0c;运用框架来开发网站无疑减轻了我们代码量&#xff0c;加快了我们的开发速度&#xff0c;框架底层封装的方法和函数使用起来简直不能太爽。今天给大家总结一个小案例&#xff0c;如何实现一个快递查询的接口。所谓接口&…

64位整数乘法

2020.12.30开始学习AcWing算法《算法竞赛进阶指南》&#xff1b; 上传博客方便复习。 //Wecccccccc //2020.12.30 #include <iostream> using namespace std; typedef unsigned long long int ull;int main() {ull a, b, c;cin >> a >> b >> c;ull ans…

分布式锁的实现与探索

源宝导读&#xff1a;大型的信息化系统对数据准确性的要求很高&#xff0c;所以经常会使用事务、锁、队列等技术&#xff0c;保障高并发下的数据一致性问题。本文将讨论在分布式部署模式下&#xff0c;如何利用锁机制保证业务数据准确的技术探索与实践。一、背景分布式场景下的…

matlab 角度转四元数_基于Matlab的机械臂路径规划

什么是 trajectory(路径)规划中文路径在英语中可能有两种翻译&#xff1a;1. path2. trajectory首先告诉大家&#xff0c;我们所说的“路径”是后者——trajectory。我们看一下这两种“路径”在机械臂的世界里有什么区别。设想机械臂的 end-effector 要从 A 点运动到 B 点&…

ASP.NET Core 中间件的几种实现方式

前言ASP.NET Core 中 HTTP 管道使用中间件组合处理的方式,换句人话来说,对于写代码的人而言,一切皆中间件.业务逻辑/数据访问/等等一切都需要以中间件的方式来呈现.那么我们必须学会如何实现自定义中间件 这里划重点,必考这里我们介绍下中间件的几种实现方式...匿名函数通常新建…

cookies默认过期时间_「图」Chrome Canary新版已启动“增强版cookies控制”预览测试...

近日谷歌承诺将于今年晚些时候在Chrome浏览器启动“增强版cookies控制”的预览测试。在今年的I/O开发者大会上&#xff0c;谷歌宣布携手Mozilla等开发者耗时3年多时间制定了名为“same-site cookies”的IETF 标准&#xff0c;而该功能就是建立在same-site cookies的基础上&…

【原创】StackOverflow 20万关注的问题:如何实现异步Task超时的处理?

前文传送门 dotNET开发系列收藏&#xff01;推荐12个超实用的Visual Studio插件程序员&#xff1a;这10种糟糕的程序命名&#xff0c;你遇到过几个&#xff1f;使用Vistual Studio N年&#xff0c;推荐2个异常捕获的技巧面试官&#xff1a;你连RESTful都不知道我怎么敢要你&…