Reputation: 421
I am working on integrating SignalR into an error/exception logging package which is being consumed by an AspNetCore project.
The logging package offers 2 ways to log errors:
ICustomLogger
interface which can be injected, then calling _customLogger.LogError(...)
IApplicationBuilder.UseExceptionHandler
to construct an instance of the custom logger, then calling .LogError(...)
similar to the aboveTo test this functionality, I have created 3 endpoints in a project which consumes this package:
/UnhandledException
:
internal static async Task TestUnhandledException()
{
//caught by the exception handler mentioned above
//logs the error and a message is received in the in the front-end by signal r
//no issues
throw new NotImplementedException();
}
/SendMessage
:
public static async Task SendSignalRMessage(IHubContext<CustomLogger.SignalR.EventHub> hubContext)
{
//uses the dependency-injected event hub from package
//does not call any functions from CustomLogger
//no issues
await hubContext.Clients.All.SendAsync("NewEvent", "Hello");
}
/ExplicitTest
:
internal static async Task Test(ICustomLogger logger)
{
//relies on injected CustomLogger receiving an injected IHubContext<EventHub>
//performs logging successfully but signalr message is not received in front-end
//issues!
var a = await logger.LogEventAsync(LogLevel.Info, "Manual event", "Is this message sent?");
}
The EventHub
is registered in the consuming project's Program.cs through:
app.UseEndpoints(ep => ep.MapHub<EventHub>("/Events"));
The custom logging package consists of:
public class CustomLogger
{
private readonly IHubContext<EventHub> hubContext;
public EventLogger(IOptionsSnapshot<LoggerSettings> settings, IHubContext<EventHub> hubContext)
{
this.hubContext = hubContext;
}
//Snip boring code that does actual logging
private async Task SendEventAsync(Event evt)
{
if (this.hubContext == null)
{
await this.LogEventAsync(LogLevel.Warning, "Configuration Error", "SignalR hub context is null");
return;
}
var eventData = new NewEvent
{
EventId = evt.EventId,
TimeStamp = evt.TimeStamp,
Message = evt.Message,
};
try
{
await this.hubContext.Clients.All.SendAsync(MessageType.NewEvent, eventData);
}
catch (Exception ex)
{
await this.LogExceptionAsync(LogLevel.Warning, ex);
}
}
}
As you can see, calling the function to manually log the data (in the non-working /ExplicitTest endpoint) requires a dependency-injected ICustomLogger
from the dependency package, the constructor of which requires a dependency-injected IHubContext<EventHub>
. The actual logging within the package will run successfully and on pausing the debugger, I can see that the injected ICustomLogger
has an IHubContext
with 1 active connection. No exception appears to be thrown when attempting to send a message to the connected clients, yet the message is not received.
Upvotes: 1
Views: 79
Reputation: 22082
After checking the issue, could you tell us why you are using EventLogger
as a constructor in the CustomLogger
class.
// Class Name
public class CustomLogger
{
private readonly IHubContext<EventHub> hubContext;
// <========= Here <==========
// The name of the constructor should be same as CLASS NAME
public EventLogger(IOptionsSnapshot<LoggerSettings> settings, IHubContext<EventHub> hubContext)
{
this.hubContext = hubContext;
}
...
...
}
Because of the lack of your EventLogger, I can't be sure that's the root cause, but you can set a breakpoint in SendEventAsync and see if the method is executed.
In my test environment, it works well. Please don't forget to add below codein your Program.cs
file.
builder.Services.AddSignalR();
builder.Services.AddSingleton<ICustomLogger, CustomLogger>();
Upvotes: 0