2015-11-16 20 views
8

Chcę statycznie przechowywać informacje o użytkowniku przez cały okres istnienia żądania SignalR. Zrobiłem to w WebAPI używając HttpContext.Current.Items, ale to nie istnieje w SignalR.Per-Request dane statyczne w Signalr

Wiem, że ThreadStatic nie będzie działał, ponieważ wątek SignalR może być współużytkowany przez wiele żądań.

Dla porównania jestem gospodarzem go w IIS i korzystania z najnowszej wersji SignalR (2.2.0)

+0

Większość rozwiązań dotyczy innej, bardziej trwałej klasy lub słownika w szczypie. Czy próbowałeś 'Dictionary ', mapując ConnectionIDs na dowolne dane, które chcesz śledzić? Dodaj ludzi w 'OnConnect', usuń je w' OnDisconnect'. –

Odpowiedz

0

Jest to z pewnością bardzo późno do odpowiedzi na to pytanie, a może masz już zorientowali się, co do tego. To tylko próba podzielenia się moją myślą o tym problemie.

Po pierwsze, można włączyć uwierzytelnianie dla SignalR, a następnie można użyć Context.User.xxx w swoich metodach koncentratora.

Dla umożliwienia authentication for all hubs można zrobić coś takiego:

public partial class Startup { 
    public void Configuration(IAppBuilder app) { 
     app.MapSignalR(); 
     GlobalHost.HubPipeline.RequireAuthentication(); 
    } 
} 

Gdy to zrobisz, że można nadal używać zwykłego uwierzytelniania rurociągu do uwierzytelnienia swoich żądań, a te informacje będą dostarczane do Hub metod poprzez Context.User nieruchomości . Poniżej znajduje się jeden przykład z here.

public async Task JoinRoom(string roomName) 
{ 
    await Groups.Add(Context.ConnectionId, roomName); 
    Clients.Group(roomName).addChatMessage(Context.User.Identity.Name + " joined."); 
} 

Wraz z tym można zachować dane poszczególnych użytkowników w pamięci out-of-memory (tak, że można go skalować), takie jak cache Redis lub coś podobnego.

Lub jako alternatywne podejście, można również przedłużyć HubPipelineModule i utworzyć custom one, aby uzyskać bardziej szczegółową kontrolę nad zdarzeniami.

public class LoggingPipelineModule : HubPipelineModule 
{ 
    protected override bool OnBeforeIncoming(IHubIncomingInvokerContext context) 
    { 
     return base.OnBeforeIncoming(context); 
    } 
    protected override bool OnBeforeOutgoing(IHubOutgoingInvokerContext context) 
    { 
     return base.OnBeforeOutgoing(context); 
    } 
} 

public void Configuration(IAppBuilder app) 
{ 
    GlobalHost.HubPipeline.AddModule(new LoggingPipelineModule()); 
    app.MapSignalR(); 
} 

Mam nadzieję, że to pomoże. Warto również wiedzieć, jak poradziłeś sobie z problemem.