У меня есть приложение ASP.NET MVC 5 с концентратором SignalR 2 и использующим автофак для DI.
Вся бизнес-логика инкапсулирована в классах менеджера на их собственном уровне. Некоторые методы менеджера нуждаются в информации о текущем вошедшем в систему пользователе (UserId, TenantId, ..).
Я решил эту проблему, внедрив AuthorizationProvider в каждый класс менеджера, которому нужна информация о пользователе.
public interface IAuthorizationProvider
{
long? GetUserId();
long? GteTenantId();
}
public class MyManager : IMyManager
{
private IAuthorizationProvider _authorizationProvider;
public MyManager(IAuthorizationProvider authorizationProvider)
{
_authorizationProvider = authorizationProvider;
}
public void MyMethod()
{
// Getting the User information here is pretty simple
long userId = _authorizationProvider.GetUserId();
}
}
Обычно я могу получить информацию о пользователе из HttpContext и из сеанса. Поэтому я написал SessionAuthorizationProvider:
public class SessionAuthorizationProvider{
public long? GetUserId()
{
HttpContext.Current?.Session?[SessionKeys.User]?.Id;
}
public long? GteTenantId() { ... }
}
Но теперь у меня есть новый метод в концентраторе SignalR, который использует тот же механизм.
[HubName("myHub")]
public class MyHub : Hub
{
private IMyManager _myManager;
public MyHub(IMyManager myManager)
{
_myManager = myManager;
}
[HubMethodName("myHubMethod")]
public void MyHubMethod(long userId, long tenantId)
{
_myManager.MyMethod();
}
}
Проблема в том, что в запросе SignalR нет сеанса. Поэтому я также установил необходимую пользовательскую информацию в методе концентратора в качестве параметров, передаваемых от клиента.
Поэтому я подумал, что лучшим решением для этой проблемы является написание нового AuthorizationProvider для SignalR и адаптация решателя зависимостей. Но я не могу получить текущего пользователя в новом SignalrAuthorizationProvider.
public class SignalrAuthorizationProvider{
public long? GetUserId()
{
// How to get the user information here???
}
public long? GteTenantId() { /* and here??? */ }
}
Есть ли рекомендуемое решение этой проблемы?
Конечно, я могу расширить MyMethod, чтобы принимать информацию о пользователе в качестве параметра. Но MyMethod вызывает другой метод из другого менеджера, и этот менеджер также вызывает другой метод. Информация о пользователе необходима только для последнего вызова метода. Поэтому мне пришлось изменить как минимум 3 метода и еще много в будущем.
Вот эскиз проблемы
Это потенциальное решение. Но это очень плохо