零基础ASP.NET Core WebAPI团队协作开发

相信大家对“前后端分离”和“微服务”这两个词应该是耳熟能详了。网上也有很多介绍这方面的文章。我这里提这个是因为接下来我要分享的内容和这个有些关联。

随着前端应用场景的繁荣,用户体验需求的提高,原先传统的后端渲染页面返回给前端展示的模式面临挑战。后端工作除了处理数据逻辑还得适应界面UI的业务,越来越不堪负重。前端的重要性逐渐体现出来,在这种情况下使用前后端分离模式开发的逐渐增多。

前端框架(比如Vue/Angular/React)的发力,大厂的推广使用,前后端分离已经很成熟。包括传统信息化这块以前使用传统WebMVC模式的开发的BS应用有些都逐步转为前后端分离模式。特别是开发人员分工之后专注做好各自的工作,效率更高,做出来的产品也就更好。

一、应用场景

1、浏览器端(Vue/Angular/React)+服务端API

2、桌面客户端(mfc/winform/wpf)+服务端API

3、移动客户端(各种App/App内置浏览器)+服务端API

4、其他终端(大数据展示平台/报表展示平台)+服务端API

客户端越来越强调轻量化,交互体验,不在满足于能用。服务端端只管提供API数据,这样业务逻辑大多在服务端处理,随着需求增加服务端的模块会越来越多。但是有些接口是共用的,有些是根据业务变动的,还有的API新旧版本过渡更新替换等等是服务端api要考虑的事情。设计好API开发框架面灵活应对这么多场景就很有必要了。

原先可能会做一个单体式应用,把所有用到的接口都加进去。但这样粒度很粗,如果某个场景下只使用了部分接口,那也得把这整个应用部署,无法做到按需添加。还有就是可能要修改其中部分方法,需要整体重新编译发布。这都存在可能影响其他模块的风险。

服务端任务量大了,怎么分工?这个时候单体明显已经不适用了。这里就引出了微服务。对微服务可能每个人有不同的理解,但有一点是有共识的,就是把一个大的单体式应用根据功能模块拆分,这样粒度细分之后很多接口就可以共用。之后的修改增加都是可以按需发布部署,局部出现问题不会影响整体。

这个服务的粒度怎么拆分也是需要慎重考虑的问题。除了功能拆分还得考虑人员匹配。

案例场景:一个系统有10个子系统(模块),每个子系统(模块)又有10个功能,每个功能再具体又可能有20个左右的方法代码。

这个案例,最后大概有2000个方法代码。

如果开始安排10人的团队开发,中途因为项目紧急再增加了10个人进来,总共变成了20人,项目组怎么做才能快速适应这种人员变动。

有时候不是人越多越能做好事情,在人员增加情况下除了增加沟通协调成本,实际情况会遇到新加的人参与进来的门槛很高,不能快速着手展开工作,有时候还会出现不知道从何入手的困境。这就是因为拆分的不合理,任何的改动可能会影响到他人。这样虽然为了赶进度加人了,但实际的效果却不是很理想。

二、功能拆分分析

怎么拆分这有两个极端例子

1、粒度最粗,全部在一个解决方案(极端例子,类似单体式应用,适合一人开发)

2、粒度最细,细分到每个方法一个解决方案(极端例子,实际肯定不会这样做)

实际项目中功能拆分就是在这两个极端情况之间找适合的平衡点。具体拆分到多大的粒度,这个就只能是根据具体项目情况具体分析了。但是微服务可能是建议往细的方向拆。

如果是项目型的会发现如果拆的太细,上线一套系统要带N个接口,运维实施都很麻烦;如果是做平台型的产品可能就是有限的几套系统,不会随着项目铺开太多定制化。也就没有了项目型里面的经常部署实施等繁琐的问题。

比如上面的案例,一般都是先根据子系统拆分,具体到每个子系统,有一人或多人开发也有后期临时加入的情况。每个子系统一套接口还是比较合适的。

实际情况项目型比较多,考虑实施运维情况拆分的粒度不会太细,让实施去部署太多业务接口会把他们逼疯。如果有和我类似情况的下面的方案提供了一种解决办法。开发时候可以横向任意扩展,新加入的人员分配任务清晰,不用担心有耦合冲突。发布部署也不会因为粒度太细,增加部署工作量。总结就是插件式开发,微服务部署。

