How to Manage Exceptions Worldwide in ASP.NET The core?

Leave a Comment

Regardless of size or volume, dependable exception management is essential to robust software. Critical data loss or system instability can result from poorly managed faults. Although ASP.NET Core provides a number of error management techniques, this article examines the Global Exception Handling method utilizing the IExceptionHandler interface. Cleaner code, a more manageable architecture, and consistent Problem Details (RFC 7807) replies are all ensured by centralizing error logic.

Methods for Handling Exceptions

Exceptions are specific objects in.NET that are used to indicate that a code execution error has occurred. The baseSystem is the source of all exceptions.class of exceptions. The program "throws" an exception object to alert the system when an issue occurs, like trying to access a missing file. Instead of just crashing, this method acts as an integrated alarm system, enabling the program to recognize and address problems. 

Several approaches of handling application faults are offered by ASP.NET Core:

  • Conventional Try-Catch Blocks: The fundamental technique of enclosing particular code blocks to identify and fix local issues.
  • Default Exception Middleware: Making use of built-in framework functions such as UseDeveloperExceptionPage and UseExceptionHandler.
  • Developing specialized middleware components to detect and manage failures throughout the whole request lifecycle is known as custom exception middleware.
  • IExceptionHandler (Best Practice): Introduced in.NET 8, this is the leading contemporary method. The recommended standard for putting in place a neat, organized, and centralized error-handling system is this interface.

Let's talk about each of the above. 

1. Standard Try-Catch Block

The try-catch block is the most common approach for immediate error handling. The following example demonstrates this implementation:

[HttpGet]
public IActionResult GetProducts()
{
    try
    {
        // Service call that may fail due to external factors
        var products = _productService.FetchAll();
        return Ok(products);
    }
    catch (Exception exception)
    {
        _logger.LogError(exception.Message);
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}

This reflects a standard pattern where the FetchAll() method represents a service or data call prone to errors. When an exception occurs, the catch block intercepts it to log the error details and return a 500 Internal Server Error status code. While functional, repeating this logic across every controller can quickly lead to redundant code.

If an error occurs while theGetProducts() method is running, the following exception is triggered:

throw new Exception("An error occurred while retrieving data.");

While this basic approach is straightforward, it significantly increases the total lines of code. While suitable for small Proof of Concept (POC) projects, manually inserting try-catch blocks into every controller action and service method is repetitive and difficult to maintain in larger systems.

A more effective strategy involves handling all exceptions in a single, central location. The following sections explore two approaches that improve the error-handling architecture by isolating all logic into a dedicated area. This results in a cleaner codebase and a more controlled application by removing the need for redundant error-handling code.

2. Exception Handling Middleware in .NET - UseExceptionHandler

To simplify development, ASP.NET Core provides the built-in ExceptionHandler Middleware. When configured in the Program.cs file, this middleware is added to the request pipeline to catch unhandled exceptions across the entire application. It offers a direct and efficient way to centralize error management.

The following example demonstrates how to configure the UseExceptionHandler middleware. Open the Program.cs file and apply the following configuration:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

var app = builder.Build();

// Configure the built-in exception handling middleware
app.UseExceptionHandler("/error-handler");

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

This configuration provides a foundational setup for the ExceptionHandler Middleware. Whenever the application pipeline detects an unhandled exception, execution control is automatically transferred to this middleware. It then intercepts the error and returns a customized response to the client, ensuring the application remains stable and provides informative feedback.

3. Custom Exceptions

It is both cleaner and more effective to categorize specific error types. This allows the application to respond uniquely to different failure scenarios later in the development process. Creating custom exception classes ensures that the application throws meaningful errors that are easier to diagnose.

To begin, create a new folder named Exceptions and add a class named ApplicationBaseException. This class must inherit from the baseException class. The implementation for this custom base exception is as follows:

namespace GlobalExceptionHandler.Domain.Exceptions
{
    public class GlobalAppException : Exception
    {
        public HttpStatusCode ResultStatusCode { get; }

        public GlobalAppException(string errorMessage, HttpStatusCode code = HttpStatusCode.InternalServerError)
            : base(errorMessage)
        {
            ResultStatusCode = code;
        }
    }
}

This GlobalAppException serves as the foundation for creating more specific error types. Inheriting from a shared base class is a cleaner architectural pattern for designing exception systems. For instance, a RecordNotFoundException can be created by inheriting from this base class.

public class RecordNotFoundException : GlobalAppException
{
    public RecordNotFoundException(Guid recordId)
        : base($"The record with ID {recordId} was not found.", HttpStatusCode.NotFound)
    {
    }
}

By using this approach, a service class can simply throw a RecordNotFoundException if a database or cache lookup fails. This provides immediate clarity in error logs regarding the nature of the issue and the specific identifier involved, eliminating the need to sift through complex stack traces.

The custom exception is utilized as follows:

throw new RecordNotFoundException(requestedProduct.Id);
4. Recommended exception handling in .NET 8: IExceptionHandler

Introduced in .NET 8, theIExceptionHandler interface is the current recommended standard for global error management. It is utilized internally by the framework and offers a more structured approach than traditional middleware.

The interface requires implementing a single method, TryHandleAsync, which processes the HTTP context and the specific exception. A major advantage is that it integrates directly with the existing UseExceptionHandler middleware, eliminating the need for a custom middleware class.

This approach allows for modular, maintainable code by enabling separate handling logic for different error types. The following example demonstrates how to implement IExceptionHandler:

The AppExceptionHandler class implements the IExceptionHandler interface to centralize error logic. The TryHandleAsync method processes the exception and returns true to signal that the error has been successfully handled. Returning false would allow the error to pass to the next handler in a chain.

public class AppExceptionHandler(ILogger<AppExceptionHandler> logger) : IExceptionHandler
{
    public async ValueTask<bool> TryHandleAsync(
        HttpContext context,
        Exception exception,
        CancellationToken cancellationToken)
    {
        var details = new ProblemDetails
        {
            Instance = context.Request.Path,
            Status = StatusCodes.Status500InternalServerError
        };

        if (exception is GlobalAppException appEx)
        {
            context.Response.StatusCode = (int)appEx.ResultStatusCode;
            details.Title = appEx.Message;
            details.Status = (int)appEx.ResultStatusCode;
        }
        else
        {
            details.Title = "An unexpected error occurred.";
        }

        logger.LogError(exception, "{ErrorTitle}", details.Title);

        await context.Response.WriteAsJsonAsync(details, cancellationToken);

        return true;
    }
}

To activate this handler, register it in Program.cs. This setup links the implementation with the built-in Problem Details services and the standard exception middleware.

builder.Services.AddExceptionHandler<AppExceptionHandler>();
builder.Services.AddProblemDetails();

// ... other configurations

var app = builder.Build();

app.UseExceptionHandler(); // Middleware to use the registered handlers
Conclusion

In this article we have seen various strategies for managing errors in ASP.NET Core. TheIExceptionHandler interface remains the recommended standard for modern applications, offering superior control and readability. Implementing this centralized approach ensures a cleaner, more maintainable, and resilient codebase. Hope you will find this useful.

Windows Hosting Recommendation

HostForLIFE.eu receives Spotlight standing advantage award for providing recommended, cheap and fast ecommerce Hosting including the latest Magento. From the leading technology company, Microsoft. All the servers are equipped with the newest Windows Server 2022 R2, SQL Server 2022, ASP.NET Core 10.0 , ASP.NET MVC, Silverlight 5, WebMatrix and Visual Studio Lightswitch. Security and performance are at the core of their Magento hosting operations to confirm every website and/or application hosted on their servers is highly secured and performs at optimum level. mutually of the European ASP.NET hosting suppliers, HostForLIFE guarantees 99.9% uptime and fast loading speed. From €3.49/month , HostForLIFE provides you with unlimited disk space, unlimited domains, unlimited bandwidth,etc, for your website hosting needs.
 
https://hostforlifeasp.net/

 

Previous PostOlder Post Home

0 comments:

Post a Comment