I am using SignalR 2 and I can not figure out how I can use my Hub methods e.g from inside a controller action.
I know I can do the following:
var hub = GlobalHost.ConnectionManager.GetHubContext<T>();
hub.Clients.All.clientSideMethod(param);
But that executes the method directly on the client side.
What if I have business logic inside my server side ClientSideMethod(param)
method I want to call from my controller the same way as when it is called from the client side?
At the moment I use public static void ClientSideMethod(param)
inside my hub and in that method I use the IHubContext
from the ConnectionManager
.
Is there no better was of doing this?
The following is not working (anymore in SignalR 2?):
var hubManager = new DefaultHubManager(GlobalHost.DependencyResolver);
instance = hubManager.ResolveHub(typeof(T).Name) as T;
instance.ClientSideMethod(param);
There I get a "Hub not created via Hub pipeline not supported" exception, when accessing the Clients.
What is a SignalR hub. The SignalR Hubs API enables you to call methods on connected clients from the server. In the server code, you define methods that are called by client. In the client code, you define methods that are called from the server.
The IHubContext is for sending notifications to clients, it is not used to call methods on the Hub . View or download sample code (how to download)
Or you can also add SignalR to a project by opening the "Tools" | "Library Package Manager" | "Package Manager Console" and running the command: "install-package Microsoft. AspNet. SignalR". Now again add the SignalR class.
It might work to create a "helper" class that implements your business rules and is called by both your Hub and your Controller:
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);
}
}
As I did not find a "good solution" I am using @michael.rp's solution with some improvements:
I did create the following base class:
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;
}
}
}
And then in the actual Hub (e.g. public class AdminHub : Hub<AdminHub>
) I have (static) methods like the following:
/// <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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With