我们都知道vs里面建立一个解决方案,两三个开发人员在同一个解决方案里面开发,只要协调好还行,如果再加入人员,参与的开发人员一旦多了,就算分工好做各自模块,但还是会存在一个些冲突,比如增加文件,增加引用等等都会引起项目文件或者解决方案文件冲突问题。而且这种情况代码权限还不好细分控制。

最好的方式是每个开发人员做的事情都在自己的解决方案里面,只要是公共使用的引用协调好大家使用统一的版本,其他的自己完全可控,完全不用担心影响他人,或者他人的修改影响自己。

大家可以看下这个 github上面dotnet基础类库,如图1。

图1

这是dotnet基础库的源码,每个基础类库都是单独一个解决方案维护,随便点一个进去看下,如图2

图2

每个类库都有独立解决方案文件。

微软肯定有更好的方式去管理,但从这里可以看出,独立开发维护的优势。

三、接口项目准备

前面分享过一篇《零基础ASP.NET Core MVC插件式开发》的文章,那边文章其实也就是强调团队开发的时候能做到尽量独立,可以横向扩展,项目灵活变动增加开发人员可以快速参与,开发之后能汇总到一个个的子系统,最后完成整体开发。在这里API的开发也可以使用类似方案,因为API没有视图部分,处理起来比MVC简单。

接下来重点介绍该方案在API开发中的使用。开始这部分内容之前先简单介绍我这边API项目开发总结的两个共性问题:

1、使用swagger显示API文档(nuget 引用 Swashbuckle.AspNetCore)

因为API是没有试图的,为了可视化,以及方便测试,使用swagger作为API的展示界面。具体使用看下面提供的demo代码

2、使用版本控制API版本号(nuget 引用Microsoft.AspNetCore.Mvc.Versioning)

版本控制对API也是同样重要,看BAT大厂提供的API都是有版本控制的,要向他们看齐。实际应用中,程序不可能维持一套最新,有时候新旧版本需要过渡,所以需要有版本来区分。这里使用微软提供的版本控制。具体使用看下面提供的demo代码

这两个使用这里就不细说了,穿插下面主题做些简单介绍,具体看案例demo就可以。

四、接口插件式开发

回到我们的主题,这里重点介绍下一个子系统(模块)任务拆分与人员分工

项目组接下一个项目,一般有个开发组长,着手模块划分并且开发任务分工

组长(公共部分接口+核心功能模块接口)

组员1:细分的模块插件1接口

组员2:细分的模块插件2接口

组员3:细分的模块插件3接口

......

......

对于的解决方案结构,具体命名自己可以根据喜好自己自定义。

Agile.ModuleName.API  如下图3

Agile.ModuleName.Plug1.API 图下图4

Agile.ModuleName.Plug2.API

Agile.ModuleName.Plug3.API

......

......

图3

图4

Demo使用的是vs2019,Asp.net core 2.1

注意:如果一个模块里面接口比较多,一个解决方案里面不适合团队开发。所以对这种接口功能比较多,拆成各个插件方便团队开发,最后发布的时候合并到一起。但是如果这个模块接口不是很多,就没必要过度设计为了插件化而拆开。

每个独立开发的都是vs里面建立的标准ASP.NET Core WebAPI项目,这里主项目和各个插件项目没有从属关系,完全平等API项目开发,最后只是可以汇合到主项目作为一个站点发布交付。各自独立调试运行各自开发功能模块,测试没问题发布汇总到主项目,部署运行,之后哪个接口问题只需要找到对应的模块修改,完全隔离开,不用担心修改会影响其他正常使用的模块。

主项目解决方案结构,如图5

图5

v1,v2里面的是有版本控制的,放在外面的就不需要版本控制。

还有Extensions文件夹里面两个类也是为了版本的显示做处理,具体看Startup.cs里面代码,如图6

图6

搭建好之后,主项目运行,选择v1版本显示如图7

图7

如果选择v2,显示如图8

图8

