Invoking SignalR Hub not working for Asp.Net Core Web API

泪湿孤枕 提交于 2020-06-27 09:10:29

问题


I'm a newb to SignalR. I'm trying to set up a Asp.Net Core WebAPI so that other clients can connect to it using SignalR and get real-time data. My Hub class is:

public class TimeHub : Hub
{
    public async Task UpdateTime(string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", message);
    }
}

I have a relay class as follows:

public class TimeRelay : ITimeRelay
{
    private readonly IHubContext<TimeHub> _timeHubContext;

    public TimeRelay(IHubContext<TimeHub> context)
    {

        _timeHubContext = context;
        Task.Factory.StartNew(async () =>
        {
            while (true)
            {
                await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());
                Thread.Sleep(2000);
            }
        });
    }
}

Startup class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddSignalR();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();

    app.UseSignalR((x) =>
    {
        x.MapHub<TimeHub>("/timeHub");
    });
    app.UseMvc();
}

The client is a console application and the code is:

class Program
{    
    static Action<string> OnReceivedAction = OnReceived;

    static void Main(string[] args)
    {
        Connect();
        Console.ReadLine();
    }

    private static async void Connect()
    {
        var hubConnectionBuilder = new HubConnectionBuilder();

        var hubConnection = hubConnectionBuilder.WithUrl("http://localhost:60211/timeHub").Build();

        await hubConnection.StartAsync();

        var on = hubConnection.On("ReceiveMessage", OnReceivedAction);

        Console.ReadLine();    
        on.Dispose();
        await hubConnection.StopAsync();
    }

    static void OnReceived(string message)
    {
        System.Console.WriteLine($"{message}");
    }
}

I tried debugging the application. The client got connected to the TimeHub succesfully. The no of connections in Clients.All changed from 0 to 1, when the client got connected. But, when await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString()); is executed, the UpdateTime function in TimeHub is not getting executed and the client is not getting any message.

I tried using "UpdateTime", "SendMessage", and "ReceiveMessage" as method in Clients.All.SendAsync in TimeRelay class. Nothing worked. Could someone point out my mistake in this.


回答1:


For Clients, it will be null if there is no client connecting to server. For starting Asp.Net Core SignalR and Console App at the same time, the Clients may be null since Index may be called before Console App connects the signalR server.

Try steps below:

  1. Change TimeHub

    public class TimeHub: Hub
    {
    public async Task UpdateTime(string message)
    {
        if (Clients != null)
        {
            await Clients.All.SendAsync("ReceiveMessage", message);
        }
    }
    }
    
  2. Register TimeHub

     services.AddSingleton<TimeHub>();  
    
  3. Controller

     public class HomeController : Controller
    {
    private readonly TimeHub _timeHub;
    public HomeController(TimeHub timeHub)
    {
        _timeHub = timeHub;
    }
    public IActionResult Index()
    {
        Task.Factory.StartNew(async () =>
        {
            while (true)
            {
                try
                {
                    await _timeHub.UpdateTime(DateTime.Now.ToShortDateString());
                    Thread.Sleep(2000);
                }
                catch (Exception ex)
                {
    
                }
            }
        });
        return View();
    }
    



回答2:


I got it to work and thought I will answer it here. Thanks @TaoZhou for the tip.

My mistake was sending "UpdateTime" from server and waiting on "ReceiveMessage" at the client.

Ideally the code should look like the following:

SignalR Server:
await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());

SignalR Client:
var on = hubConnection.On("UpdateTime", OnReceivedAction);

In this case any message send from the server would be received at the client instantly.
Please refer the code provided in the question for more info.



来源:https://stackoverflow.com/questions/51968201/invoking-signalr-hub-not-working-for-asp-net-core-web-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!