LambdaLuke Help

Add Error Logging

.NET has built-in structured logging via the ILogger interface

Add Global Error Handling

If you want centralized error handling, you can use middleware

This will log any unhandled exception, and return a generic 500 error to the client

In Program.cs, add before app.Run()

app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { var logger = context.RequestServices.GetRequiredService<ILogger<Program>>(); var exception = context.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature>()?.Error; logger.LogError(exception, "Unhandled exception occurred"); context.Response.StatusCode = 500; await context.Response.WriteAsJsonAsync(new { error = "An unexpected error occurred." }); }); });

Save Logs to a File

Serilog is a powerful structured logging library that allows us to create structured logs and save them to a file

First, we need to install some required Nuget packages

Serilog.AspNetCore
Serilog.Sinks.Console
Serilog.Sinks.File

Update Program.cs to use Serilog. Add the following to the beginning of the file

Log.Logger = new LoggerConfiguration() .WriteTo.Console() .WriteTo.File("Logs/log.txt", rollingInterval: RollingInterval.Day) .Enrich.FromLogContext() .CreateLogger();

Add the following to the builder

builder.Host.UseSerilog();

Then finally, add this to the very end of the file

Log.CloseAndFlush();

This line ensures that if the application crashes, the error will still be logged to the log file

The completed Program.cs file should look like this

using CrudAppAPI.Data; using CrudAppAPI.Endpoints; using CrudAppAPI.Services; using Serilog; Log.Logger = new LoggerConfiguration() .WriteTo.Console() .WriteTo.File("Logs/log.txt", rollingInterval: RollingInterval.Day) .Enrich.FromLogContext() .CreateLogger(); var builder = WebApplication.CreateBuilder(args); builder.Host.UseSerilog(); builder.Services.AddOpenApi(); builder.Services.AddScoped<TaskService>(); builder.Services.AddScoped<IDbConnectionFactory, SqlConnectionFactory>(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.MapOpenApi(); } app.UseHttpsRedirection(); app.MapTaskEndpoints(); app.UseExceptionHandler(errorApp => { errorApp.Run(async context => { var logger = context.RequestServices.GetRequiredService<ILogger<Program>>(); var exception = context.Features.Get<Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature>()?.Error; logger.LogError(exception, "Unhandled exception occurred"); context.Response.StatusCode = 500; await context.Response.WriteAsJsonAsync(new { error = "An unexpected error occurred." }); }); }); app.Run(); Log.CloseAndFlush();

Add validation results to Logs

app.MapPost("/api/tasks", async ( CreateTaskDto dto, TaskService service, IValidator<CreateTaskDto> validator, ILogger<Program> logger) => { var validationResult = await validator.ValidateAsync(dto); if (!validationResult.IsValid) { logger.LogWarning("Validation failed for CreateTaskDto: {@Errors}", validationResult.Errors); return Results.BadRequest(validationResult.Errors); } await service.AddTaskAsync(dto); return Results.Ok(); });
10 July 2025