It is a middleware for error handling in ASP.NET projects, the application aims to facilitate and handle when an accidental or custom exception occurs in the project.
Install-Package CustomExceptionMiddleware
dotnet add package CustomExceptionMiddleware
Minimum requirements to use: .NET Standard 2.0
Compilation requirements: .NET 8
It's very simple to use, go to Startup.cs
on Configure()
method and add this code:
app.UseCustomExceptionMiddleware();
Or if you are using any of the newer versions of .NET put the code after the app build
on Program.cs
file.
var app = builder.Build();
app.UseCustomExceptionMiddleware();
Example output
{
"type": "VALIDATION_ERRORS",
"error": {
"msg": "Custom domain exception message"
}
}
-
Create object options
It's possible create aCustomExceptionOptions
to customize the return middleware object, to view theStackTrace
like this:app.UseCustomExceptionMiddleware(new CustomExceptionOptions { ViewStackTrace = true });
-
Use an action options
Other options to customize the return object is using an action to create aCustomErrorModel
app.UseCustomExceptionMiddleware(options => { options.ViewStackTrace = true; });
In both cases the output will include de stack trace in detail
object property:
Example output
{
"type": "VALIDATION_ERRORS",
"error": {
"msg": "Custom domain exception message",
"detail": "at CustomExceptionMiddleware.WebAppTest.Custom.ProductService.GetDomainException(Boolean returnProducts) in C:\\isaacnborges\\projects\\custom-exception-middleware\\tests\\CustomExceptionMiddleware.WebAppTest.Custom\\ProductService.cs:line 18\r\n at CustomExceptionMiddleware.WebAppTest.Custom.Controllers.ProductController.GetDomain(Boolean returnProduct) in C:\\isaacnborges\\projects\\custom-exception-middleware\\tests\\CustomExceptionMiddleware.WebAppTest.Custom\\Controllers\\ProductController.cs:line 26"
}
}
This middleware use some custom exceptions to catch and personalize the response status code.
The custom middleware supports the following Exceptions:
Exception | Status code description | Status code |
---|---|---|
DomainException | BadRequest | 400 |
UnauthorizedException | Unauthorized | 401 |
CannotAccessException | Forbidden | 403 |
NotFoundException | NotFound | 404 |
Exception | InternalServerError | 500 |
DomainException
is an abstract exception, so to use it's necessary create other exception and inherit. The others exceptions only throw an exception
public class InvalidStateException : DomainException
{
public InvalidStateException()
{ }
public InvalidStateException(string message) : base(message)
{ }
public InvalidStateException(string message, Exception innerException) : base(message, innerException)
{ }
}
throw new InvalidStateException("Custom domain exception message");
throw new UnauthorizedException("Custom unauthorized exception message");
throw new CannotAccessException("Custom cannot access exception message");
throw new NotFoundException("Custom not found exception message");
throw new Exception("Custom exception message");
It's possible to customize the exception type when throw an exception, just pass the type in an exception constructor.
throw new CustomDomainException("Custom domain exception message", "OTHER_CUSTOM_TYPE");
Inside the samples
folder has two projects that could be used for test the and validate the middleware.
- WebAppTest
dotnet run --project .\samples\CustomExceptionMiddleware.WebAppTest\
- WebAppTest.Custom
dotnet run --project .\samples\CustomExceptionMiddleware.WebAppTest.Custom\
- Swagger
- Postman
- Open
docs
folder, inside has a postman collection that could be used for test.
- Open
This middleware will Log
some informations that can be used for monitoring and observability, like TraceIdentifier
, request and exception informations like message type and stack trace:
Example log:
Occurred an exception - TraceId: 0HMBO9LGH0JHD:00000002 - ExceptionType: InvalidStateException - Message: Custom domain exception message
CustomExceptionMiddleware.WebAppTest.InvalidStateException: Custom domain exception message
at CustomExceptionMiddleware.WebAppTest.Custom.ProductService.GetDomainException(Boolean returnProducts) in C:\\isaacnborges\\projects\\custom-exception-middleware\\tests\\CustomExceptionMiddleware.WebAppTest.Custom\\ProductService.cs:line 18\r\n at CustomExceptionMiddleware.WebAppTest.Custom.Controllers.ProductController.GetDomain(Boolean returnProduct) in C:\\isaacnborges\\projects\\custom-exception-middleware\\tests\\CustomExceptionMiddleware.WebAppTest.Custom\\Controllers\\ProductController.cs:line 26
In some scenarios the project needs other response object, integrations with 3rd party systems for example, this middleware contains an attribute that could be ignore, it's possible use in class or methods
Using the IgnoreCustomExceptionAttribute
attribute the middleware will ignore your own flow. To use it simply, decorate the class or method with the name.
-
Class example
[IgnoreCustomException] public class ValuesController : ControllerBase { [HttpGet] public IActionResult Get() { throw new CustomDomainException("Some error ignore class"); }
-
Method example
[IgnoreCustomException] [HttpGet("ignore")] public IActionResult GetIgnore() { throw new CustomDomainException("Some error ignore method"); }
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
Please make sure to update tests as appropriate.