net core3.1 和 net 5 下action重载问题

1、问题

  最近将一个.net framework api 项目迁移到net core 3.1。其中有两个action是重载的,方法参数个数不一样。在.net framework下会自动根据请求参数个数进行路由匹配,但是在.net core3.1 下会报【The request matched multiple endpoints】异常。

2、问题查找

  异常的原因在于匹配的多个节点路由。遇到此问题我的第一反映,我重写匹配endpoints相关方法不就行了。带着这个思路我开始看相关的源码,看其是如何进行endpoints注册和匹配的。

  相关注册源码地址:

  https://github.com/aspnet/Routing/blob/master/src/Microsoft.AspNetCore.Routing/Builder/EndpointRoutingApplicationBuilderExtensions.cs

  https://github.com/dotnet/aspnetcore/blob/c925f99cddac0df90ed0bc4a07ecda6b054a0b02/src/Mvc/Mvc.Core/src/Builder/ControllerEndpointRouteBuilderExtensions.cs

  https://github.com/dotnet/aspnetcore/blob/c925f99cddac0df90ed0bc4a07ecda6b054a0b02/src/Mvc/Mvc.Core/src/Routing/ControllerActionEndpointDataSourceFactory.cs#L10

  顺着代码看下GetRequiredService中都是实体类已经类是internal。这注册相关的代码好像不太好重写。

  那只能看匹配的相关代码试试。

  匹配相关源码地址:

  https://github.com/aspnet/Routing/blob/c28c7dea4e866ec5a0d33f0e290bc49baadb1c85/src/Microsoft.AspNetCore.Routing/EndpointRoutingMiddleware.cs

  https://github.com/aspnet/Routing/blob/c28c7dea4e866ec5a0d33f0e290bc49baadb1c85/src/Microsoft.AspNetCore.Routing/Matching/DfaMatcherFactory.cs#L9

  在DfaMatcherFactory中有一段代码:

  

 1 public override Matcher CreateMatcher(EndpointDataSource dataSource)
 2         {
 3             if (dataSource == null)
 4             {
 5                 throw new ArgumentNullException(nameof(dataSource));
 6             }
 7 
 8             return new DataSourceDependentMatcher(dataSource, () =>
 9             {
10                 return _services.GetRequiredService<DfaMatcherBuilder>();
11             });
12         }
View Code

   看着可以重写MatcherFactory对应的实现来达到目的。但是写完不知道对默认实现有没有影响,需要大量测试,有点耗时间。准备找另外一种解决方法。

3、另一种思路

  既然重写有点耗时,那如果把已经注册好的endpoints中影响匹配的endpoint删掉不就行了。在源码中可以看到,endpoint都是放在EndpointDataSource中。

4、问题解决

  在app.UseEndpoints(endpoints => 中的endpoints 有一个DataSources属性,类型是ICollection<EndpointDataSource>实际类型是List。遍历DataSource中Endpoints,找到需要删除的endpoint,然后将其删除即可。然后使用MapWhen单独注册这连个action路由即可。

5、net 5 下问题再现

   在将.net core 3.1 发布到线上后。准备将项目升级到.net 5。在升级到.net 5后,那两个接口再请求时候再次报【The request matched multiple endpoints】。翻看官方.net core 升级.net 5 文档,上面也没有提endpoint相关逻辑修改。我只能进行调试,看看Startup.Configure中UseEndpoints有什么变化。经过仔细对比发现MapWhen中endpoints.DataSources有变化。只能再次修改MapWhen中endpoints.DataSources将问题解决

6、最后

  上面的解决方法不怎么优雅,下面有空还是找找重写EndpointRoutingMiddleware中相关代码来进行实现。各位大神有什么好的方法也可以评论一下。

原文地址:https://www.cnblogs.com/gsjlovenet/p/14394939.html