Skip to content

Commit 857e35f

Browse files
Fix Dependency Injection Conflict with Null Parameter in SignalR Hub Methods (#61687)
1 parent 404fb15 commit 857e35f

File tree

3 files changed

+48
-27
lines changed

3 files changed

+48
-27
lines changed

src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,26 @@ private void ReplaceArguments(HubMethodDescriptor descriptor, HubMethodInvocatio
726726
var hubInvocationArgumentPointer = 0;
727727
for (var parameterPointer = 0; parameterPointer < arguments.Length; parameterPointer++)
728728
{
729-
if (hubMethodInvocationMessage.Arguments?.Length > hubInvocationArgumentPointer &&
729+
// populate the synthetic arguments first
730+
if (descriptor.IsServiceArgument(parameterPointer))
731+
{
732+
arguments[parameterPointer] = descriptor.GetService(scope.ServiceProvider, parameterPointer, descriptor.OriginalParameterTypes[parameterPointer]);
733+
}
734+
else if (descriptor.OriginalParameterTypes[parameterPointer] == typeof(CancellationToken))
735+
{
736+
cts = CancellationTokenSource.CreateLinkedTokenSource(connection.ConnectionAborted);
737+
arguments[parameterPointer] = cts.Token;
738+
}
739+
else if (isStreamCall && ReflectionHelper.IsStreamingType(descriptor.OriginalParameterTypes[parameterPointer], mustBeDirectType: true))
740+
{
741+
Log.StartingParameterStream(_logger, hubMethodInvocationMessage.StreamIds![streamPointer]);
742+
var itemType = descriptor.StreamingParameters![streamPointer];
743+
arguments[parameterPointer] = connection.StreamTracker.AddStream(hubMethodInvocationMessage.StreamIds[streamPointer],
744+
itemType, descriptor.OriginalParameterTypes[parameterPointer]);
745+
746+
streamPointer++;
747+
}
748+
else if (hubMethodInvocationMessage.Arguments?.Length > hubInvocationArgumentPointer &&
730749
(hubMethodInvocationMessage.Arguments[hubInvocationArgumentPointer] == null ||
731750
descriptor.OriginalParameterTypes[parameterPointer].IsAssignableFrom(hubMethodInvocationMessage.Arguments[hubInvocationArgumentPointer]?.GetType())))
732751
{
@@ -736,29 +755,8 @@ private void ReplaceArguments(HubMethodDescriptor descriptor, HubMethodInvocatio
736755
}
737756
else
738757
{
739-
if (descriptor.OriginalParameterTypes[parameterPointer] == typeof(CancellationToken))
740-
{
741-
cts = CancellationTokenSource.CreateLinkedTokenSource(connection.ConnectionAborted);
742-
arguments[parameterPointer] = cts.Token;
743-
}
744-
else if (descriptor.IsServiceArgument(parameterPointer))
745-
{
746-
arguments[parameterPointer] = descriptor.GetService(scope.ServiceProvider, parameterPointer, descriptor.OriginalParameterTypes[parameterPointer]);
747-
}
748-
else if (isStreamCall && ReflectionHelper.IsStreamingType(descriptor.OriginalParameterTypes[parameterPointer], mustBeDirectType: true))
749-
{
750-
Log.StartingParameterStream(_logger, hubMethodInvocationMessage.StreamIds![streamPointer]);
751-
var itemType = descriptor.StreamingParameters![streamPointer];
752-
arguments[parameterPointer] = connection.StreamTracker.AddStream(hubMethodInvocationMessage.StreamIds[streamPointer],
753-
itemType, descriptor.OriginalParameterTypes[parameterPointer]);
754-
755-
streamPointer++;
756-
}
757-
else
758-
{
759-
// This should never happen
760-
Debug.Assert(false, $"Failed to bind argument of type '{descriptor.OriginalParameterTypes[parameterPointer].Name}' for hub method '{descriptor.MethodExecutor.MethodInfo.Name}'.");
761-
}
758+
// This should never happen
759+
Debug.Assert(false, $"Failed to bind argument of type '{descriptor.OriginalParameterTypes[parameterPointer].Name}' for hub method '{descriptor.MethodExecutor.MethodInfo.Name}'.");
762760
}
763761
}
764762
}
@@ -896,4 +894,4 @@ private static void SetActivityError(Activity? activity, Exception ex)
896894
activity?.SetTag("error.type", ex.GetType().FullName);
897895
activity?.SetStatus(ActivityStatusCode.Error);
898896
}
899-
}
897+
}

src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTestUtils/Hubs.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,11 @@ public async Task<int> ServicesAndParams(int value, [FromService] Service1 servi
13811381
}
13821382
return total + value;
13831383
}
1384+
1385+
public int ServiceWithStringAttribute([FromService] Service1 service, string value)
1386+
{
1387+
return 115;
1388+
}
13841389

13851390
public int ServiceWithoutAttribute(Service1 service)
13861391
{
@@ -1464,4 +1469,4 @@ public override async Task OnConnectedAsync()
14641469
await Clients.Client(id).SendAsync("Test", 1);
14651470
}
14661471
}
1467-
}
1472+
}

src/SignalR/server/SignalR/test/Microsoft.AspNetCore.SignalR.Tests/HubConnectionHandlerTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4679,6 +4679,24 @@ public async Task HubMethodCanInjectService()
46794679
Assert.True(Assert.IsType<bool>(res.Result));
46804680
}
46814681
}
4682+
4683+
// Regression test for https://github.com/dotnet/aspnetcore/issues/61491
4684+
[Fact]
4685+
public async Task HubMethodCanInjectServiceWithNullParameter()
4686+
{
4687+
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(provider =>
4688+
{
4689+
provider.AddSingleton<Service1>();
4690+
});
4691+
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<ServicesHub>>();
4692+
4693+
using (var client = new TestClient())
4694+
{
4695+
var connectionHandlerTask = await client.ConnectAsync(connectionHandler).DefaultTimeout();
4696+
var res = await client.InvokeAsync(nameof(ServicesHub.ServiceWithStringAttribute),(string)null ).DefaultTimeout();
4697+
Assert.Equal(115L, res.Result);
4698+
}
4699+
}
46824700

46834701
[Fact]
46844702
public async Task HubMethodCanInjectMultipleServices()
@@ -5459,4 +5477,4 @@ public static async Task<IEnumerable<T>> ReadAllAsync<T>(this IAsyncEnumerable<T
54595477

54605478
return result;
54615479
}
5462-
}
5480+
}

0 commit comments

Comments
 (0)