asp.net - tag - ¿Usar los métodos de Hub desde el controlador?
tag helper asp for (2)
Estoy usando SignalR 2 y no puedo entender cómo puedo usar mis métodos de Hub, por ejemplo, desde dentro de una acción del controlador.
Sé que puedo hacer lo siguiente:
var hub = GlobalHost.ConnectionManager.GetHubContext<T>();
hub.Clients.All.clientSideMethod(param);
Pero eso ejecuta el método directamente en el lado del cliente.
¿Qué ClientSideMethod(param)
si tengo lógica de negocios dentro del método ClientSideMethod(param)
lado del servidor que deseo llamar desde mi controlador de la misma manera que cuando se llama desde el lado del cliente?
En este momento, utilizo public static void ClientSideMethod(param)
dentro de mi hub y en ese método utilizo el IHubContext
del ConnectionManager
.
¿No hay mejor manera de hacer esto?
Lo siguiente no funciona (¿ya en SignalR 2?):
var hubManager = new DefaultHubManager(GlobalHost.DependencyResolver);
instance = hubManager.ResolveHub(typeof(T).Name) as T;
instance.ClientSideMethod(param);
Allí obtengo una excepción de "Hub no creado a través de Hub pipeline no compatible", al acceder a los Clientes.
Como no encontré una "buena solución", estoy usando la solución de @ michael.rp con algunas mejoras:
Creé la siguiente clase base:
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;
}
}
}
Y luego, en el Hub real (por ejemplo, public class AdminHub : Hub<AdminHub>
) tengo métodos (estáticos) como los siguientes:
/// <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();
}
Podría funcionar para crear una clase de "ayudante" que implemente sus reglas de negocio y sea llamada tanto por su concentrador como por su controlador:
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);
}
}