Handle all exceptions in SignalR hubs in Asp.Net Core 3.1

5k views Asked by At

In Web API all the exceptions can be cought by Middleware. In Asp.Net Core 5.0 Hub Filters will do that job.

But how to handle exceptions in Asp.Net Core 3.1 in SignalR hubs? Is there a sole way to write try/catch in every methods like below?

[Authorize]
public class OrdersHub : BaseHub
{
        public async Task GetOrder(Guid requestId, int orderId)
        {
            try
            {
                var data = await ordersService.GetOrderAsync(orderId);
                await Clients.Caller.SendAsync("GetOrderResult", requestId, result);
            }
            catch (Exception ex)
            {
                await Clients.Caller.Reject(requestId, ex);
            }
        }
}
3

There are 3 answers

0
Fei Han On BEST ANSWER

You may know that ASP.NET SignalR has support for HubPipeline modules that provide a way to handle hub exceptions globally.

But from this doc we can find HubPipeline modules is no longer supported in ASP.NET Core SignalR, and currently it seems not provide alternative approach to handle incomming errors globally.

As you mentioned, we can wrap code in try-catch blocks and log the exception object or manually send it to caller.

Please note that exceptions often contain sensitive information, for security reasons sending detailed information to clients is not recommended in production.

Besides, ASP.NET Core SignalR provides built-in diagnostics logging feature that could help capture and log useful transports and Hub related information, which could help troubleshoot the issue.

Note: you can check this github issue that discuss same requirement about "Signalr .net core central exception handling".

0
datchung On

In my case, I wanted to log all unhandled exceptions thrown in my signalr hub. I'm using .NET 6 and did the following.

  1. Add ExceptionFilter.cs.
public class ExceptionFilter : IHubFilter
{
    private readonly ILogger _logger;

    public ExceptionFilter(ILogger logger)
    {
        _logger = logger;
    }

    public async ValueTask<object> InvokeMethodAsync(
        HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object>> next)
    {
        try
        {
            return await next(invocationContext);
        }
        catch (Exception ex)
        {
            _logger.LogError($"Exception calling '{invocationContext.HubMethodName}': {ex}");
            throw;
        }
    }
}
  1. Add ExceptionFilter to the signalr options.
builder.Services.AddSignalR(options =>
{
    options.AddFilter<ExceptionFilter>();
});
  1. Register ExceptionFilter for DI.
builder.Services.AddSingleton<ExceptionFilter>();

I tested this by manually throwing an exception in a hub method, and the catch block gets executed.

0
hillin On