Best Practices for Creating an Effective Error Handler in ASP.NET Core 7

Akash Jaiswal
4 min readAug 26, 2023

--

Hello everyone! In this blog, we will delve into the world of error handling in ASP.NET projects and explore the best practices to implement it effectively.

Understanding the Significance of Error Handling

Before we embark on our journey to implement error handling, let’s take a moment to understand what error handling is all about.

Error handling is a fundamental aspect of developing robust ASP.NET Core applications. It not only prevents your projects from crashing but also aids in debugging your code. Moreover, it encourages you to write cleaner and more concise code. In this blog, we will focus on using Error Handler as middleware.

A Brief Overview of Middleware

Middleware plays a vital role in ASP.NET Core. Think of it as a series of components that sit in the request-response pipeline, allowing you to intercept and process requests and responses at different stages.

The Role of Error Handler Middleware

You might be wondering, ‘Why use error handler middleware when we can handle errors directly in code, such as in Controllers or Services?’ Well, the answer lies in the request pipeline. Every API request passes through middleware before reaching your application’s endpoints and before the response is sent to the client. This means that if an error occurs anywhere in your Controllers or Services, it can be caught and managed by the Middleware before reaching the client. This approach ensures consistency in error handling and responses.

Crafting a Centralized API Response Format

Before we dive into the code for the error handler, it’s essential to establish a standardized API response format. This format will be used for both APIs and error handling. Follow these steps to create a centralized response format:

  1. Create a Helpers folder in your project directory.
  2. In the Helpers folder, create a file named ApiResponse.cs.
namespace MyProject.Helpers
{
public class ApiResponse<T>
{
public bool Success { get; set; }
public string Message { get; set; } = string.Empty;
public T? Data { get; set; }
}
}

Implementing the Error Handler Middleware

Now that we have our centralized API response format in place, let’s proceed to create the error handler middleware. Follow these steps:

  1. Create a Middleware folder in your project directory.
  2. In the Middleware folder, create a file named ErrorHandlerMiddleware.cs.
namespace MultiDeviceQrLogin.Middlewares
{
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;

public ErrorHandlerMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}

catch (UnauthorizedAccessException)
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsJsonAsync(new ApiResponse<object> { Success = false, Message = "Unauthorized access." });
}

catch (Exception ex)
{
// Handle other unhandled exceptions
// Log the exception for debugging purposes.
Console.WriteLine($"Unhandled Exception: {ex}");

// Customize the error response as needed.
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
await context.Response.WriteAsJsonAsync(new ApiResponse<object> { Success = false, Message = "An error occurred while processing your request." });
}
}
}
}

Configuring the Middleware

Finally, configure the error handler middleware in your Program.cs:

var app = builder.Build();

app.UseMiddleware<ErrorHandlerMiddleware>();

// Rest of your application configuration...

Creating Custom Exceptions

For better organization, consider creating custom exceptions. For instance, you can create a NotFoundException for cases where a resource is not found. Here's how to do it:

  1. Create an Exceptions folder in your project directory.
  2. In the Exceptions folder, create a file named NotFoundException.cs.
namespace MultiDeviceQrLogin.Exceptions
{
public class NotFoundException : Exception
{
public NotFoundException(string message) : base(message)
{
}
}
}

3. Now add the exception in your ErrorHandlerMiddleware class.

namespace MultiDeviceQrLogin.Middlewares;

public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;

public ErrorHandlerMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (NotFoundException ex)
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsJsonAsync(new ApiResponse<object> { Success = false, Message = ex.Message });
}
catch (UnauthorizedAccessException)
{
// Handle unauthorized access
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsJsonAsync(new ApiResponse<object> { Success = false, Message = "Unauthorized access." });
}
catch (NotFoundException ex)
{
// Handle custom NotFoundException
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsJsonAsync(new ApiResponse<object> { Success = false, Message = ex.Message });
}
catch (Exception ex)
{
// Handle other unhandled exceptions
// Log the exception for debugging purposes.
Console.WriteLine($"Unhandled Exception: {ex}");

// Customize the error response as needed.
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
await context.Response.WriteAsJsonAsync(new ApiResponse<object> { Success = false, Message = "An error occurred while processing your request." });
}
}
}

Putting It All Together

Let’s see how you can use the error handler in a basic API. Suppose you want to find a user:

[HttpGet(Name = "FindUser")]
public ActionResult<ApiResponse<string>> FindUser(string user) {
string[] usersList = new string[]{"John", "Alex", "Altnas", "Elisa", "Bob"};

if(usersList.Contains(user))
{
return new ApiResponse<string> {Success = true, Message = "User Found!", Data= $"Hello {user}"};
} else {
throw new NotFoundException("User not found");
}
}
When User not found and exception got hit.
When User got found.

With these steps, you’ve set up a robust error handling mechanism for your ASP.NET Core project, ensuring smoother development and reliable user experiences.

If you have any questions or need further assistance, please don’t hesitate to ask. Happy coding!

--

--