How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1?

ぐ巨炮叔叔 提交于 2019-12-21 05:22:32

问题


How can I pass a SignalR hub context to a Hangfire job on ASP .NET Core 2.1?

It seems that since passing arguments to Hangfire is done via serialization/deserialization, it seems that Hangfire has hard-time reconstructing the SignalR hub context.

I schedule the job (in my controller) using :

BackgroundJob.Schedule(() => _hubContext.Clients.All.SendAsync(
        "MyMessage",
        "MyMessageContent", 
        System.Threading.CancellationToken.None), 
    TimeSpan.FromMinutes(2));

Then after 2 minutes, when the job tries to execute, I have the error :

Newtonsoft.Json.JsonSerializationException: Could not create an instance of type Microsoft.AspNetCore.SignalR.IClientProxy. Type is an interface or abstract class and cannot be instantiated.

Any idea?

Update 1

I ended up using a static context defined in Startup.cs, and assigned from Configure()

hbctx = app.ApplicationServices.GetRequiredService<IHubContext<MySignalRHub>>(); 

So now Hangfire schedules instead a hub helper that uses the static context :

BackgroundJob.Schedule(() => new MyHubHelper().Send(), TimeSpan.FromMinutes(2)); 

and the hub helper gets the context with Startup.hbctx

Even though this is working, it is a little smelly

Update 2

I tried also using the approach in Access SignalR Hub without Constructor Injection:

My background job scheduling became :

BackgroundJob.Schedule(() => Startup.GetService().SendOutAlert(2), TimeSpan.FromMinutes(2));

However this time, I have an exception when I reach the above line:

An unhandled exception has occurred while executing the request System.ObjectDisposedException: Cannot access a disposed object. Object name: 'IServiceProvider'.

Update 3

Thanks all. The solution was to create a helper that gets the hubcontext via its constructor via DI, and then using hangfire to schedule the helper method Send as the background job.

public interface IMyHubHelper
{
    void SendOutAlert(String userId);
}

public class MyHubHelper : IMyHubHelper
{
    private readonly IHubContext<MySignalRHub> _hubContext;

    public MyHubHelper(IHubContext<MySignalRHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public void SendOutAlert(String userId)
    {
        _hubContext.Clients.All.SendAsync("ReceiveMessage", userId, "msg");
    }
}

Then launching the background job from anywhere with :

BackgroundJob.Schedule<MyHubHelper>( x => x.SendOutAlert(userId), TimeSpan.FromMinutes(2));

回答1:


The answer from Nkosi suggesting to use Schedule<T> generics pointed me to the final solution I used:

First, my MySignalRHub is just an empty class inheriting from Hub.

public class MySignalRHub 
{
}

Then, I created a hub helper which maintains a hubcontext on my MySignalRHub. The hubcontext is injected in the helper class via the ASP.Net Core built-in DI mechanism (as explained here).

The helper class:

public class MyHubHelper : IMyHubHelper
{
    private readonly IHubContext<MySignalRHub> _hubContext;

    public MyHubHelper(IHubContext<MySignalRHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public void SendData(String data)
    {
        _hubContext.Clients.All.SendAsync("ReceiveMessage", data);
    }
}

The helper interface:

public interface IMyHubHelper
{
    void SendData(String data);
}

Finally, I can use hangfire to schedule from anywhere in the code the method SendData() of the hub helper as a background job with:

BackgroundJob.Schedule<MyHubHelper>(h => h.SendData(myData), TimeSpan.FromMinutes(2));



回答2:


Using Schedule<T> generics you should be able to take advantage of the dependency injection capabilities of the framework.

BackgroundJob.Schedule<IHubContext<MySignalRHub>>(hubContext => 
    hubContext.Clients.All.SendAsync(
        "MyMessage",
        "MyMessageContent", 
        System.Threading.CancellationToken.None), 
    TimeSpan.FromMinutes(2));


来源:https://stackoverflow.com/questions/53538213/how-can-i-pass-a-signalr-hub-context-to-a-hangfire-job-on-asp-net-core-2-1

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