Introduction

Error handling is a crucial aspect of developing reliable APIs in .NET. Effective error handling not only ensures a smooth user experience but also helps in troubleshooting and debugging issues efficiently. In this blog, we’ll explore the best practices for API error handling in .NET, along with clear examples to demonstrate each concept.

Define Clear and Consistent Error Responses

Example

{
  "error": {
    "code": 400,
    "message": "Invalid request parameters.",
    "details": "The 'id' parameter is missing."
  }
}

Exception Handling

Example

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace API_Error_Handling.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeesController : ControllerBase
    {
        private readonly ILogger<EmployeesController> _logger;

        public EmployeesController(ILogger<EmployeesController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IActionResult GetEmployees()
        {
            try
            {
                throw new NotImplementedException();
            }
            catch (Exception ex)
            {
                // Log the exception
                _logger.LogError(ex, "An error occurred");

                // Return a generic error response
                return StatusCode(500, "An unexpected error occurred, Please try again later.");
            }
        }
    }
}

Output

Output

Use Custom Exception Types

Scenario

Imagine an application for managing employee data. We can create a custom exception to handle situations where a user tries to assign a negative salary to an employee.

Custom Exception Class

 public class InvalidSalaryException : Exception
 {
     public decimal RequestedSalary { get; private set; }

     public InvalidSalaryException() { }

     public InvalidSalaryException(decimal requestedSalary)
         : base($"Salary cannot be negative. You tried to assign: {requestedSalary}")
     {
         RequestedSalary = requestedSalary;
     }
 }

Explanation

Throwing the Exception

 public void UpdateEmployeeSalary(int employeeId, decimal newSalary)
 {
     if (newSalary < 0)
     {
         throw new InvalidSalaryException(newSalary);
     }
 }

Catching and Handling the Exception

[HttpGet(nameof(GetEmployeeSalary))]
public IActionResult GetEmployeeSalary()
{
    try
    {
        CustomException customException = new();
        customException.UpdateEmployeeSalary(1, -1000); // Invalid salary
        return Ok();
    }
    catch (InvalidSalaryException ex)
    {
        _logger.LogError("Error updating salary: " + ex.Message);
        return StatusCode(403, "Please enter a valid positive salary.");
    }
}

Output

Error

Global Error Handling

“In my next blog post, I’ll be covering Global Error Handling in more depth.”

Logging and Monitoring

Source Code

Download code from here

Keep Learning!