通过上面两个切换,应该看到不管选择v1还是v2下面不受版本控制的都会显示。

如果把图4的代码注释掉,看下运行效果,如图9

图9

显示就这样,不能根据swagger选择,直观的显示是v1还是v2。这个就是RemoveVersionFromParameter和ReplaceVersionWithExactValueInPath两个类的作用。

这两个类的代码如下

public class RemoveVersionFromParameter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters.Count > )
{
var versionParameter = operation.Parameters.FirstOrDefault(p => p.Name == "version");
operation.Parameters.Remove(versionParameter);
}
}
} public class ReplaceVersionWithExactValueInPath : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
swaggerDoc.Paths = swaggerDoc.Paths
.ToDictionary(
path => path.Key.Replace("v{version}", swaggerDoc.Info.Version),
path => path.Value
);
}
}

到这里主项目API运行正常,接下来看下插件项目API。

插件1项目结构,和主项目类似,如图10

图10

单独运行下这个插件1项目,效果如图11

图11

这里作为插件API项目同样有一点要注意,不要出现和其他插件或者主项目同名的路由(version,controller,action三个完全一样,分工之后各自命名规范估计这种情况也不会出现,主要还是注意避免合并之后路由重名问题)。

这里先把插件1编译的dll放到主项目的运行目录来,如图12

图12

并且在主项目的Startup.cs里面增加这段代码,如图13

图13

运行看下效果,如图14

图14

汇合成功,插件1的API能展示出来,测试也正常,测试就不截图了。

同理,插件1,插件2...等等也是一样处理。开发阶段,各自开发的功能都是可以独立调试运行的。有没有主项目对各自开发的不影响。

五、问题总结

 

如果插件项目里面引用了一个第三方的程序集,如图15

图15

引用一个测试类库,在Plug1NoVerController的Get方法里面写一个测试代码,如图16

图16

在插件项目单独测试,运行正常。

再把插件1相关文件拷贝到主项目,这时候多了个插件项目自己引用的OtherLib.dll,如图17

图17

正常运行,如图18

图18

测试下刚才插件1里面用到OtherLib类的接口,看效果如图19

图19

汗,居然报错了,提示FileNotFoundException,但是看上面的错误信息截图提示找不到OtherLib.dll文件。OtherLib.dll这个文件明明在这个目录有的。查了相关资料都说是.net core的加载机制变了,但还是没理解透彻,不知道.net core3.0会不会解决这个问题。希望有大神看到可以解惑下这个问题。不过这里我使用一种方式可以解决这个报错,在主程序这里加这段代码。在注册插件项目之前,遍历所有dll,做一次加载就可以了。如图20

图20

需要在注册插件之前,把所有dll文件这样加载一遍,就可以了。

再运行,测试就正常了,如图21

图21

 

 

六、发布运行

各个独立开发的插件API,各自独立开发调试正常之后,发布出来。

好了,插件1,插件2...等等各自都开发好了,各自模块调试没问题,最后汇总到主的项目来,基本也就没什么问题了,并且还可以作为一个站点部署。

这里的一个站点只是一个接口服务,不要理解成一个系统就这一个接口服务,虽然可以这样做,但不建议,部署还是各个子系统一个服务,这样数量也不会很多。这里是指在开发阶段对一个子系统(模块)的N个接口做开发方面的分工独立开发调试。

子系统(模块)有N个接口,开发分工如下:

主插件,插件1,插件2,插件3...

全部汇总到主插件的发布目录,或者手动拷贝,最后提供一个完成的子系统接口发布版本,目录如图22

图22

同样命令行运行,或者宿主到iis,这里命令行运行,如图23

图23

浏览器打开,如图24

图24

直接swagger测试各个接口,正常。

独立插件化开发,微服务发布部署。

希望你看了之后有点收获,代码程序下面附件提供

Demo程序

