Использовать методы концентратора от контроллера?
Я использую SignalR 2, и я не могу понять, как я могу использовать методы Hub, например, изнутри действия контроллера.
Я знаю, что могу сделать следующее:
var hub = GlobalHost.ConnectionManager.GetHubContext<T>();
hub.Clients.All.clientSideMethod(param);
Но этот метод выполняется непосредственно на стороне клиента.
Что делать, если у меня есть бизнес-логика внутри моего метода ClientSideMethod(param)
на стороне сервера. Я хочу вызвать из моего контроллера так же, как при вызове с клиентской стороны?
В данный момент я использую public static void ClientSideMethod(param)
внутри своего концентратора, и в этом методе я использую IHubContext
из ConnectionManager
.
Не лучше ли этого сделать?
Следующие действия не работают (больше в SignalR 2?):
var hubManager = new DefaultHubManager(GlobalHost.DependencyResolver);
instance = hubManager.ResolveHub(typeof(T).Name) as T;
instance.ClientSideMethod(param);
Там, где я получаю доступ к Клиентам, я получаю исключение "Концентратор, не созданный по конвейеру конвейера не поддерживается".
Ответы
Ответ 1
Поскольку я не нашел "хорошего решения", я использую решение @michael.rp с некоторыми улучшениями:
Я создал следующий базовый класс:
public abstract class Hub<T> : Hub where T : Hub
{
private static IHubContext hubContext;
/// <summary>Gets the hub context.</summary>
/// <value>The hub context.</value>
public static IHubContext HubContext
{
get
{
if (hubContext == null)
hubContext = GlobalHost.ConnectionManager.GetHubContext<T>();
return hubContext;
}
}
}
И затем в фактическом концентраторе (например, public class AdminHub : Hub<AdminHub>
) у меня есть (статические) методы, например:
/// <summary>Tells the clients that some item has changed.</summary>
public async Task ItemHasChangedFromClient()
{
await ItemHasChangedAsync().ConfigureAwait(false);
}
/// <summary>Tells the clients that some item has changed.</summary>
public static async Task ItemHasChangedAsync()
{
// my custom logic
await HubContext.Clients.All.itemHasChanged();
}
Ответ 2
Это может сработать для создания класса "помощника", который реализует ваши бизнес-правила и вызывается как вашим концентратором, так и вашим контроллером:
public class MyHub : Hub
{
public void DoSomething()
{
var helper = new HubHelper(this);
helper.DoStuff("hub stuff");
}
}
public class MyController : Controller
{
public ActionResult Something()
{
var hub = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
var helper = new HubHelper(hub);
helper.DoStuff("controller stuff");
}
}
public class HubHelper
{
private IHubConnectionContext hub;
public HubHelper(IHubConnectionContext hub)
{
this.hub = hub;
}
public DoStuff(string param)
{
//business rules ...
hub.Clients.All.clientSideMethod(param);
}
}