简体   繁体   中英

SignalR - Multitenant Dependency Injection

I need to resolve a DbContext based on tenant's owin value. But in the pipeline of method OnDisconnected of hub, the HttpContext is not accessible .

My hub class:

public class UserTrackingHub : Hub
{
    private readonly UserContext _context;

    public UserTrackingHub(UserContext context) { ... }

    public override async Task OnConnected() { /* OK HERE...*/ }

    public override async Task OnDisconnected(bool stopCalled)
    {
        // NEVER FIRES WITH IF I USE THE CTOR INJECTION.

        var connection = await _context.Connections.FindAsync(Context.ConnectionId);
        if (connection != null)
        {
            _context.Connections.Remove(connection);
            await _context.SaveChangesAsync();
        }
    }
}

Here's my Autofac config:

    public static IContainer Register(IAppBuilder app)
    {
        var builder = new ContainerBuilder();

        // Other registers...

        builder.Register<UserContext>(c =>
        {    
            // Details and conditions omitted for brevity.

            var context = HttpContext.Current; // NULL in OnDisconnected pipeline.
            var owinContext = context.GetOwinContext();
            var tenant = owinContext.Environment["app.tenant"].ToString();
            var connection = GetConnectionString(tenant); 

            return new UserContext(connection);
        });

        var container = builder.Build();
        var config = new HubConfiguration
        {
            Resolver = new AutofacDependencyResolver(container)
        };

        app.MapSignalR(config);

        return container;
    }

Can someone help me to identify the tenant OnDisconnected in this or any other way?
Thanks!

For anyone interested, I end up injecting a context factory instead the context itself:

public class UserTrackingHub : Hub
{
    private readonly Func<string, UserContext> _contextFactory;

    public UserTrackingHub(Func<string, UserContext> contextFactory) { ... }

    public override async Task OnConnected() { ... }

    public override async Task OnDisconnected(bool stopCalled)
    {
        var tenant = Context.Request.Cookies["app.tenant"].Value;

        using (var context = _contextFactory.Invoke(tenant))
        {
            var connection = await context.Connections.FindAsync(Context.ConnectionId);
            if (connection != null)
            {
                context.Connections.Remove(connection);
                await context.SaveChangesAsync();
            }
        }
    }
}

And Autofac's config:

 // Resolve context based on tenant
 builder.Register<Func<string, UserContext>>(c => new Func<string, UserContext>(tenant => UserContextResolver.Resolve(tenant)));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM