Summary
I want to disable or override the default message dialog that appears during unhandled exceptions inside a try-catch
block. Instead, I would like to handle the error manually and show notify only or logs.
Context
Currently, when an exception occurs—even though it's wrapped in a try-catch
—a system-generated dialog still appears. This is not the desired behavior because:
- I already catch and handle the error.
- I want full control over the user experience.
- The default dialog might confuse users or duplicate my custom error messages.
Expected Behavior
When an exception is caught in a try-catch
, only my custom error-handling logic should be executed. No default or automatic dialogs should be shown.
Questions
- How can I disable the automatic error dialog triggered by the framework or component?
- Is there a global setting or configuration in Blazor ABP that forces only manual error display?
- If this behavior is baked in, what's the recommended way to override or suppress it?
Images
Example Scenario
try
{
// Some operation that might throw
}
catch (Exception ex)
{
Logger.LogError(e, "Error change status container type with id id :{SelectedContainerTypeId}",
SelectedContainerTypeId);
await Notify.Error(string.IsNullOrEmpty(e.Message) ? L["Messages:Error"] : e.Message);
}
7 Answer(s)
-
0
Hi, to fix this here is an example:
1-) I have a method call to open the edit modal in razor side as below:
<EntityAction TItem="BookDto" Text="@L["Edit"]" Visible=HasUpdatePermission Clicked="async () => await OpenMyEditModalAsync()" />
The important part is here, the
Clicked
part. In here, I made the method as async and use the await keyword explicitly. So, if I catch the exception, my own notification will shown.2-) Inside of the
OpenMyEditModalAsync
method:public async Task OpenMyEditModalAsync() { try { // Some operation that might throw - simulating with the below exception throw new UserFriendlyException("My message"); } catch (UserFriendlyException ex) { Logger.LogError(ex, "Handled UserFriendlyException"); await Notify.Error(string.IsNullOrEmpty(ex.Message) ? L["Messages:Error"] : ex.Message); } catch (Exception ex) { //for other exceptions you can also handle here... } }
When you try like this, it should not show a model for the error, and you should be able to only see the notification on the bottom-right of your page:
-
0
Hi, thanks for the detailed explanation!
I've followed your suggestion and updated the
OnChange
handler to use anasync
lambda as shown:However, I'm still seeing the default error dialog (from ABP) even though the exception is caught and I’m manually showing a toast notification.
And can i ask are there any supported way to disable this dialog globally or override the error handling mechanism or correctly to handle this?
Thanks again for your support!
<TelerikSwitch Value="@item.IsActive" OnLabel=" " OffLabel=" " Size="@ThemeConstants.Switch.Size.Small" OnChange="@(async () => await ToggleStatus(item))" /> private async Task ToggleStatus(TIem item) { try { } catch (Exception e) { await Notify.Error(string.IsNullOrEmpty(e.Message) ? L["Messages:Error"] : e.Message); } finally { LoaderVisible = false; } }
-
0
Hi, thanks for the detailed explanation!
I've followed your suggestion and updated the
OnChange
handler to use anasync
lambda as shown:However, I'm still seeing the default error dialog (from ABP) even though the exception is caught and I’m manually showing a toast notification.
And can i ask are there any supported way to disable this dialog globally or override the error handling mechanism or correctly to handle this?
Thanks again for your support!
<TelerikSwitch Value="@item.IsActive" OnLabel=" " OffLabel=" " Size="@ThemeConstants.Switch.Size.Small" OnChange="@(async () => await ToggleStatus(item))" /> private async Task ToggleStatus(ContainerTypeDto item) { try { var messageKey = item.IsActive ? "Delete:ConfirmInactiveMessage" : "Delete:ConfirmActiveMessage"; var message = L[messageKey, L["ContainerType"]]; if (await Dialogs.ConfirmAsync(message, L["Dialog:ConfirmAction"])) { LoaderVisible = true; SelectedContainerTypeId = item.Id.ToString(); await ContainerTypeService.ChangeStatusAsync(Guid.Parse(SelectedContainerTypeId)); var result = await ContainerTypeService.GetListAsync(new ContainerTypeRequestDto()); ContainerTypes = result.Items.ToList(); await Notify.Success(L["Messages:Success"]); } } catch (Exception e) { Logger.LogError(e, "Error changing container type status for ID: {SelectedContainerTypeId}", SelectedContainerTypeId); await Notify.Error(string.IsNullOrEmpty(e.Message) ? L["Messages:Error"] : e.Message); } finally { LoaderVisible = false; } } public async Task ChangeStatusAsync(Guid containerTypeId) { var containerType = await repository.GetAsync(containerTypeId); var hasInUse = await containerRepository .AnyAsync(d => d.ContainerTypeId == containerTypeId && !d.IsDeleted && d.Asset != null && d.Asset.IsActive); if (hasInUse) { throw new BusinessException(TmsSolutionDomainErrorCodes.ContainerTypeIsInUse); } containerType.IsActive = !containerType.IsActive; await repository.UpdateAsync(containerType); }
Hi, you should catch
UserFriendlyException
, because ABP shows dialog for this exception type. Can you try like in my suggested code? -
0
Hi . The error dialog still showing after editing code like you suggested.
<TelerikSwitch Value="@item.IsActive" OnLabel=" " OffLabel=" " Size="@ThemeConstants.Switch.Size.Small" OnChange="@(async () => await ToggleStatus(item))"/> </span> private async Task ToggleStatus(ChassisTypeDto item) { try { throw new UserFriendlyException("Test exception"); } catch (UserFriendlyException ex) { Logger.LogError(ex, "Handled UserFriendlyException"); await Notify.Error(string.IsNullOrEmpty(ex.Message) ? L["Messages:Error"] : ex.Message); } catch (Exception e) { Logger.LogError(e, "Error change status container type with id id :{SelectedChassisTypeId}", SelectedChassisTypeId); await Notify.Error(string.IsNullOrEmpty(e.Message) ? L["Messages:Error"] : e.Message); } finally { LoaderVisible = false; } }
-
0
Hi . The error dialog still showing after editing code like you suggested.
<TelerikSwitch Value="@item.IsActive" OnLabel=" " OffLabel=" " Size="@ThemeConstants.Switch.Size.Small" OnChange="@(async () => await ToggleStatus(item))"/> </span> private async Task ToggleStatus(ChassisTypeDto item) { try { throw new UserFriendlyException("Test exception"); } catch (UserFriendlyException ex) { Logger.LogError(ex, "Handled UserFriendlyException"); await Notify.Error(string.IsNullOrEmpty(ex.Message) ? L["Messages:Error"] : ex.Message); } catch (Exception e) { Logger.LogError(e, "Error change status container type with id id :{SelectedChassisTypeId}", SelectedChassisTypeId); await Notify.Error(string.IsNullOrEmpty(e.Message) ? L["Messages:Error"] : e.Message); } finally { LoaderVisible = false; } }
Okay, it seems it's all about timing and you need to disable ABP's exception handling system on the UI side. To do that, you can add the following line to both your
Blazor.Client
andBlazor
projects' module classes:public override void ConfigureServices(ServiceConfigurationContext context) { //other configs... context.Services.Replace(ServiceDescriptor.Transient(typeof(IUserExceptionInformer), typeof(NullUserExceptionInformer))); }
This will replace the
UserExceptionInformer
service (https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore.Components.Web/Volo/Abp/AspNetCore/Components/Web/ExceptionHandling/UserExceptionInformer.cs), which shows a message dialog by default. If you want you can create your own UserExceptionInformer implementation and then show Notify popup on the bottom-right for each exception.After the replacement, it should work seamlessly:
-
0
Hi, thank you for your support!
The issue has been resolved successfully.
-
0
Hi, thank you for your support!
The issue has been resolved successfully.
Great to hear that! Regards.