In this post, let's see how we can provide a common approach for handling
exceptions in ASP.NET Core Web APIs in the Development environment as well as
in Production environments.
It's quite easy, basically, we can introduce UseExceptionHandler Middleware to handle exceptions.
Consider the following code.
WebApplicationBuilder builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); WebApplication app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseExceptionHandler("/error-development"); } else { app.UseExceptionHandler("/error"); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
Here I have added UseExceptionHandler passing in different routes based on the environment. Now we need to
define controller actions to respond to /error-development and /error routes.
using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc; using System.Net; namespace WebApplication1.Controllers; [ApiController] [ApiExplorerSettings(IgnoreApi = true)] public class ErrorController : ControllerBase { private readonly IHostEnvironment _hostEnvironment; public ErrorController(IHostEnvironment hostEnvironment) { _hostEnvironment = hostEnvironment; } [Route("/error-development")] public IActionResult HandleErrorDevelopment() { if (!_hostEnvironment.IsDevelopment()) { return NotFound(); } IExceptionHandlerFeature exceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>()!; if (exceptionHandlerFeature == null) { return Problem( title: $"'{nameof(IExceptionHandlerFeature)}' not found."); } return exceptionHandlerFeature.Error switch { NotImplementedException notImplementedException => Problem( title: notImplementedException.Message, detail: notImplementedException.StackTrace,
statusCode: (int)HttpStatusCode.NotImplemented), _ => Problem( title: exceptionHandlerFeature.Error.Message, detail: exceptionHandlerFeature.Error.StackTrace) }; } [Route("/error")] public IActionResult HandleError() => Problem(); }
Note: The actions aren't attributed with HttpVerbs and the controller
is attributed with [ApiExplorerSettings(IgnoreApi = true)] to exclude from OpenAPI specification (if there's any).
For the Development environment, based on the type of the exception, I am
returning different statusCodes and I am including the StackTrace to
troubleshoot the issue easily.
For an example, consider the following action.
[HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { throw new NotImplementedException("Not implemented."); }
If we call the above action when running on a Development environment, I
will be getting a response like below. It's the standard RFC 7807-compliant Problem Detail.
[HttpGet(Name = "GetWeatherForecast")] public IEnumerable<WeatherForecast> Get() { throw new Exception("Something happened."); }
I am getting the default Internal Server Error status code with the
StackTrace.
Development: StatusCode: 500 |
And when in a production environment, we just get the response hiding internal
details.
Production: StatusCode: 500 |
More read:
Handle errors in ASP.NET Core web APIs
Handle errors in ASP.NET Core web APIs
Hope this helps.
Happy Coding.
Regards,
Jaliya
No comments:
Post a Comment