Use Hub methods from controller?

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.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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);
    }
}

Method 2

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();
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x