尝试激活“XXXXX”时无法解析类型“Microsoft.AspNetCore.SignalR.Hub`1[IXXXX]”的服务

问题描述 投票:0回答:3

我完全按照 MS 规则定义我的强类型 SignalR 集线器

public class OutputMessages : Hub<IOutputMessages>
{...}

用同样的方式将我的 SignalR hub 注入控制器

public class ApplicationAPIController : ControllerBase
{
     public ApplicationAPIController(IHubContext<OutputMessages, IOutputMessages> _outputMessages)
     {...}
}

在启动中我将 SignalR 服务添加为

        services.AddSignalR()
                .AddHubOptions<OutputMessages>(options =>
                {
                    options.EnableDetailedErrors = true;
                })

并定义端点

        app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<OutputMessages>("/OutputMessages", options =>
                {
                   options.Transports =
                   HttpTransportType.WebSockets |
                   HttpTransportType.LongPolling;
                });

           });

看起来不错吗?是的。而且编译也不错。但在运行时我收到

fail: Microsoft.AspNetCore.SignalR.HubConnectionHandler[1]
      Error when dispatching 'OnConnectedAsync' on hub.
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.Hub`1[IOutputMessages]' while attempting to activate 'OutputMessages'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
   at lambda_method(Closure , IServiceProvider , Object[] )
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubActivator`1.Create()
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnConnectedAsync(HubConnectionContext connection)
   at Microsoft.AspNetCore.SignalR.Internal.DefaultHubDispatcher`1.OnConnectedAsync(HubConnectionContext connection)
   at Microsoft.AspNetCore.SignalR.HubConnectionHandler`1.RunHubAsync(HubConnectionContext connection)
dbug: Microsoft.AspNetCore.SignalR.HubConnectionHandler[6]
      OnConnectedAsync ending.
asp.net-core dependency-injection signalr
3个回答
3
投票

最后我找到了解决方案

这是我的强类型集线器定义

public class OutputMessages : Hub<IOutputMessages>
        {
            public static readonly Dictionary<string, string> ConnectedUserList = new Dictionary<string, string>(1024);
            private readonly IHubContext<OutputMessages,IOutputMessages> _hubContext;
            private readonly ApplicationDbContext _db;
            private readonly ILogger<OutputMessages> _logger;

        public OutputMessages(IHubContext<OutputMessages, IOutputMessages> hubContext, ILogger<OutputMessages> logger, ApplicationDbContext dbContext)
        {
            _hubContext = hubContext;
            _db = dbContext;
            _logger = logger;
        }

....

        public async Task AdminMessages2(string userId, string message, bool consoleOnly)
        {
            string uname = await Username(userId);
            await _hubContext.Clients.All.AdminMessages2(userId, "API: " + uname + " " + message, consoleOnly);
        }

        [ResponseCache(VaryByHeader = "id", Duration = 36000, Location = ResponseCacheLocation.Any)]
        public async Task<string> Username(string id)
        {
            ApplicationUser user = null;
            await Task.Run(() => user = _db.Users.Find(id));
            return user.UserName;
        }

        public override async Task OnConnectedAsync()
        {
            string JWT = Context.GetHttpContext().Request.Headers["Authorization"];
            string ValidUserID = UserHelpers.ValidateJWT(JWT);
            if (ValidUserID != null)
            {
                _logger.LogInformation($"User {ValidUserID} connected to {this.GetType().Name} hub");
                if (ConnectedUserList.Any(x => x.Key == ValidUserID))
                {
                    ConnectedUserList.Remove(ValidUserID);
                }
                ConnectedUserList.Add(ValidUserID, Context.ConnectionId);
            }
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(System.Exception exception)
        {
            var JWT = Context.GetHttpContext().Request.Headers["Authorization"];
            string ValidUserID = UserHelpers.ValidateJWT(JWT);
            if (ValidUserID != null)
            {
                _logger.LogInformation($"User {ValidUserID} disconnected from {this.GetType().Name} hub");
                if (ConnectedUserList.Any(x => x.Key == ValidUserID))
                {
                    ConnectedUserList.Remove(ValidUserID);
                }
                ConnectedUserList.Add(ValidUserID, Context.ConnectionId);
            }
            await base.OnDisconnectedAsync(exception);
        }
    }

这是控制器的注入集线器

    public class ApplicationAPIController : ControllerBase
    {
         public ApplicationAPIController(ILogger<ApplicationAPIController> logger, ApplicationDbContext dbContext, IConfiguration Configuration, CoreObjectDumper.CoreObjectDumper dump, IHubContext<OutputMessages, IOutputMessages> _outputMessages)
        {
 ...

StartUp 中 SignalR 服务的定义没有改变。问题是从类而不是接口创建 Hub,并且 Hub 构造函数必须完全是 IHubContext


0
投票

就我而言,发生此错误时我正在使用 ABP 框架,我发现 ABP(部分)删除了缺少 DI、IOnlineClientManager 的类的实现

参见:https://github.com/aspnetboilerplate/aspnetboilerplate/commit/30b70e9a7f4395a2103219cdfd4b9499d35ebf3b

解决方案是删除这些类的通用实现(以及它们被引用的任何地方)

    IOnlineClientManager<ChatChannel> onlineClientManager,

在这里删除

ChatChannel
为我解决了这个问题。


0
投票

当我在代码中使用 SignalR 时,我遇到了同样的问题。除集线器连接外,所有其他 REST 端点均按预期工作。启用下面的代码后,我能够在 Visual Studio 输出窗格中看到错误:

services.AddSignalR()
                .AddHubOptions<OutputMessages>(options =>
                {
                    options.EnableDetailedErrors = true;
                })

我传递给集线器中的构造函数的某些类的依赖注入存在问题。一旦我解决了 DI 问题,集线器连接就按预期工作了。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.