DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Database Query Service With OpenAI and PostgreSQL in .NET
  • Yes! I Can Finally Run My .NET Application on Heroku!
  • Microservices With .NET Core: Building Scalable and Resilient Applications
  • Docker + .NET APIs: Simplifying Deployment and Scaling

Trending

  • How the Go Runtime Preempts Goroutines for Efficient Concurrency
  • AI, ML, and Data Science: Shaping the Future of Automation
  • Evolution of Cloud Services for MCP/A2A Protocols in AI Agents
  • It’s Not About Control — It’s About Collaboration Between Architecture and Security

Best Practices for Error Handling in .Net 6

There are many .NET exception handling and logging tools that help developers integrate global error handling and logging into their applications.

By 
Jason Archer user avatar
Jason Archer
·
Sep. 13, 22 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
13.6K Views

Join the DZone community and get the full member experience.

Join For Free

Quick Microsoft .NET 6 Overview

Microsoft .NET 6 is a cross-platform framework that merges the .NET Core, .NET Framework, and  Xamarin/Mono technologies into a single framework. Continuing the unification that started with .NET 5 by unifying the runtime and SDK for desktop, web, mobile, and cloud applications.

Alongside C# 10 and Visual Studio 2022, Microsoft made .NET 6 generally available on November 9, 2021. There are many new enhancements to .NET 6, including:

  • Improved performance
  • Profile - guided optimizing
  • Security improvements 
  • C# 10 and F# 6 improvements

Error Handling Using Try-Catch Blocks

Try-catch blocks are the most basic way of handling exceptions and are most widely used and generally used to gracefully handle code statements that might generate an exception. 

Consider the following ProcessFile class as a code example:

C#
 
using System;
using System.IO;

public class ProcessFile
{
    public static void Main()
    {
        try
        {
            using (StreamReader sr = File.OpenText("data.txt"))
            {
                Console.WriteLine($"The first line of this file is {sr.ReadLine()}");
            }
        }
        catch (FileNotFoundException e)
        {
            Console.WriteLine($"The file was not found: '{e}'");
        }
        catch (DirectoryNotFoundException e)
        {
            Console.WriteLine($"The directory was not found: '{e}'");
        }
        catch (IOException e)
        {
            Console.WriteLine($"The file could not be opened: '{e}'");
        }
      	catch (Exception e)
        {
            Console.WriteLine($"General exception: '{e}'");
        }
    }
}


The above code example is a typical case where we use try-catch to handle the exception. Any exception thrown by the code enclosed within the try block will be caught and handled by the catch block. Also illustrated is the use of catching multiple exception types, which is useful for handling different exceptions uniquely for the same block of code.

Try-catch blocks are best used within methods in which an error might occur, and you would like to handle it appropriately and uniquely for the end user or service. Every developer should be aware of try-catch blocks as it is a useful tools to develop robust applications. However, adding a try-catch block to every method is not desirable and can get messy quickly. It's best to use global exception handling and try-catch block where uniquely needed.

Global Exception Handling

Global exception handling enables an application with a much broader ability to handle all exceptions. This is usually done through custom middleware for ASP.NET core applications, AppDomain unhandled exception events for .NET core console and service applications, or .NET 3rd party exception handling libraries.

ASP.NET Core Global Exception Handling With Custom Middleware

Using custom middleware to handle global exceptions provides a better development and application experience.

Consider the following CustomExceptionHandlingMiddleware class as a Custom Middleware example:

C#
 
using System.Net;
using System.Text.Json;
using ExceptionHandling.Models.Responses;

namespace Middleware;

public class CustomExceptionHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<CustomExceptionHandlingMiddleware> _logger;

    public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<CustomExceptionHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }
    
    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(httpContext, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        var response = context.Response;

        var errorResponse = new ErrorResponse
        {
            Success = false
        };
        switch (exception)
        {
            case ApplicationException ex:
                if (ex.Message.Contains("Unauthorized"))
                {
                    response.StatusCode = (int) HttpStatusCode.Forbidden;
                    errorResponse.Message = ex.Message;
                    break;
                }
                response.StatusCode = (int) HttpStatusCode.BadRequest;
                errorResponse.Message = ex.Message;
                break;
            default:
                response.StatusCode = (int) HttpStatusCode.InternalServerError;
                errorResponse.Message = "Internal server error!";
                break;
        }
        _logger.LogError(exception.Message);
        var result = JsonSerializer.Serialize(errorResponse);
        await context.Response.WriteAsync(result);
    }
}


Next, you must register your middleware in your Program class.

C#
 
app.UseMiddleware<ExceptionHandlingMiddleware>();


.NET Core Console Global Exception Handling

Global exception handling in console apps is done through the AppDomain unhandled exception event. Here you can add custom logic around what happens when an unhandled exception occurs.

Consider the following code from a sample Program class that catches and logs exceptions:

C#
 
var logger = host.Services.GetRequiredService<ILogger<Program>>();
System.AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    var exception = e.ExceptionObject as Exception;
    logger.LogError(exception, exception.Message);
}


3rd Party Logging and Exception Handling

There are many .NET exception handling and logging tools that help developers integrate global error handling and logging into their applications. This removes a lot of the heavy lifting from the developer with easier implementation and management.

Consider this example of ClearInsights Logging for global exception handling:

ASP.NET Core

C#
 
using ClearInsights.Logging;
using System.Net;

var builder = WebApplication.CreateBuilder(args);

//Add to capture logs with ClearInsights Logging
builder.Logging.AddClearInsightsLogger(configuration =>
{
    configuration.ApiKey = "{ApiKey}";
    configuration.Secret = "{Environment Client Secret}";
    configuration.ApplicationName = "{Application Name}";
});


var app = builder.Build();

//Add to use ClearInsights global error handling.
//This will automatically catch and log any unhandled exceptions
app.UseClearInsightsExceptionHandling(options =>
{
    //Add to extend the error handler and add additional logic.
    //Add logic like custom HTTP response, etc...
    options.OnError += (sender, arg) =>
    {
        var response = "Oops something went wrong";
        arg.HttpContext.Response.ContentType = "text/html";
        arg.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
        arg.HttpContext.Response.WriteAsync(response);
    };
});


.NET Core

C#
 
using ClearInsights.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(builder =>
        builder.ClearProviders()
            //Add to capture logs with ClearInsights Logging
            .AddClearInsightsLogger(configuration =>
            {
                configuration.ApiKey = "{ApiKey}";
                configuration.Secret = "{Environment Client Secret}";
                configuration.ApplicationName = "{Application Name}";
            }))    
            .Build();

//Add to use ClearInsights global error handling.
//This will automatically catch and log any unhandled exceptions
System.AppDomain.CurrentDomain.UseClearInsightsExceptionHandling(host.Services.GetRequiredService<ILogger<Program>>());



Net (command)

Opinions expressed by DZone contributors are their own.

Related

  • Database Query Service With OpenAI and PostgreSQL in .NET
  • Yes! I Can Finally Run My .NET Application on Heroku!
  • Microservices With .NET Core: Building Scalable and Resilient Applications
  • Docker + .NET APIs: Simplifying Deployment and Scaling

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!