简体   繁体   中英

How to use SignalR 2 with WEB API, calling SignalR methods from API and from Clients

I've been struggling for the past two days on how to get SignalR 2 to work with Web API. I tried to follow a few tutorials, from Microsoft and from others, about the topic, but still took me time to understand where I was wrong. I'm posting this question to help someone else that ends up in the same situation I was on.

I needed to create a Hub on SignalR that could respond to a Console Application (C#) and a Web App (AngularJs) as clients, and I also needed it to send signals after a certain method on API being hit.

I followed these (and others) tutorials:

ASP.NET SignalR Hubs API Guide - Server (C#)

ASP.NET SignalR Hubs API Guide - .NET Client (C#)

Stream Web API Transactions Using SignalR

And some more, but those are the best I could find. Also, a dozen of others questions, here and on other sites.

The best I could come up with was a solution that only answered to the API method being hit, but the clients wasn't able to fire any of the Hub's methods (they could only listen to it).

This was my Hub's code:

public class MyHub : Hub
{
    private static IHubContext hubContext =
    GlobalHost.ConnectionManager.GetHubContext<MyHub>();

    public static void GetStatus(string message)
    {
        hubContext.Clients.All.acknowledgeMessage($"GetStatus: {message}");
    }

    public void GetMessage(string message)
    {
        hubContext.Clients.User(id).acknowledgeMessage($"GetStatus: {message}");            
    }
}

And my question was: How can I make the clients hit those methods on Hub, so they can get some personal response, if needed?

Ok, so the main problem here was that somewhere when I started, I found out how to make the Hub respond to API's methods (I couldn't find where by the time I'm posting this answer), and then I only found different ways for the clients to call the Hub's methods, and one did not work with the other. I could not set both to the same way.

This is the code from my API's controller:

public IHttpActionResult TesteComunicacao(string mensagem)
    {
        MyHub.GetStatus("Message here!");

        return Ok("ok");
    }

And the Hub's method:

// Use this for Server Methods
public static void GetStatus(string message)
    {
        hubContext.Clients.All.acknowledgeMessage($"GetStatus: {message}");
    }

This is the only way I found to make it happen. The hub will not respond with the method used by the clients. Those must have a different code, like this Hub's method here:

// Use this for Clients Methods
public void GetMessage(string message)
    {
        Clients.Caller.acknowledgeMessage($"GetMessage: {message}");

    }

I was trying to implement my " hubContext " solution on the clients method, but it wasn't working at all, and when I tried to implement the " Clients " solution, later found, to be consumed by my API, I had to make it a "non-static method", and then call it on the controller, which only resulted in this error: "using hubcontext outside hub pipeline is unsoported"

And then, I found this blessed answer here on Stack Overflow, that finaly showed me where I was wrong.

And that's exactly what I was doing wrong. I must implement then differently based on the method's objective. The ones to be consumed by my API use " hubContext ", and the ones to be consumed by my clients application use " Clients ".

I hope it helps other people struggling with this problem to find it faster, since the blessed answer there was about ASP.NET MVC, not Web API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM