#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 и сделал следующее.
- Добавьте файл 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;
}
}
}
- Добавьте ExceptionFilter к параметрам signalr.
builder.Services.AddSignalR(options =>
{
options.AddFilter<ExceptionFilter>();
});
- Зарегистрируйте ExceptionFilter для DI.
builder.Services.AddSingleton<ExceptionFilter>();
Я протестировал это, вручную создав исключение в методе концентратора, и блок catch будет выполнен.