零基础ASP.NET Core WebAPI团队协作开发的更多相关文章

  1. 零基础ASP.NET Core MVC插件式开发

    零基础ASP.NET Core MVC插件式开发 一个项目随着业务模块的不断增加,系统会越来越庞大.如果参与开发的人员越多,管理起来也难度也很大.面对这样的情况,首先想到的是模块化插件式开发,根据业务 ...

  2. Asp.net core WebApi 使用Swagger生成帮助页

    最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...

  3. Asp.net core WebApi 使用Swagger生成帮助页实例

    最近我们团队一直进行.net core的转型,web开发向着前后端分离的技术架构演进,我们后台主要是采用了asp.net core webapi来进行开发,开始每次调试以及与前端人员的沟通上都存在这效 ...

  4. 第十九节:Asp.Net Core WebApi基础总结和请求方式

    一. 基础总结 1.Restful服务改造 Core下的WebApi默认也是Restful格式服务,即通过请求方式(Get,post,put,delete)来区分请求哪个方法,请求的URL中不需要写方 ...

  5. ASP.NET Core WebApi构建API接口服务实战演练

    一.ASP.NET Core WebApi课程介绍 人生苦短,我用.NET Core!提到Api接口,一般会想到以前用到的WebService和WCF服务,这三个技术都是用来创建服务接口,只不过Web ...

  6. ASP.NET Core WebApi基于Redis实现Token接口安全认证

    一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebSer ...

  7. asp.net core webapi之跨域(Cors)访问

    这里说的跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被当作 ...

  8. Asp.Net Core WebApi学习笔记(四)-- Middleware

    Asp.Net Core WebApi学习笔记(四)-- Middleware 本文记录了Asp.Net管道模型和Asp.Net Core的Middleware模型的对比,并在上一篇的基础上增加Mid ...

  9. ASP.NET Core WebAPI中的分析工具MiniProfiler

    介绍 作为一个开发人员,你知道如何分析自己开发的Api性能么? 在Visual Studio和Azure中, 我们可以使用Application Insight来监控项目.除此之外我们还可以使用一个免 ...

随机推荐

  1. Android Xposed框架出现java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation问题

    第一次玩Xposed框架,按照多个demo的格式写了一个demo发现死活不进入 public abstract void handleLoadPackage(LoadPackageParam lppa ...

  2. sqlserver创建接受任何类型的nvl

    if exists ( select * from sys.objects where object_id = object_id(N'dbo.nvl') and type = N'FN') begi ...

  3. textblock的LineHeight的调整

    原文:textblock的LineHeight的调整 <TextBlock Width="113.594" Height="73.667" Text=&q ...

  4. LINQ查询表达式---------let子句

    LINQ查询表达式---------let子句 let子句创建一个范围变量来存储结果,变量被创建后,不能修改或把其他表达式的结果重新赋值给它.此范围变量可以再后续的LINQ子句中使用. class P ...

  5. Qt:移动无边框窗体(使用Windows的SendMessage)

    移动无边框窗体的代码网上很多,其原理都是一样的,但是是有问题的,我这里只是对其修正一下 网上的代码仅仅实现了两个事件 void EditDialog::mousePressEvent(QMouseEv ...

  6. Qt4.8.6与VS2008的集成开发环境的安装配置

    一.安装编译Qt 1. 在Windows下用Qt做开发,编译器可以用mingw的gcc/g++,也可以用VS. 2. 安装VS2008集成开发环境(完全安装).  3. 安装qt4.8.6(qt-op ...

  7. Spring与IoC

    控制反转(IOC,Inversion of Control),是一个概念,是一种思想. 指将传统上由程序代码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理.控制反转就是对对象控制权的转移 ...

  8. mvc中Scripts.Render的用法

    第一次接触新的东西,都会很陌生,但是时间久了就熟悉了变简单了. 视图文件中使用Scripts.Render()输出脚本包,Styles.Render()输出样式包 上面两张图是我所做项目里的,放上面会 ...

  9. 【LEETCODE】32、LeetCode的第35题,查找插入的位置

    凉凉,看来想做好一个题还不容易啊... 有点难受... 1.看看题目吧 Given a sorted array and a target value, return the index if the ...

  10. Unity Shader 玻璃效果

    一个玻璃效果主要分为两个部分,一部分是折射效果的计算,另一部分则是反射.下面分类进行讨论: 折射: 1.利用Grass Pass对当前屏幕的渲染图像进行采样 2.得到法线贴图对折射的影响 3.对采集的 ...