Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Customize Error Responses and Log Levels for Specific Exceptions in ABP Framework? #21997

Open
1 task done
zhangzw218 opened this issue Jan 24, 2025 · 3 comments
Open
1 task done

Comments

@zhangzw218
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

Is there a way to customize error responses and log levels for specific exceptions in ABP Framework?

Description
I need to handle two requirements for specific exceptions in ABP Framework:

  1. Return customized error messages to clients.
  2. Adjust the log level for specific exception types (e.g., reduce Error to Warning).

Use Case Example
When a database unique constraint violation occurs (e.g., duplicate entry for a unique index), I want to:

  1. Return a user-friendly message like "A subject with the same name already exists".
  2. Change the log level from the default Error to Warning.

Current Implementation for Custom Error Messages

I implemented a custom ExceptionToErrorInfoConverter to handle database unique constraint errors:

[Dependency(ReplaceServices = true)]
public class CustomExceptionConverter : DefaultExceptionToErrorInfoConverter
{
    public CustomExceptionConverter(
        IOptions<AbpExceptionLocalizationOptions> localizationOptions,
        IStringLocalizerFactory stringLocalizerFactory,
        IStringLocalizer<AbpExceptionHandlingResource> stringLocalizer,
        IServiceProvider serviceProvider)
        : base(localizationOptions, stringLocalizerFactory, stringLocalizer, serviceProvider)
    {
    }

    protected override RemoteServiceErrorInfo CreateErrorInfoWithoutCode(
        Exception exception, 
        AbpExceptionHandlingOptions options)
    {
        if (!options.SendExceptionsDetailsToClients)
        {
            exception = TryToGetActualException(exception);
            
            if (exception is DbUpdateException dbEx && 
                dbEx.InnerException is SqlException sqlEx && 
                sqlEx.Message.Contains("unique constraint 'IX_Subjects_Name_OrganizationUnitId'"))
            {
                return new RemoteServiceErrorInfo(
                    "A subject with the same name already exists in the current organization"
                );
            }
        }
        
        return base.CreateErrorInfoWithoutCode(exception, options);
    }
}

About log level customization

The above are just examples that I have come up with so far, I don't know if there is a better idea in ABP, I found the source code for the log level,

protected virtual void LogException(ExceptionContext context, out RemoteServiceErrorInfo remoteServiceErrorInfo)
{
………………
  var logLevel = context.Exception.GetLogLevel();
  logger.LogWithLevel(logLevel, remoteServiceErrorInfoBuilder.ToString()); 
………………
}

This doesn't get what I want, I need to rewrite the whole method to get there, is there an easier way?

Describe the solution you'd like

ABP has a ready-made configurable way to define the error level and change the text returned by the error

Additional context

No response

@maliming
Copy link
Member

When a database unique constraint violation occurs

You can try to check before inserting it into the database.

@zhangzw218
Copy link
Author

When a database unique constraint violation occurs

You can try to check before inserting it into the database.

Well, can.
But I also met a problem, most of the time, passed non-existent user front-end to the back-end, will trigger a 404 Error, log will print Volo. Abp. Domain. Entities. EntityNotFoundException, LogLevel = Error, I think to a Warning

@maliming
Copy link
Member

The GetAsync will throw an exception if the entity doesn't exit.
You can use FindAsync to query the entity.

https://abp.io/docs/9.0/framework/architecture/domain-driven-design/repositories#standard-repository-methods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants