Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.Hub`1[IXXXX]' while attempting to activate 'XXXXX'
Asked Answered
D

2

7

I define my strong typed SignalR hub exactly by MS Rules

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

than inject my SignalR hub to conctoller by the same way

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

In Startup I add SignalR service as

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

and define endpoint

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

           });

Looks good? Yes. And compilation is good. But in runTime I receive

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.
Daphinedaphna answered 23/8, 2020 at 0:52 Comment(4)
I don't think .AddHubOptions<OutputMessages>(options =>... is correct. change that to services.AddSignalR(o => o.EnableDetailedErrors = true);, then try injecting IOutputMessages the normal route: services.AddTransient<IOutputMessages, OutputMessages>();Turkish
Take a look at this: #48393929Turkish
in this case I receive in project initialization - 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: IOutputMessages Lifetime: Transient ImplementationType: OutputMessages': Unable to resolve service for type 'Microsoft.AspNetCore.SignalR.Hub`1[IOutputMessages]' while attempting to activate 'OutputMessages'.)'Daphinedaphna
The problem is that you have a constructor in your hub method to your OutputMessages class. You don't need any constructor since AddSignalR registers the HUB on DI. Then the dependency you resolve trough DI like I answered you in previous questions.Plea
D
3

and finally I found a solution

this is my strong type Hub definition

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

and this is injection Hub to controller

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

definition of SignalR service in StartUp not changed. Problem is create Hub from class instead interface and Hub constructor must be exactly IHubContext<OutputMessages,IOutputMessages>

Daphinedaphna answered 25/8, 2020 at 0:0 Comment(0)
P
0

In my case, I was using the ABP framework when this error occurred and I found that ABP (partially) removed the implementation of the class that lacked the DI, IOnlineClientManager

See: https://github.com/aspnetboilerplate/aspnetboilerplate/commit/30b70e9a7f4395a2103219cdfd4b9499d35ebf3b

The solution was then to remove the generic implementations of those classes ( and everywhere where they are being refferred)

    IOnlineClientManager<ChatChannel> onlineClientManager,

here removing ChatChannel solved it for me.

Pentomic answered 24/7 at 16:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.