How to handle errors in minimal APIs in ASP.NET Core

How to use the exception handling middleware in ASP.NET Core to handle errors gracefully in your minimal API applications.

error neon mistake
Florent Darrault (CC BY-SA 2.0)

In ASP.NET Core 7, minimal APIs provide a lightweight way to create web APIs with less boilerplate code. However, errors can still occur and you should be able to handle them elegantly.

This article discusses how we can handle errors gracefully in minimal API apps in ASP.NET Core 7. To use the code examples provided in this article, you should have Visual Studio 2022 installed in your system. If you don’t already have a copy, you can download Visual Studio 2022 here.

Create an ASP.NET Core 7 minimal Web API project in Visual Studio 2022

First off, let’s create an ASP.NET Core 7 project in Visual Studio 2022. Follow these steps:

  1. Launch the Visual Studio 2022 IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web API” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  7. Click Next.
  8. In the “Additional Information” window shown next, select “NET 7.0 (Current)” as the framework and uncheck the check box that says “Use controllers…” Leave the “Authentication Type” as “None” (default).
  9. Ensure that the check boxes “Enable OpenAPI Support,” “Enable Docker”, “Configure for HTTPS,” and “Enable Open API Support” are unchecked as we won’t be using any of those features here.
  10. Click Create.

We’ll use this ASP.NET Core 7 Web API project to create a minimal API and implement error handling in the sections below.

Handling errors in minimal API applications

Replace the default generated source code of the Program.cs file in the project we created with the following code snippet.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Map("/error", ()
    => {
            throw new InvalidOperationException("An Error Occurred...");
        });
app.Run();

When you run the application, the “Hello World” text message will be displayed in your web browser. If you browse to the /error endpoint, a run time error will occur, and the execution of the application will halt, as shown in Figure 1.

errors minimal apis 01 IDG

Figure 1. A fatal exception in our minimal API application.

There are two built-in mechanisms for handling errors in minimal API applications, the Developer Exception Page middleware and the Exception Handler middleware. Let’s examine each in turn. 

Using the Developer Exception Page middleware

To help developers diagnose and fix errors during development, you can use the Developer Exception Page middleware. The Developer Exception Page middleware displays detailed error information in the browser when an exception occurs.

Here is an example of how to use the Developer Exception Page middleware in a minimal API.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
//builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
   app.UseDeveloperExceptionPage();
}
app.MapGet("/", () => "Hello, world!");
app.Run();

In this example, the UseDeveloperExceptionPage method is used to add the middleware to the pipeline. The middleware is enabled only when the application is running in the Development environment, which is determined by the app.Environment.IsDevelopment() method.

If an exception occurs within the pipeline, the Developer Exception Page middleware catches it and displays a detailed error page in the browser. The error page includes information about the exception, including the stack trace, request details, and environment variables as shown in Figure 2.

errors minimal apis 02 IDG

Figure 2. The Developer Exception Page middleware in action.

By using the Developer Exception Page middleware, developers can quickly diagnose and fix errors during development.

Using the Exception Handler middleware

The Exception Handler middleware catches unhandled exceptions and returns an error response. Typically, you should use this middleware in a non-development environment. Here is an example of how to use the Exception Handler middleware in a minimal API.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp
    => exceptionHandlerApp.Run(async context => await Results.Problem().ExecuteAsync(context)));
app.Map("/error", ()
    => { throw new InvalidOperationException("An Error Occurred..."); });
app.MapGet("/", () => "Hello, world!");
app.Run();

In this example, the UseExceptionHandler method is used to configure this middleware. The parameter "/error" specifies the endpoint to which the middleware will redirect in case of an exception.

If an unhandled exception occurs within the pipeline, the Exception Handling middleware catches it and redirects the request to the specified endpoint. Subsequently the error will be handled and an appropriate error message returned.

By using the Exception Handling middleware, you can easily handle exceptions that occur within minimal APIs in ASP.NET Core 7. This can help to improve the reliability and usability of your API.

Using ProblemDetails for response formatting

The ProblemDetails class is a way to include details of error information to avoid creating custom error response formats in ASP.NET Core. The AddProblemDetails extension method pertaining to the IServiceCollection interface can be used to register a default implementation of the IProblemDetailsService.

The following middleware in ASP.NET Core generates ProblemDetails HTTP responses when you make a call to the AddProblemDetailsMiddleware method in your application.

  • ExceptionHandlerMiddleware: This middleware is used to generate a ProblemDetails response if no custom handler is available.
  • DeveloperExceptionPageMiddleware: The DeveloperExceptionPageMiddleware creates a ProblemDetails response if the Accept HTTP header does not contain text/html.
  • StatusCodePagesMiddleware: By default, StatusCodePagesMiddleware generates ProblemDetails responses.

The following code listing shows how you can use ProblemDetails in your minimal APIs.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
app.Map("/authors/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new Author(id)));
app.Map("/error", ()
=> {
       throw new InvalidOperationException("An Error Occurred...");
   });
app.Run();
public record Author(int Id);

In this example, the /error endpoint extracts the exception information from the HttpContext and creates a ProblemDetails object with the error details. It then sets the response status code and content type, and returns the ProblemDetails object as a JSON response.

Using Status Code Pages middleware to generate a response body

When an ASP.NET Core app encounters HTTP error codes such as “404 - Not Found,” it does not provide a status code page by default. Whenever a response body is not provided for an HTTP 400-599 error status code, the app returns the status code and an empty response body.

You can invoke the UseStatusCodePages method in the Program.cs file of your application to enable text-only handlers for common error status codes. You can use the StatusCodePagesMiddleware class in ASP.NET Core to generate the response as shown in the code snippet given below.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseStatusCodePages(async statusCodeContext
    => await Results.Problem(statusCode: statusCodeContext.HttpContext.Response.StatusCode)
                 .ExecuteAsync(statusCodeContext.HttpContext));
app.Map("/authors/{id:int}", (int id)
    => id <= 0 ? Results.BadRequest() : Results.Ok(new Author(id)));
app.Run();
public record Author(int Id);

In ASP.NET Core applications, exception filters can be used to catch specific types of exceptions and handle them gracefully. To use a filter, implement the IExceptionFilter interface and add it to the application pipeline. You can learn more about using exception filters (and other filters) in ASP.NET Core in my earlier article here.

Copyright © 2023 IDG Communications, Inc.