HubFilter should act the same way as an API middleware
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 281
Description
I have an IUserResolver service and an IUserAccessor service inside my API.
When using normal API request, I have a middleware that has the job of resolving the current user and setting it in the IUserAccessor service. This middleware works well and is scoped for the current request.
However, when trying the same thing with IHubFilter, I get very different results. Here's my filter.
```cs
public class UserResolverFilter : IHubFilter
{
private IUserResolverService _userResolverService;
private IUserAccessorService _userAccessorService;
private readonly ILogger _logger;
public UserResolverFilter(IUserResolverService userResolverService, IUserAccessorService userAccessorService, ILogger logger)
{
_userResolverService = userResolverService;
_userAccessorService = userAccessorService;
_logger = logger;
}
public async ValueTask InvokeMethodAsync(
HubInvocationContext invocationContext,
Func> next
)
{
return await next(invocationContext);
}
public async Task OnConnectedAsync(HubLifetimeContext context, Func next)
{
var accessToken = await _userResolverService.ResolveAccessTokenAsync();
var user = await _userResolverService.ResolveAsync();
_userAccessorService.AccessToken = accessToken;
_userAccessorService.User = user;
if (user == null)
{
_logger.LogDebug($"Unauthenticated user with connectionId {context.Context.ConnectionId} connected");
}
else
{
_logger.LogDebug($"Authenticated User {_userAccessorService.User.UserName} with connectionId {context.Context.ConnectionId} connected");
}
await next(context);
}
public async Task OnDisconnectedAsync(
HubLifetimeContext context, Exception exception, Func next)
{
if (_userAccessorService.User == null)
{
_logger.LogDebug($"Unauthenticated user with connectionId {context.Context.ConnectionId} disconnected");
}
else
{
_logger.LogDebug($"Authenticated User {_userAccessorService.User.UserName} with connectionId {context.Context.ConnectionId} disconnected");
}
await next(context, exception);
}
```
And my hub
```cs
public class SessionHub : Hub
{
private readonly ISessionService _sessionService;
public classSessionHub (
ISessionService sessionService
)
{
_sessionService= sessionService;
}
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
await _sessionService.CreateAsync(Context.ConnectionId);
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await _sessionService.DeleteAsync(Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
```
Now my ISessionService calls injects my IUserAccessor service and when is constructed, assings the user to a public variable. The problem is that when the constructor is called, the filter has not been executed yet, which is really different of the middleware logic, making assigning null to my user variable.
Is there a way to unify this behaviour so that we can have the same exact "middleware" DI logic for hub filters^
Contributor guide
Assessment
This issue has not been assessed yet.