Концентратор SignalR разрешает обнулить в обработчике подписки RabbitMQ в ASP.NET Core - PullRequest
1 голос
/ 29 мая 2019

У меня есть проект ASP.NET Core MVC с RabbitMQ (посредством EasyNetQ) и SignalR.

Далее у меня есть подписка на сообщение RabbitMQ, которое должно отправлять уведомление клиенту через SignalR.

Но, к сожалению, концентратор всегда разрешается на null.

Интересное наблюдение состоит в том, что, когда приложение все еще запускается и в очереди все еще остаются неподтвержденные сообщения, служба фактически разрешает толькохорошо.

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

Я подозреваю, что, возможно, я делаю что-то не так в отношении регистрации подписки внутри app.Use, но я не могу найти никаких полезных примеров, так что это было лучшее, что я могfigure.

Я на ASP.NET Core 3 Preview 5, я не знаю, имеет ли это какое-либо отношение к моей проблеме.

Итак, вопрос: как мне получитьконтекст хаба внутри обработчика подписки на сообщения?

ОБНОВЛЕНИЕ

Я проверил документы GetRequiredService , и вызов должен активировать бросокInvalidOperationException, если служба не может быть разрешена, но это не так.Он возвращает null, что, насколько я могу судить, не должно быть возможным (если контейнер по умолчанию не поддерживает регистрацию экземпляров с нулевым значением).

1 Ответ

1 голос
/ 29 мая 2019

Мне удалось решить проблему с помощью этой проблемы , применив вместо нее IHostedService.

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