Обрабатывать все исключения в концентраторах SignalR в Asp.Net Ядро 3.1

#c# #asp.net-core #exception #signalr-hub #asp.net-core-signalr

#c# #asp.net-ядро #исключение #signalr-hub #asp.net-core-signalr

Вопрос:

В Web API все исключения могут быть обработаны промежуточным программным обеспечением. В Asp.Net Фильтры-концентраторы Core 5.0 выполнят эту работу.

Но как обрабатывать исключения в Asp.Net Ядро 3.1 в концентраторах SignalR? Есть ли единственный способ написать try / catch во всех методах, как показано ниже?

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

Ответ №1:

Возможно, вы знаете, что ASP.NET SignalR поддерживает модули HubPipeline, которые обеспечивают способ обработки исключений концентратора по всему миру.

Но из этого документа мы можем найти, что модули HubPipeline больше не поддерживаются в ASP.NET Core SignalR, и в настоящее время, похоже, не предоставляет альтернативного подхода для обработки возникающих ошибок в глобальном масштабе.

Как вы упомянули, мы можем обернуть код в блоки try-catch и зарегистрировать объект исключения или вручную отправить его вызывающему.

Пожалуйста, обратите внимание, что исключения часто содержат конфиденциальную информацию, по соображениям безопасности отправка подробной информации клиентам не рекомендуется в рабочей среде.

Кроме того, ASP.NET Core SignalR предоставляет встроенную функцию ведения журнала диагностики, которая может помочь собирать и регистрировать полезную информацию о транспорте и концентраторе, связанную с ним, что может помочь в устранении проблемы.

Примечание: вы можете проверить эту проблему на github, в которой обсуждается то же требование о «центральной обработке исключений Signalr .net core».

Ответ №2:

Начиная с .net 5.0, вы можете использовать фильтры концентраторов: https://learn.microsoft.com/en-us/aspnet/core/signalr/hub-filters?view=aspnetcore-5.0

Ответ №3:

В моем случае я хотел регистрировать все необработанные исключения, возникающие в моем концентраторе signalr. Я использую .NET 6 и сделал следующее.

  1. Добавьте файл 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. Добавьте ExceptionFilter к параметрам signalr.
 builder.Services.AddSignalR(options =>
{
    options.AddFilter<ExceptionFilter>();
});
  
  1. Зарегистрируйте ExceptionFilter для DI.
 builder.Services.AddSingleton<ExceptionFilter>();
  

Я протестировал это, вручную создав исключение в методе концентратора, и блок catch будет выполнен.