ActualLab / Fusion

MIT License
76 stars 11 forks source link

đź’‰Problem Initializing Session with Dependency Injection in Blazor Server Project #26

Open neozhu opened 1 month ago

neozhu commented 1 month ago

Hello @alexyakunin, I'm working on integrating the Fusion library into my Blazor Server project to enable real-time interaction. I have already implemented user login and authentication using Identity.EntityFrameworkCore. However, I'm encountering an issue when injecting the Session service into a Blazor component.

Error: When I try to inject the Session instance using the following syntax:

@inject Session Session
...
@Session.Id

I get the following error message:

System.InvalidOperationException: Property Session is not initialized.

image

Configuration Code for Fusion Service:

 // Fusion services
 var fusion= services.AddFusion();
 fusion.AddOperationReprocessor();
 fusion.AddAuthService<InMemoryAuthService>();
 fusion.AddBlazor().AddAuthentication().AddPresenceReporter();
 fusion.AddInMemoryKeyValueStore();
 fusion.AddService<IUserSessionTracker, UserSessionTracker>();
 fusion.AddService<IOnlineUserTracker, OnlineUserTracker>();

Project Information:

Framework: Blazor Server Identity Integration: Identity.EntityFrameworkCore is used for user login and authentication.

Additional Information: If there are additional configurations or a different approach to session management that I should consider, I would greatly appreciate any advice on implementing this correctly.

Thank you for your assistance!

neozhu commented 1 month ago

I have implemented a feature in my project that tracks active sessions for each Blazor component a user accesses. Here’s the relevant code:

public class UserSessionTracker : IUserSessionTracker
{

    private volatile ImmutableDictionary<string, ImmutableHashSet<string>> _pageUserSessions = ImmutableDictionary<string, ImmutableHashSet<string>>.Empty;

    public async Task AddUserSession(string pageComponent, string userName, CancellationToken cancellationToken = default)
    {
        if (Invalidation.IsActive)
            return;
        if (_pageUserSessions.TryGetValue(pageComponent, out var existingUsers))
        {
            if (!existingUsers.Contains(userName))
            {
                var updatedUsers = existingUsers.Add(userName);
                _pageUserSessions = _pageUserSessions.SetItem(pageComponent, updatedUsers);
            }
        }
        else
        {
            _pageUserSessions = _pageUserSessions.Add(pageComponent, ImmutableHashSet.Create(userName));
        }
        using var invalidating = Invalidation.Begin();
         _ = await GetUserSessions(cancellationToken).ConfigureAwait(false);

    }

    public virtual  Task<(string PageComponent, string[] UserSessions)[]> GetUserSessions(CancellationToken cancellationToken = default)
    {
        return Task.FromResult(_pageUserSessions.Select(kvp => (kvp.Key, kvp.Value.ToArray())).ToArray());
    }

    public async Task RemoveUserSession(string pageComponent, string userName, CancellationToken cancellationToken = default)
    {
        if (Invalidation.IsActive)
            return;
        if (_pageUserSessions.TryGetValue(pageComponent, out var users) && users.Contains(userName))
        {
            var updatedUsers = users.Remove(userName);
            if (updatedUsers.IsEmpty)
            {
                _pageUserSessions = _pageUserSessions.Remove(pageComponent);
            }
            else
            {
                _pageUserSessions = _pageUserSessions.SetItem(pageComponent, updatedUsers);
            }
        }

        using var invalidating = Invalidation.Begin();
        _ = await GetUserSessions(cancellationToken).ConfigureAwait(false);
    }
}

The purpose of this code is to notify users when multiple users are viewing the same page simultaneously, creating a collaborative experience. This functionality is working well; however, I would like to leverage Fusion’s Session to differentiate between unique users more reliably. This is why I attempted to inject Session but encountered the initialization error above.