No articles found
Try different keywords or browse our categories
Fix: 500 Internal Server Error in ASP.NET Core - Complete Error Handling Guide
Learn how to fix the 500 Internal Server Error in ASP.NET Core applications. This comprehensive guide covers error diagnosis, debugging techniques, and proper error handling implementation.
The ‘500 Internal Server Error’ is one of the most common and frustrating HTTP status errors in ASP.NET Core applications. This generic server-side error indicates that something went wrong on the server, but doesn’t provide specific details about what caused the issue. Understanding and resolving this error is crucial for building robust ASP.NET Core applications that provide a good user experience.
This comprehensive guide explains what causes the 500 Internal Server Error, why it happens, and provides multiple solutions to fix and prevent it in your ASP.NET Core projects with clean code examples and directory structure.
What is the 500 Internal Server Error?
The 500 Internal Server Error occurs when:
- An unhandled exception occurs in your ASP.NET Core application
- The server encounters an unexpected condition that prevents it from fulfilling the request
- Database connection issues occur
- Configuration problems exist
- File access permissions are incorrect
- Memory or resource limitations are reached
- Third-party service failures occur
Common Error Messages:
500 - Internal Server ErrorHTTP Error 500.0 - Internal Server Error500.32 - ANCM Failed to Start Within Startup Time Limit500.0 - ANCM In-Process Handler Load FailureSystem.Exception: An error occurred while processing your request
Understanding the Problem
In ASP.NET Core, the 500 Internal Server Error is a generic HTTP status code that indicates a server-side problem. Unlike client-side errors (4xx), this error means the server received the request but couldn’t process it due to an internal issue. The error can be caused by various factors including unhandled exceptions, configuration issues, resource problems, or dependency failures.
Typical ASP.NET Core Project Structure:
MyAspNetCoreApp/
├── MyAspNetCoreApp.sln
├── src/
│ ├── MyAspNetCoreApp/
│ │ ├── Program.cs
│ │ ├── Startup.cs
│ │ ├── Controllers/
│ │ │ ├── HomeController.cs
│ │ │ └── UserController.cs
│ │ ├── Models/
│ │ │ ├── User.cs
│ │ │ └── ErrorViewModel.cs
│ │ ├── Services/
│ │ │ ├── IUserService.cs
│ │ │ └── UserService.cs
│ │ ├── Data/
│ │ │ ├── ApplicationDbContext.cs
│ │ │ └── SeedData.cs
│ │ ├── Middleware/
│ │ │ ├── ErrorHandlingMiddleware.cs
│ │ │ └── RequestLoggingMiddleware.cs
│ │ ├── MyAspNetCoreApp.csproj
│ │ └── appsettings.json
│ └── MyAspNetCoreApp.Tests/
│ ├── UnitTests.cs
│ └── MyAspNetCoreApp.Tests.csproj
├── packages/
└── bin/
Solution 1: Proper Exception Handling and Logging
The most fundamental approach to prevent and diagnose 500 errors is to implement proper exception handling and logging.
❌ Without Proper Exception Handling:
// Controllers/UserController.cs - ❌ No exception handling
using Microsoft.AspNetCore.Mvc;
using MyAspNetCoreApp.Services;
namespace MyAspNetCoreApp.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
// ❌ If this throws an exception, it will cause a 500 error
var user = _userService.GetUserById(id); // ❌ Could throw exception
return Ok(user);
}
}
}
✅ With Proper Exception Handling:
Services/IUserService.cs:
using MyAspNetCoreApp.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Services
{
public interface IUserService
{
Task<List<User>> GetUsersAsync();
Task<User> GetUserByIdAsync(int id);
Task<User> CreateUserAsync(User user);
Task<User> UpdateUserAsync(int id, User user);
Task<bool> DeleteUserAsync(int id);
Task<User> GetUserByEmailAsync(string email);
}
}
Services/UserService.cs:
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Services
{
public class UserService : IUserService
{
private readonly ILogger<UserService> _logger;
private readonly List<User> _users;
public UserService(ILogger<UserService> logger)
{
_logger = logger;
_users = new List<User>
{
new User { Id = 1, Name = "John Doe", Email = "john@example.com", IsActive = true },
new User { Id = 2, Name = "Jane Smith", Email = "jane@example.com", IsActive = true },
new User { Id = 3, Name = "Bob Johnson", Email = "bob@example.com", IsActive = false }
};
}
public async Task<List<User>> GetUsersAsync()
{
try
{
_logger.LogInformation("Getting all users");
return await Task.FromResult(_users.ToList());
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting users");
throw new InvalidOperationException("Failed to retrieve users", ex);
}
}
public async Task<User> GetUserByIdAsync(int id)
{
try
{
_logger.LogInformation("Getting user with ID: {UserId}", id);
if (id <= 0)
{
_logger.LogWarning("Invalid user ID: {UserId}", id);
return null;
}
var user = _users.FirstOrDefault(u => u.Id == id);
if (user == null)
{
_logger.LogWarning("User not found with ID: {UserId}", id);
return null;
}
return await Task.FromResult(user);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user with ID: {UserId}", id);
throw new InvalidOperationException($"Failed to retrieve user with ID {id}", ex);
}
}
public async Task<User> CreateUserAsync(User user)
{
try
{
_logger.LogInformation("Creating new user: {UserName}", user?.Name);
if (user == null)
{
_logger.LogWarning("Attempted to create null user");
throw new ArgumentNullException(nameof(user));
}
if (string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email))
{
_logger.LogWarning("Invalid user data for creation: Name={Name}, Email={Email}",
user.Name, user.Email);
throw new ArgumentException("User name and email are required");
}
// Check for duplicate email
if (_users.Any(u => u.Email.Equals(user.Email, StringComparison.OrdinalIgnoreCase)))
{
_logger.LogWarning("Duplicate email attempted: {Email}", user.Email);
throw new InvalidOperationException("A user with this email already exists");
}
user.Id = _users.Any() ? _users.Max(u => u.Id) + 1 : 1;
user.CreatedAt = DateTime.UtcNow;
_users.Add(user);
_logger.LogInformation("User created successfully with ID: {UserId}", user.Id);
return await Task.FromResult(user);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating user: {UserName}", user?.Name);
throw new InvalidOperationException("Failed to create user", ex);
}
}
public async Task<User> UpdateUserAsync(int id, User user)
{
try
{
_logger.LogInformation("Updating user with ID: {UserId}", id);
if (id <= 0 || user == null)
{
_logger.LogWarning("Invalid update parameters: ID={UserId}, UserIsNull={IsNull}",
id, user == null);
return null;
}
var existingUser = _users.FirstOrDefault(u => u.Id == id);
if (existingUser == null)
{
_logger.LogWarning("Attempted to update non-existent user with ID: {UserId}", id);
return null;
}
// Validate update data
if (string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email))
{
_logger.LogWarning("Invalid user data for update: Name={Name}, Email={Email}",
user.Name, user.Email);
throw new ArgumentException("User name and email are required");
}
// Check for duplicate email (excluding current user)
var duplicateEmailUser = _users.FirstOrDefault(u =>
u.Email.Equals(user.Email, StringComparison.OrdinalIgnoreCase) && u.Id != id);
if (duplicateEmailUser != null)
{
_logger.LogWarning("Duplicate email attempted for user {UserId}: {Email}", id, user.Email);
throw new InvalidOperationException("A user with this email already exists");
}
existingUser.Name = user.Name;
existingUser.Email = user.Email;
existingUser.IsActive = user.IsActive;
existingUser.UpdatedAt = DateTime.UtcNow;
_logger.LogInformation("User updated successfully: {UserId}", id);
return await Task.FromResult(existingUser);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while updating user with ID: {UserId}", id);
throw new InvalidOperationException($"Failed to update user with ID {id}", ex);
}
}
public async Task<bool> DeleteUserAsync(int id)
{
try
{
_logger.LogInformation("Deleting user with ID: {UserId}", id);
if (id <= 0)
{
_logger.LogWarning("Invalid user ID for deletion: {UserId}", id);
return false;
}
var user = _users.FirstOrDefault(u => u.Id == id);
if (user == null)
{
_logger.LogWarning("Attempted to delete non-existent user with ID: {UserId}", id);
return false;
}
_users.Remove(user);
_logger.LogInformation("User deleted successfully: {UserId}", id);
return await Task.FromResult(true);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while deleting user with ID: {UserId}", id);
throw new InvalidOperationException($"Failed to delete user with ID {id}", ex);
}
}
public async Task<User> GetUserByEmailAsync(string email)
{
try
{
_logger.LogInformation("Getting user by email: {Email}", email);
if (string.IsNullOrWhiteSpace(email))
{
_logger.LogWarning("Invalid email for lookup: {Email}", email);
return null;
}
var user = _users.FirstOrDefault(u =>
u.Email.Equals(email, StringComparison.OrdinalIgnoreCase));
if (user == null)
{
_logger.LogWarning("User not found with email: {Email}", email);
}
return await Task.FromResult(user);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user by email: {Email}", email);
throw new InvalidOperationException($"Failed to retrieve user with email {email}", ex);
}
}
// ✅ Additional service methods with proper error handling
public async Task<List<User>> GetActiveUsersAsync()
{
try
{
_logger.LogInformation("Getting active users");
var activeUsers = _users.Where(u => u.IsActive).ToList();
return await Task.FromResult(activeUsers);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting active users");
throw new InvalidOperationException("Failed to retrieve active users", ex);
}
}
public async Task<int> GetUserCountAsync()
{
try
{
_logger.LogInformation("Getting user count");
return await Task.FromResult(_users.Count);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user count");
throw new InvalidOperationException("Failed to retrieve user count", ex);
}
}
}
}
Models/User.cs:
using System;
namespace MyAspNetCoreApp.Models
{
public class User
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public bool IsActive { get; set; } = true;
public string? Role { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; }
}
}
Middleware/ErrorHandlingMiddleware.cs:
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Middleware
{
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unhandled exception occurred: {Message}", ex.Message);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
context.Response.ContentType = "application/json";
var response = new
{
error = "An error occurred while processing your request.",
details = string.Empty // Don't expose internal details in production
};
// ✅ Set appropriate status code based on exception type
switch (exception)
{
case ArgumentException:
case ArgumentNullException:
case InvalidOperationException:
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
response = new
{
error = "Invalid request parameters.",
details = "The request contains invalid parameters."
};
break;
case UnauthorizedAccessException:
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
response = new
{
error = "Unauthorized access.",
details = "You don't have permission to access this resource."
};
break;
default:
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
response = new
{
error = "An internal server error occurred.",
details = "Please try again later or contact support."
};
break;
}
var jsonResponse = System.Text.Json.JsonSerializer.Serialize(response);
await context.Response.WriteAsync(jsonResponse);
}
}
}
Program.cs (for .NET 6+):
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Middleware;
using MyAspNetCoreApp.Services;
var builder = WebApplication.CreateBuilder(args);
// ✅ Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// ✅ Add logging
builder.Services.AddLogging();
// ✅ Register services
builder.Services.AddScoped<IUserService, UserService>();
var app = builder.Build();
// ✅ Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
// ✅ In development, show detailed errors
app.UseDeveloperExceptionPage();
}
else
{
// ✅ In production, use custom error handling
app.UseMiddleware<ErrorHandlingMiddleware>();
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Solution 2: Use Global Exception Handler
Implement a global exception handler to catch and properly handle all unhandled exceptions.
Middleware/GlobalExceptionHandlerMiddleware.cs:
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.Json;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Middleware
{
public class GlobalExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionHandlerMiddleware> _logger;
public GlobalExceptionHandlerMiddleware(
RequestDelegate next,
ILogger<GlobalExceptionHandlerMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
_logger.LogError(
exception,
"An unhandled exception occurred while processing request: {Path}",
context.Request.Path);
var response = new
{
timestamp = DateTime.UtcNow,
status = (int)HttpStatusCode.InternalServerError,
error = "Internal Server Error",
message = "An error occurred while processing your request.",
path = context.Request.Path,
details = new Dictionary<string, object>()
};
// ✅ Add specific error details based on exception type
switch (exception)
{
case InvalidOperationException invalidOpEx:
response = response with {
status = (int)HttpStatusCode.BadRequest,
error = "Bad Request",
message = invalidOpEx.Message
};
break;
case ArgumentException argEx:
response = response with {
status = (int)HttpStatusCode.BadRequest,
error = "Bad Request",
message = argEx.Message
};
break;
case UnauthorizedAccessException unauthorizedEx:
response = response with {
status = (int)HttpStatusCode.Unauthorized,
error = "Unauthorized",
message = unauthorizedEx.Message
};
break;
case KeyNotFoundException keyNotFoundEx:
response = response with {
status = (int)HttpStatusCode.NotFound,
error = "Not Found",
message = keyNotFoundEx.Message
};
break;
default:
// ✅ For security, don't expose internal exception details in production
if (context.Request.Host.Value.Contains("localhost") ||
context.Request.Host.Value.Contains("127.0.0.1"))
{
response.details = new Dictionary<string, object>
{
["exceptionType"] = exception.GetType().Name,
["exceptionMessage"] = exception.Message,
["stackTrace"] = exception.StackTrace
};
}
break;
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = response.status;
var jsonResponse = JsonSerializer.Serialize(response, new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});
await context.Response.WriteAsync(jsonResponse);
}
}
}
Controllers/UserController.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Models;
using MyAspNetCoreApp.Services;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
private readonly ILogger<UserController> _logger;
public UserController(
IUserService userService,
ILogger<UserController> logger)
{
_userService = userService;
_logger = logger;
}
[HttpGet]
public async Task<IActionResult> GetUsers()
{
try
{
_logger.LogInformation("Getting all users");
var users = await _userService.GetUsersAsync();
return Ok(users);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting users");
return StatusCode(500, new { message = "An error occurred while retrieving users" });
}
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
try
{
_logger.LogInformation("Getting user with ID: {UserId}", id);
if (id <= 0)
{
return BadRequest(new { message = "Invalid user ID" });
}
var user = await _userService.GetUserByIdAsync(id);
if (user == null)
{
return NotFound(new { message = $"User with ID {id} not found" });
}
return Ok(user);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user with ID: {UserId}", id);
return StatusCode(500, new { message = "An error occurred while retrieving the user" });
}
}
[HttpPost]
public async Task<IActionResult> CreateUser([FromBody] User user)
{
try
{
_logger.LogInformation("Creating new user: {UserName}", user?.Name);
if (user == null)
{
return BadRequest(new { message = "User data is required" });
}
if (string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email))
{
return BadRequest(new { message = "User name and email are required" });
}
var createdUser = await _userService.CreateUserAsync(user);
return CreatedAtAction(nameof(GetUser), new { id = createdUser.Id }, createdUser);
}
catch (ArgumentException ex)
{
_logger.LogWarning(ex, "Invalid user data provided for creation");
return BadRequest(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Operation failed during user creation");
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating user: {UserName}", user?.Name);
return StatusCode(500, new { message = "An error occurred while creating the user" });
}
}
[HttpPut("{id}")]
public async Task<IActionResult> UpdateUser(int id, [FromBody] User user)
{
try
{
_logger.LogInformation("Updating user with ID: {UserId}", id);
if (id <= 0)
{
return BadRequest(new { message = "Invalid user ID" });
}
if (user == null)
{
return BadRequest(new { message = "User data is required" });
}
if (id != user.Id)
{
return BadRequest(new { message = "User ID mismatch" });
}
var updatedUser = await _userService.UpdateUserAsync(id, user);
if (updatedUser == null)
{
return NotFound(new { message = $"User with ID {id} not found" });
}
return Ok(updatedUser);
}
catch (ArgumentException ex)
{
_logger.LogWarning(ex, "Invalid user data provided for update");
return BadRequest(new { message = ex.Message });
}
catch (InvalidOperationException ex)
{
_logger.LogWarning(ex, "Operation failed during user update");
return BadRequest(new { message = ex.Message });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while updating user with ID: {UserId}", id);
return StatusCode(500, new { message = "An error occurred while updating the user" });
}
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteUser(int id)
{
try
{
_logger.LogInformation("Deleting user with ID: {UserId}", id);
if (id <= 0)
{
return BadRequest(new { message = "Invalid user ID" });
}
var success = await _userService.DeleteUserAsync(id);
if (!success)
{
return NotFound(new { message = $"User with ID {id} not found" });
}
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while deleting user with ID: {UserId}", id);
return StatusCode(500, new { message = "An error occurred while deleting the user" });
}
}
[HttpGet("active")]
public async Task<IActionResult> GetActiveUsers()
{
try
{
_logger.LogInformation("Getting active users");
var users = await _userService.GetActiveUsersAsync();
return Ok(users);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting active users");
return StatusCode(500, new { message = "An error occurred while retrieving active users" });
}
}
[HttpGet("count")]
public async Task<IActionResult> GetUserCount()
{
try
{
_logger.LogInformation("Getting user count");
var count = await _userService.GetUserCountAsync();
return Ok(new { count });
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user count");
return StatusCode(500, new { message = "An error occurred while retrieving user count" });
}
}
[HttpGet("email/{email}")]
public async Task<IActionResult> GetUserByEmail(string email)
{
try
{
_logger.LogInformation("Getting user by email: {Email}", email);
if (string.IsNullOrWhiteSpace(email))
{
return BadRequest(new { message = "Email is required" });
}
var user = await _userService.GetUserByEmailAsync(email);
if (user == null)
{
return NotFound(new { message = $"User with email {email} not found" });
}
return Ok(user);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user by email: {Email}", email);
return StatusCode(500, new { message = "An error occurred while retrieving the user" });
}
}
}
}
Solution 3: Configure Proper Error Pages
Set up proper error pages for different environments to handle 500 errors gracefully.
Controllers/ErrorController.cs:
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Models;
using System;
namespace MyAspNetCoreApp.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ErrorController : ControllerBase
{
private readonly ILogger<ErrorController> _logger;
public ErrorController(ILogger<ErrorController> logger)
{
_logger = logger;
}
[HttpGet]
[Route("error")]
public IActionResult Error()
{
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionFeature != null)
{
var exception = exceptionFeature.Error;
_logger.LogError(exception, "An error occurred: {Message}", exception.Message);
// ✅ Log the error details
var errorViewModel = new ErrorViewModel
{
RequestId = HttpContext.TraceIdentifier,
ErrorMessage = exception.Message,
StackTrace = exception.StackTrace,
Path = exceptionFeature.Path
};
// ✅ Return appropriate error response
return StatusCode(500, new
{
error = "Internal Server Error",
message = "An error occurred while processing your request.",
requestId = errorViewModel.RequestId
});
}
return StatusCode(500, new
{
error = "Internal Server Error",
message = "An unknown error occurred."
});
}
[HttpGet]
[Route("error/{statusCode}")]
public IActionResult ErrorWithStatusCode(int statusCode)
{
switch (statusCode)
{
case 404:
return NotFound(new { error = "Not Found", message = "The requested resource was not found." });
case 400:
return BadRequest(new { error = "Bad Request", message = "The request was invalid." });
case 500:
return StatusCode(500, new { error = "Internal Server Error", message = "An internal server error occurred." });
default:
return StatusCode(statusCode, new { error = "Error", message = "An error occurred." });
}
}
}
}
Models/ErrorViewModel.cs:
namespace MyAspNetCoreApp.Models
{
public class ErrorViewModel
{
public string RequestId { get; set; } = string.Empty;
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string ErrorMessage { get; set; } = string.Empty;
public string? StackTrace { get; set; }
public string? Path { get; set; }
}
}
Solution 4: Database Connection Error Handling
Handle database-related 500 errors properly with connection and query error handling.
Data/ApplicationDbContext.cs:
using Microsoft.EntityFrameworkCore;
using MyAspNetCoreApp.Models;
namespace MyAspNetCoreApp.Data
{
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name).IsRequired().HasMaxLength(100);
entity.Property(e => e.Email).IsRequired().HasMaxLength(255);
entity.HasIndex(e => e.Email).IsUnique();
});
base.OnModelCreating(modelBuilder);
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
try
{
return await base.SaveChangesAsync(cancellationToken);
}
catch (DbUpdateException ex)
{
// ✅ Handle database update exceptions
throw new InvalidOperationException("Database update failed", ex);
}
catch (Exception ex)
{
// ✅ Handle other database exceptions
throw new InvalidOperationException("Database operation failed", ex);
}
}
}
}
Services/DatabaseUserService.cs:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Data;
using MyAspNetCoreApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Services
{
public class DatabaseUserService : IUserService
{
private readonly ApplicationDbContext _context;
private readonly ILogger<DatabaseUserService> _logger;
public DatabaseUserService(
ApplicationDbContext context,
ILogger<DatabaseUserService> logger)
{
_context = context;
_logger = logger;
}
public async Task<List<User>> GetUsersAsync()
{
try
{
_logger.LogInformation("Getting all users from database");
return await _context.Users.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting users from database");
throw new InvalidOperationException("Failed to retrieve users from database", ex);
}
}
public async Task<User> GetUserByIdAsync(int id)
{
try
{
_logger.LogInformation("Getting user with ID: {UserId} from database", id);
if (id <= 0)
{
_logger.LogWarning("Invalid user ID: {UserId}", id);
return null;
}
var user = await _context.Users.FindAsync(id);
if (user == null)
{
_logger.LogWarning("User not found with ID: {UserId}", id);
}
return user;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user with ID: {UserId} from database", id);
throw new InvalidOperationException($"Failed to retrieve user with ID {id} from database", ex);
}
}
public async Task<User> CreateUserAsync(User user)
{
try
{
_logger.LogInformation("Creating new user in database: {UserName}", user?.Name);
if (user == null)
{
_logger.LogWarning("Attempted to create null user in database");
throw new ArgumentNullException(nameof(user));
}
if (string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email))
{
_logger.LogWarning("Invalid user data for creation in database: Name={Name}, Email={Email}",
user.Name, user.Email);
throw new ArgumentException("User name and email are required");
}
_context.Users.Add(user);
await _context.SaveChangesAsync();
_logger.LogInformation("User created successfully in database with ID: {UserId}", user.Id);
return user;
}
catch (DbUpdateException ex)
{
_logger.LogError(ex, "Database update error while creating user: {UserName}", user?.Name);
throw new InvalidOperationException("Failed to create user in database due to a database constraint", ex);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while creating user in database: {UserName}", user?.Name);
throw new InvalidOperationException("Failed to create user in database", ex);
}
}
public async Task<User> UpdateUserAsync(int id, User user)
{
try
{
_logger.LogInformation("Updating user in database with ID: {UserId}", id);
if (id <= 0 || user == null)
{
_logger.LogWarning("Invalid update parameters for database: ID={UserId}, UserIsNull={IsNull}",
id, user == null);
return null;
}
var existingUser = await _context.Users.FindAsync(id);
if (existingUser == null)
{
_logger.LogWarning("Attempted to update non-existent user in database with ID: {UserId}", id);
return null;
}
// Update properties
existingUser.Name = user.Name;
existingUser.Email = user.Email;
existingUser.IsActive = user.IsActive;
existingUser.UpdatedAt = DateTime.UtcNow;
await _context.SaveChangesAsync();
_logger.LogInformation("User updated successfully in database: {UserId}", id);
return existingUser;
}
catch (DbUpdateException ex)
{
_logger.LogError(ex, "Database update error while updating user with ID: {UserId}", id);
throw new InvalidOperationException("Failed to update user in database due to a database constraint", ex);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while updating user in database with ID: {UserId}", id);
throw new InvalidOperationException($"Failed to update user with ID {id} in database", ex);
}
}
public async Task<bool> DeleteUserAsync(int id)
{
try
{
_logger.LogInformation("Deleting user in database with ID: {UserId}", id);
if (id <= 0)
{
_logger.LogWarning("Invalid user ID for deletion in database: {UserId}", id);
return false;
}
var user = await _context.Users.FindAsync(id);
if (user == null)
{
_logger.LogWarning("Attempted to delete non-existent user in database with ID: {UserId}", id);
return false;
}
_context.Users.Remove(user);
await _context.SaveChangesAsync();
_logger.LogInformation("User deleted successfully in database: {UserId}", id);
return true;
}
catch (DbUpdateException ex)
{
_logger.LogError(ex, "Database update error while deleting user with ID: {UserId}", id);
throw new InvalidOperationException("Failed to delete user in database due to a database constraint", ex);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while deleting user in database with ID: {UserId}", id);
throw new InvalidOperationException($"Failed to delete user with ID {id} in database", ex);
}
}
public async Task<User> GetUserByEmailAsync(string email)
{
try
{
_logger.LogInformation("Getting user by email from database: {Email}", email);
if (string.IsNullOrWhiteSpace(email))
{
_logger.LogWarning("Invalid email for lookup in database: {Email}", email);
return null;
}
var user = await _context.Users
.FirstOrDefaultAsync(u => u.Email.Equals(email, StringComparison.OrdinalIgnoreCase));
if (user == null)
{
_logger.LogWarning("User not found with email in database: {Email}", email);
}
return user;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user by email from database: {Email}", email);
throw new InvalidOperationException($"Failed to retrieve user with email {email} from database", ex);
}
}
// ✅ Additional database service methods
public async Task<List<User>> GetActiveUsersAsync()
{
try
{
_logger.LogInformation("Getting active users from database");
return await _context.Users
.Where(u => u.IsActive)
.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting active users from database");
throw new InvalidOperationException("Failed to retrieve active users from database", ex);
}
}
public async Task<int> GetUserCountAsync()
{
try
{
_logger.LogInformation("Getting user count from database");
return await _context.Users.CountAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error occurred while getting user count from database");
throw new InvalidOperationException("Failed to retrieve user count from database", ex);
}
}
}
}
Solution 5: Configuration and Environment Error Handling
Handle configuration-related 500 errors and environment-specific issues.
Program.cs with Enhanced Error Handling:
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Data;
using MyAspNetCoreApp.Middleware;
using MyAspNetCoreApp.Services;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// ✅ Add configuration
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
builder.Configuration.AddEnvironmentVariables();
try
{
// ✅ Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// ✅ Add logging
builder.Services.AddLogging();
// ✅ Add Entity Framework
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(connectionString))
{
throw new InvalidOperationException("Database connection string is not configured");
}
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
// ✅ Register services with proper error handling
builder.Services.AddScoped<IUserService, DatabaseUserService>();
var app = builder.Build();
// ✅ Configure the HTTP request pipeline
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
// ✅ In development, show detailed errors
app.UseDeveloperExceptionPage();
}
else
{
// ✅ In production, use custom error handling
app.UseMiddleware<GlobalExceptionHandlerMiddleware>();
app.UseExceptionHandler("/api/error");
app.UseHsts();
}
// ✅ Ensure database is created
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
try
{
context.Database.EnsureCreated();
}
catch (Exception ex)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the database.");
throw;
}
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
catch (Exception ex)
{
var logger = builder.Services.BuildServiceProvider().GetService<ILogger<Program>>();
logger?.LogCritical(ex, "An unhandled exception occurred during startup");
throw;
}
appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyAspNetCoreApp;Trusted_Connection=true;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.EntityFrameworkCore": "Warning"
}
},
"AllowedHosts": "*",
"ErrorHandling": {
"LogSensitiveData": false,
"ShowDetailedErrors": false
}
}
Working Code Examples
Complete ASP.NET Core Application with Error Handling:
// Program.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MyAspNetCoreApp.Data;
using MyAspNetCoreApp.Middleware;
using MyAspNetCoreApp.Services;
var builder = WebApplication.CreateBuilder(args);
// ✅ Add configuration
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
builder.Configuration.AddEnvironmentVariables();
try
{
// ✅ Add services to the container
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// ✅ Add logging
builder.Services.AddLogging();
// ✅ Add Entity Framework with proper error handling
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(connectionString))
{
throw new InvalidOperationException("Database connection string is not configured");
}
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlServer(connectionString);
options.EnableSensitiveDataLogging(builder.Environment.IsDevelopment());
});
// ✅ Register services
builder.Services.AddScoped<IUserService, DatabaseUserService>();
var app = builder.Build();
// ✅ Configure the HTTP request pipeline with error handling
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseDeveloperExceptionPage();
}
else
{
app.UseMiddleware<GlobalExceptionHandlerMiddleware>();
app.UseExceptionHandler("/api/error");
app.UseHsts();
}
// ✅ Ensure database is created with error handling
using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
try
{
context.Database.EnsureCreated();
}
catch (Exception ex)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the database.");
throw;
}
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
catch (Exception ex)
{
var logger = builder.Services.BuildServiceProvider().GetService<ILogger<Program>>();
logger?.LogCritical(ex, "An unhandled exception occurred during startup");
throw;
}
Unit Test Example:
// MyAspNetCoreApp.Tests/UnitTests.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MyAspNetCoreApp.Controllers;
using MyAspNetCoreApp.Middleware;
using MyAspNetCoreApp.Models;
using MyAspNetCoreApp.Services;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MyAspNetCoreApp.Tests
{
[TestClass]
public class ErrorHandlingTests
{
private ServiceProvider _serviceProvider;
private MockUserService _mockUserService;
[TestInitialize]
public void Setup()
{
var services = new ServiceCollection();
services.AddLogging();
_mockUserService = new MockUserService();
services.AddSingleton<IUserService>(_mockUserService);
_serviceProvider = services.BuildServiceProvider();
}
[TestMethod]
public async Task UserController_GetUser_WithValidId_ReturnsUser()
{
// ✅ Arrange
var controller = new UserController(_mockUserService,
_serviceProvider.GetService<ILogger<UserController>>());
var userId = 1;
// ✅ Act
var result = await controller.GetUser(userId);
// ✅ Assert
Assert.IsInstanceOfType(result, typeof(OkObjectResult));
var okResult = (OkObjectResult)result;
Assert.IsNotNull(okResult.Value);
}
[TestMethod]
public async Task UserController_GetUser_WithInvalidId_ReturnsBadRequest()
{
// ✅ Arrange
var controller = new UserController(_mockUserService,
_serviceProvider.GetService<ILogger<UserController>>());
var invalidId = -1;
// ✅ Act
var result = await controller.GetUser(invalidId);
// ✅ Assert
Assert.IsInstanceOfType(result, typeof(BadRequestObjectResult));
}
[TestMethod]
public async Task UserController_GetUser_WithException_ReturnsInternalServerError()
{
// ✅ Arrange
var mockUserService = new MockUserService();
mockUserService.ShouldThrowException = true;
var controller = new UserController(mockUserService,
_serviceProvider.GetService<ILogger<UserController>>());
var userId = 1;
// ✅ Act
var result = await controller.GetUser(userId);
// ✅ Assert
Assert.IsInstanceOfType(result, typeof(ObjectResult));
var objectResult = (ObjectResult)result;
Assert.AreEqual(500, objectResult.StatusCode);
}
[TestMethod]
public async Task GlobalExceptionHandlerMiddleware_HandlesException_Correctly()
{
// ✅ Arrange
var httpContext = new DefaultHttpContext();
var exception = new InvalidOperationException("Test exception");
var logger = _serviceProvider.GetService<ILogger<GlobalExceptionHandlerMiddleware>>();
var middleware = new GlobalExceptionHandlerMiddleware(
async (context) => throw exception, logger);
// ✅ Act
await middleware.InvokeAsync(httpContext);
// ✅ Assert
Assert.AreEqual(500, httpContext.Response.StatusCode);
Assert.AreEqual("application/json", httpContext.Response.ContentType);
}
[TestMethod]
public async Task UserService_CreateUser_WithValidData_CreatesSuccessfully()
{
// ✅ Arrange
var userService = new MockUserService();
var user = new User { Name = "Test User", Email = "test@example.com" };
// ✅ Act
var result = await userService.CreateUserAsync(user);
// ✅ Assert
Assert.IsNotNull(result);
Assert.AreEqual("Test User", result.Name);
Assert.AreEqual("test@example.com", result.Email);
}
[TestMethod]
public async Task UserService_CreateUser_WithInvalidData_ThrowsException()
{
// ✅ Arrange
var userService = new MockUserService();
var invalidUser = new User { Name = "", Email = "" };
// ✅ Act & Assert
await Assert.ThrowsExceptionAsync<ArgumentException>(
async () => await userService.CreateUserAsync(invalidUser));
}
}
// ✅ Mock service for testing
public class MockUserService : IUserService
{
private readonly List<User> _users;
public bool ShouldThrowException { get; set; } = false;
public MockUserService()
{
_users = new List<User>
{
new User { Id = 1, Name = "John Doe", Email = "john@example.com", IsActive = true },
new User { Id = 2, Name = "Jane Smith", Email = "jane@example.com", IsActive = true }
};
}
public async Task<List<User>> GetUsersAsync()
{
if (ShouldThrowException) throw new InvalidOperationException("Test exception");
return await Task.FromResult(_users);
}
public async Task<User> GetUserByIdAsync(int id)
{
if (ShouldThrowException) throw new InvalidOperationException("Test exception");
return await Task.FromResult(_users.Find(u => u.Id == id));
}
public async Task<User> CreateUserAsync(User user)
{
if (ShouldThrowException) throw new InvalidOperationException("Test exception");
if (string.IsNullOrWhiteSpace(user.Name) || string.IsNullOrWhiteSpace(user.Email))
{
throw new ArgumentException("User name and email are required");
}
user.Id = _users.Count > 0 ? _users.Max(u => u.Id) + 1 : 1;
_users.Add(user);
return await Task.FromResult(user);
}
public async Task<User> UpdateUserAsync(int id, User user)
{
if (ShouldThrowException) throw new InvalidOperationException("Test exception");
var existingUser = _users.Find(u => u.Id == id);
if (existingUser != null)
{
existingUser.Name = user.Name;
existingUser.Email = user.Email;
existingUser.IsActive = user.IsActive;
}
return await Task.FromResult(existingUser);
}
public async Task<bool> DeleteUserAsync(int id)
{
if (ShouldThrowException) throw new InvalidOperationException("Test exception");
var user = _users.Find(u => u.Id == id);
if (user != null)
{
_users.Remove(user);
return await Task.FromResult(true);
}
return await Task.FromResult(false);
}
public async Task<User> GetUserByEmailAsync(string email)
{
if (ShouldThrowException) throw new InvalidOperationException("Test exception");
return await Task.FromResult(_users.Find(u =>
u.Email.Equals(email, StringComparison.OrdinalIgnoreCase)));
}
}
}
Best Practices for Error Handling
1. Always Use Try-Catch Blocks for Critical Operations
// ✅ Use try-catch for database operations
public async Task<User> GetUserByIdAsync(int id)
{
try
{
return await _context.Users.FindAsync(id);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error getting user with ID: {UserId}", id);
throw;
}
}
2. Log Errors with Sufficient Context
// ✅ Log with context for debugging
_logger.LogError(
ex,
"Error occurred while processing request for user {UserId} at {Timestamp}",
userId,
DateTime.UtcNow);
3. Use Specific Exception Types
// ✅ Handle specific exception types
catch (DbUpdateException ex)
{
// Handle database-specific errors
throw new InvalidOperationException("Database update failed", ex);
}
catch (ArgumentNullException ex)
{
// Handle argument null errors
throw new ArgumentException("Required parameter is null", ex);
}
4. Implement Global Exception Handling
// ✅ Use middleware for global exception handling
app.UseMiddleware<GlobalExceptionHandlerMiddleware>();
5. Validate Input Parameters
// ✅ Validate input before processing
if (id <= 0)
{
throw new ArgumentException("ID must be positive", nameof(id));
}
6. Use Health Checks for Dependencies
// ✅ Add health checks for database and other dependencies
services.AddHealthChecks()
.AddDbContextCheck<ApplicationDbContext>();
Debugging Steps
Step 1: Enable Detailed Error Pages in Development
// ✅ In development, show detailed errors
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
Step 2: Check Application Logs
// ✅ Look for error entries in application logs
// Check both application logs and system event logs
Step 3: Verify Configuration
// ✅ Check appsettings.json and environment variables
// Verify connection strings and other configuration values
Step 4: Test Database Connectivity
// ✅ Test database connection separately
// Use tools like SQL Server Management Studio to verify connectivity
Step 5: Use Debugging Tools
// ✅ Use Visual Studio debugger or other debugging tools
// Set breakpoints in problematic areas
// Use logging to trace execution flow
Common Mistakes to Avoid
1. Not Handling Exceptions Properly
// ❌ Not handling exceptions
public async Task<User> GetUser(int id)
{
return await _context.Users.FindAsync(id); // ❌ Could throw unhandled exception
}
2. Exposing Sensitive Information
// ❌ Exposing internal details in production
if (!env.IsDevelopment())
{
// ❌ Don't return stack traces to clients in production
return StatusCode(500, new { error = ex.Message, stackTrace = ex.StackTrace });
}
3. Forgetting to Configure Logging
// ❌ Not configuring logging properly
// Make sure logging is configured in both development and production
4. Not Validating Input
// ❌ Not validating input parameters
public async Task<User> UpdateUser(int id, User user)
{
// ❌ Should validate id and user before processing
var existingUser = await _context.Users.FindAsync(id);
// ...
}
5. Improper Service Registration
// ❌ Not registering services properly
// Make sure all required services are registered in the DI container
Performance Considerations
1. Minimize Exception Throwing
// ✅ Use validation to prevent exceptions when possible
if (id <= 0) return null; // Instead of throwing exception
// Rather than:
// if (id <= 0) throw new ArgumentException("Invalid ID");
2. Use Async Methods Properly
// ✅ Use async/await consistently
public async Task<User> GetUserAsync(int id)
{
return await _context.Users.FindAsync(id);
}
3. Implement Caching for Expensive Operations
// ✅ Cache results of expensive operations
public async Task<User> GetUserAsync(int id)
{
var cachedUser = _cache.Get<User>($"user_{id}");
if (cachedUser != null) return cachedUser;
var user = await _context.Users.FindAsync(id);
_cache.Set($"user_{id}", user, TimeSpan.FromMinutes(10));
return user;
}
Security Considerations
1. Don’t Expose Internal Details
// ✅ Don't expose internal exception details in production
public async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
if (context.Request.Host.Value.Contains("localhost"))
{
// ✅ Only show details in development
response.details = new { exception.Message, exception.StackTrace };
}
else
{
// ✅ Generic message in production
response.details = "Internal server error";
}
}
2. Validate All Input
// ✅ Validate all input parameters
public async Task<IActionResult> CreateUser([FromBody] User user)
{
if (user == null || string.IsNullOrWhiteSpace(user.Email))
{
return BadRequest("Invalid user data");
}
// ...
}
3. Use Proper Authentication and Authorization
// ✅ Implement proper security measures
[Authorize]
[ApiController]
public class UserController : ControllerBase
{
// Protected endpoints
}
Testing Error Scenarios
1. Unit Test Exception Handling
[TestMethod]
public async Task GetUser_WithInvalidId_ThrowsArgumentException()
{
var service = new UserService(mockLogger);
await Assert.ThrowsExceptionAsync<ArgumentException>(
async () => await service.GetUserByIdAsync(-1));
}
2. Integration Test Error Scenarios
[TestMethod]
public async Task UserController_GetUser_WithException_Returns500()
{
// Arrange
var mockService = new Mock<IUserService>();
mockService.Setup(s => s.GetUserByIdAsync(It.IsAny<int>()))
.ThrowsAsync(new InvalidOperationException());
var controller = new UserController(mockService.Object, mockLogger);
// Act
var result = await controller.GetUser(1);
// Assert
Assert.IsInstanceOfType(result, typeof(ObjectResult));
Assert.AreEqual(500, ((ObjectResult)result).StatusCode);
}
3. Test Different Error Types
[TestMethod]
public async Task ErrorHandlingMiddleware_HandlesDifferentExceptionTypes()
{
// Test various exception types and ensure proper status codes
// ArgumentException -> 400
// UnauthorizedAccessException -> 401
// General Exception -> 500
}
Alternative Solutions
1. Use Third-Party Error Tracking
// ✅ Example with Serilog and Seq
Log.Logger = new LoggerConfiguration()
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
2. Implement Circuit Breaker Pattern
// ✅ Use Polly for circuit breaker pattern
var retryPolicy = Policy
.Handle<SqlException>()
.Or<TimeoutException>()
.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
3. Use Application Insights
// ✅ Add Application Insights for monitoring
services.AddApplicationInsightsTelemetry();
Migration Checklist
- Implement global exception handling middleware
- Add proper logging configuration
- Update all service methods with try-catch blocks
- Validate input parameters in all endpoints
- Configure error pages for different environments
- Test all error scenarios with unit tests
- Set up monitoring and alerting
- Document error handling procedures
Conclusion
The ‘500 Internal Server Error’ is a common but preventable ASP.NET Core issue that occurs when the server encounters an unexpected condition. By following the solutions provided in this guide—implementing proper exception handling, using global error middleware, configuring appropriate logging, and following best practices—you can effectively prevent and resolve this error in your ASP.NET Core applications.
The key is to understand ASP.NET Core’s error handling mechanisms, implement proper exception handling patterns, use modern C# features like async/await correctly, and maintain clean, well-organized code. With proper error handling, your ASP.NET Core applications will be more robust, maintainable, and provide a better user experience.
Remember to test your changes thoroughly, follow ASP.NET Core best practices for error handling, implement proper logging, and regularly review your error handling code to ensure your applications maintain the best possible architecture and avoid common runtime errors like 500 Internal Server Error.
Related Articles
Fix: CORS Error in ASP.NET Core - Complete Cross-Origin Guide
Learn how to fix CORS errors in ASP.NET Core applications. This comprehensive guide covers CORS configuration, policy setup, and proper cross-origin request handling techniques.
Fix: Cannot consume scoped service from singleton error in C#
Learn how to fix the 'Cannot consume scoped service from singleton' error in C# dependency injection. This comprehensive guide covers service lifetimes, proper registration patterns, and architectural solutions.
How to Fix: No service for type has been registered error in C# - Complete Dependency Injection Guide
Learn how to fix the 'No service for type has been registered' error in C# dependency injection. This comprehensive guide covers DI registration, service lifetimes, and proper configuration techniques.