SignalR hub resolves to null inside RabbitMQ subscription handler in ASP.NET Core

青春壹個敷衍的年華 提交于 2019-12-10 23:37:43

问题


I have an ASP.NET Core MVC project with RabbitMQ (by means of EasyNetQ) and SignalR.

Next, I have a subscription on a RabbitMQ message that should send a notification to the client via SignalR.

But sadly, the hub always resolves to null.

An interesting observation is that when the application is still starting and there are still unacknowledged messages in the queue, the service actually resolves just fine.

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.RegisterEasyNetQ("host=localhost;virtualHost=/");
}

public void Configure(IApplicationBuilder app)
{
    app.UseSignalR(route =>
    {
        route.MapHub<MyHub>("/mypath");
    });

    app.Use(async (context, next) =>
    {
        var bus = context.RequestServices.GetRequiredService<IBus>();

        bus.SubscribeAsync<MyMessage>("MySubscription", async message =>
        {
            var hubContext = context.RequestServices
                .GetRequiredService<IHubContext<MyHub>>();

            // hubContext is null 
            await hubContext.Clients.All.SendAsync("MyNotification");
        });

        await next.Invoke();
    });
}

I suspect that perhaps I'm doing something wrong with regards to registering the subscription inside an app.Use but I can't seem to find any useful examples so this was the best I could figure.

I'm on ASP.NET Core 3 preview 5, I don't know if that has anything to do with my problem.

So the question is: how do I get the hub context inside the message subscription handler?

UPDATE

I've checked the GetRequiredService docs and the call should actuall throw an InvalidOperationException if the service couldn't be resolved, but it doesn't. It returns null, which as far as I can tell, shouldn't be possible (unless the default container supports registration of null-valued instances).


回答1:


I've managed to solve the issue with help from this issue by implementing an IHostedService instead.

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.RegisterEasyNetQ("host=localhost;virtualHost=/");
    services.AddHostedService<MyHostedService>();
}

public void Configure(IApplicationBuilder app)
{
    app.UseSignalR(route =>
    {
        route.MapHub<MyHub>("/mypath");
    });    
}

public class MyHostedService : BackgroundService
{
    private readonly IServiceScopeFactory _serviceScopeFactory;

    public ServiceBusHostedService(IServiceScopeFactory serviceScopeFactory)
    {
        _serviceScopeFactory = serviceScopeFactory;
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var scope = _serviceScopeFactory.CreateScope();
        var bus = scope.ServiceProvider.GetRequiredService<IBus>();

        bus.SubscribeAsync<MyMessage>("MySubscription", async message =>
        {
            var hubContext = scope.ServiceProvider.GetRequiredService<IHubContext<MyHub>>();

            await hubContext.Clients
                .All
                .SendAsync("MyNotification", cancellationToken: stoppingToken);
        });

        return Task.CompletedTask;
    }
}


来源:https://stackoverflow.com/questions/56360983/signalr-hub-resolves-to-null-inside-rabbitmq-subscription-handler-in-asp-net-cor

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