diff --git a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs index 541b36aa14..bbaa45a26e 100644 --- a/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.SignalR/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRModule.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Connections; @@ -54,10 +55,17 @@ public class AbpAspNetCoreSignalRModule : AbpModule .GetRequiredService>() .Value; + var hubWithRoutePatterns = new List>(); foreach (var hubConfig in signalROptions.Hubs) { routePatterns.AddIfNotContains(hubConfig.RoutePattern); + if (hubWithRoutePatterns.Any(x => x.Key == hubConfig.HubType && x.Value == hubConfig.RoutePattern)) + { + throw new AbpException($"The hub type {hubConfig.HubType.FullName} is already registered with route pattern {hubConfig.RoutePattern}"); + } + + hubWithRoutePatterns.Add(new KeyValuePair(hubConfig.HubType, hubConfig.RoutePattern)); MapHubType( hubConfig.HubType, endpointContext.Endpoints, diff --git a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo.Abp.AspNetCore.SignalR.Tests.csproj b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo.Abp.AspNetCore.SignalR.Tests.csproj index cf784b8917..8a1bcfcb9e 100644 --- a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo.Abp.AspNetCore.SignalR.Tests.csproj +++ b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo.Abp.AspNetCore.SignalR.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRTestModule.cs b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRTestModule.cs index 4bb545007b..f0c056c784 100644 --- a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRTestModule.cs +++ b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpAspNetCoreSignalRTestModule.cs @@ -1,14 +1,34 @@ -using Volo.Abp.Autofac; +using System; +using Microsoft.AspNetCore.Builder; +using Volo.Abp.AspNetCore.TestBase; +using Volo.Abp.Autofac; using Volo.Abp.Modularity; namespace Volo.Abp.AspNetCore.SignalR; [DependsOn( typeof(AbpAspNetCoreSignalRModule), - typeof(AbpTestBaseModule), + typeof(AbpAspNetCoreTestBaseModule), typeof(AbpAutofacModule) )] public class AbpAspNetCoreSignalRTestModule : AbpModule { + public static Exception UseConfiguredEndpointsException { get; set; } + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + var app = context.GetApplicationBuilder(); + + app.UseRouting(); + + UseConfiguredEndpointsException = null; + try + { + app.UseConfiguredEndpoints(); + } + catch (Exception e) + { + UseConfiguredEndpointsException = e; + } + } } diff --git a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions_Tests.cs b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions_Tests.cs index f0ee46594b..3cfc928b02 100644 --- a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions_Tests.cs +++ b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/AbpSignalROptions_Tests.cs @@ -1,11 +1,13 @@ -using Microsoft.Extensions.Options; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Shouldly; using Volo.Abp.AspNetCore.SignalR.SampleHubs; using Xunit; namespace Volo.Abp.AspNetCore.SignalR; -public class AbpSignalROptions_Tests : AbpAspNetCoreSignalRTestBase +public class AbpSignalROptions_Tests : AbpAspNetCoreTestBase { private readonly AbpSignalROptions _options; @@ -14,12 +16,74 @@ public class AbpSignalROptions_Tests : AbpAspNetCoreSignalRTestBase _options = GetRequiredService>().Value; } - [Fact(Skip = "Can not run this test since AspNet Core environment has not been properly set!")] + protected override void ConfigureServices(IServiceCollection services) + { + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + } + + [Fact] public void Should_Auto_Add_Maps() { _options.Hubs.ShouldContain(h => h.HubType == typeof(RegularHub)); _options.Hubs.ShouldContain(h => h.HubType == typeof(RegularAbpHub)); _options.Hubs.ShouldNotContain(h => h.HubType == typeof(DisableConventionalRegistrationHub)); _options.Hubs.ShouldNotContain(h => h.HubType == typeof(DisableAutoHubMapHub)); + _options.Hubs.ShouldContain(h => h.HubType == typeof(RegularHubClass1)); + _options.Hubs.ShouldContain(h => h.HubType == typeof(RegularHubClass12)); + _options.Hubs.ShouldContain(h => h.HubType == typeof(RegularHubClass2)); + _options.Hubs.ShouldContain(h => h.HubType == typeof(RegularHubClass22)); + } +} + +[Collection("AbpAspNetCoreSignalR")] +public class AbpSignalSameRroutePattern_Tests : AbpAspNetCoreTestBase +{ + protected override void ConfigureServices(IServiceCollection services) + { + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + } + + [Fact] + public void Should_Throw_Exception_If_HubType_Has_Same_RoutePattern() + { + AbpAspNetCoreSignalRTestModule.UseConfiguredEndpointsException.ShouldNotBeNull(); + AbpAspNetCoreSignalRTestModule.UseConfiguredEndpointsException.Message.ShouldBe($"The hub type {typeof(RegularHubClass12).FullName} is already registered with route pattern {HubRouteAttribute.GetRoutePattern(typeof(RegularHubClass12))}"); + } +} + +[Collection("AbpAspNetCoreSignalR")] +public class AbpSignalDifferentRroutePattern_Tests : AbpAspNetCoreTestBase +{ + protected override void ConfigureServices(IServiceCollection services) + { + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.Configure(options => + { + var firstHub = options.Hubs.FirstOrDefault(x => x.HubType == typeof(RegularHubClass22)); + if (firstHub != null) + { + firstHub.RoutePattern = "/signalr-hubs/regular-hub-class-22"; + } + + var lastHub = options.Hubs.LastOrDefault(x => x.HubType == typeof(RegularHubClass22)); + if (lastHub != null) + { + lastHub.RoutePattern = "/signalr-hubs/regular-hub-class-22-1"; + } + }); + } + + [Fact] + public void Should_Work_If_Same_HubType_Has_Different_RoutePattern() + { + AbpAspNetCoreSignalRTestModule.UseConfiguredEndpointsException.ShouldBeNull(); } } diff --git a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/Program.cs b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/Program.cs new file mode 100644 index 0000000000..b01b1eaf97 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/Program.cs @@ -0,0 +1,10 @@ +using Microsoft.AspNetCore.Builder; +using Volo.Abp.AspNetCore.SignalR; +using Volo.Abp.AspNetCore.TestBase; + +var builder = WebApplication.CreateBuilder(); +await builder.RunAbpModuleAsync(); + +public partial class Program +{ +} diff --git a/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/SampleHubs/RegularHubBase.cs b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/SampleHubs/RegularHubBase.cs new file mode 100644 index 0000000000..daf8cfe1e5 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.SignalR.Tests/Volo/Abp/AspNetCore/SignalR/SampleHubs/RegularHubBase.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.SignalR; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.AspNetCore.SignalR.SampleHubs; + +public abstract class RegularHubBase : Hub where THub : class +{ + +} + +[DisableConventionalRegistration] +[ExposeServices(typeof(RegularHubClass1))] +public class RegularHubClass1 : RegularHubBase +{ + +} + +[DisableConventionalRegistration] +[ExposeServices(typeof(RegularHubClass12), typeof(RegularHubClass1))] +public class RegularHubClass12 : RegularHubClass1 +{ + +} + +[DisableConventionalRegistration] +[ExposeServices(typeof(RegularHubClass2))] +public class RegularHubClass2 : RegularHubBase +{ + +} + +[DisableConventionalRegistration] +[ExposeServices(typeof(RegularHubClass22), typeof(RegularHubClass2))] +public class RegularHubClass22 : RegularHubClass2 +{ + +}