Real-World Scenarios

This guide demonstrates how Dumpify fits into practical development workflows and solves common debugging challenges.

Table of Contents

Debugging API Responses

Inspecting HTTP Client Responses

public async Task<User> GetUserAsync(int userId)
{
    var response = await _httpClient.GetAsync($"/api/users/{userId}");
    response.Dump("HTTP Response");
    
    var content = await response.Content.ReadAsStringAsync();
    content.Dump("Raw JSON");
    
    var user = JsonSerializer.Deserialize<User>(content);
    user.Dump("Deserialized User");
    
    return user;
}

Debugging Minimal API Endpoints

app.MapGet("/api/orders/{id}", async (int id, OrderService service) =>
{
    var order = await service.GetOrderAsync(id);
    order.Dump($"Order {id}"); // Debug output
    
    return order is null 
        ? Results.NotFound() 
        : Results.Ok(order);
});

Examining Request Data

app.MapPost("/api/orders", async (CreateOrderRequest request, OrderService service) =>
{
    request.Dump("Incoming Order Request");
    
    var validationResult = ValidateRequest(request);
    validationResult.Dump("Validation Result");
    
    if (!validationResult.IsValid)
    {
        return Results.BadRequest(validationResult.Errors);
    }
    
    var order = await service.CreateOrderAsync(request);
    order.Dump("Created Order");
    
    return Results.Created($"/api/orders/{order.Id}", order);
});

Entity Framework Debugging

Inspecting Query Results

public async Task<List<Order>> GetOrdersWithDetailsAsync(int customerId)
{
    var orders = await _context.Orders
        .Where(o => o.CustomerId == customerId)
        .Include(o => o.OrderItems)
            .ThenInclude(oi => oi.Product)
        .ToListAsync();
    
    orders.Dump("Orders with Details");
    
    return orders;
}

Debugging Navigation Properties

// Check what's loaded vs. null
var customer = await _context.Customers
    .Include(c => c.Address)
    .FirstOrDefaultAsync(c => c.Id == customerId);

customer.Dump(config => config
    .SetMaxDepth(3)
    .UseMembersConfig(m => m.IncludeNonPublicMembers(false)));

Tracking Entity State

public async Task UpdateOrderAsync(Order order)
{
    _context.Entry(order).State.Dump("Entity State Before");
    
    _context.Orders.Update(order);
    
    var changes = _context.ChangeTracker.Entries()
        .Where(e => e.State != EntityState.Unchanged)
        .Select(e => new 
        { 
            Entity = e.Entity.GetType().Name, 
            State = e.State,
            Original = e.OriginalValues.ToObject(),
            Current = e.CurrentValues.ToObject()
        })
        .ToList();
    
    changes.Dump("Pending Changes");
    
    await _context.SaveChangesAsync();
}

Hiding Sensitive EF Properties

// Filter out EF Core internal properties
var config = new DumpConfig
{
    MembersConfig = new MembersConfig
    {
        MemberFilter = member => 
            !member.Name.StartsWith("__") &&
            member.Name != "LazyLoader"
    }
};

dbEntity.Dump(config);

Logging and Diagnostics

Structured Logging Integration

public class OrderProcessor
{
    private readonly ILogger<OrderProcessor> _logger;
    
    public async Task ProcessOrderAsync(Order order)
    {
        // Get string representation for logging
        var orderDump = order.DumpText();
        _logger.LogInformation("Processing order: {OrderDetails}", orderDump);
        
        try
        {
            await ProcessInternalAsync(order);
            _logger.LogInformation("Order {OrderId} processed successfully", order.Id);
        }
        catch (Exception ex)
        {
            var context = new { Order = order, Timestamp = DateTime.UtcNow };
            _logger.LogError(ex, "Failed to process order: {Context}", 
                context.DumpText());
            throw;
        }
    }
}

Debug vs Release Output

public class DiagnosticService
{
    [Conditional("DEBUG")]
    public void DumpState<T>(T obj, string label)
    {
        obj.Dump(label);
    }
    
    public void ProcessWithDiagnostics(Request request)
    {
        DumpState(request, "Input Request");
        
        var result = Process(request);
        
        DumpState(result, "Processing Result");
    }
}

Application Startup Diagnostics

var builder = WebApplication.CreateBuilder(args);

// Dump configuration during startup
#if DEBUG
builder.Configuration.AsEnumerable()
    .Where(kvp => !kvp.Key.Contains("Password", StringComparison.OrdinalIgnoreCase))
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
    .Dump("Application Configuration");
#endif

var app = builder.Build();

Unit Test Debugging

Test Assertion Debugging

[Fact]
public void ProcessOrder_ShouldCalculateTotal_Correctly()
{
    // Arrange
    var order = new Order
    {
        Items = new List<OrderItem>
        {
            new() { ProductId = 1, Quantity = 2, UnitPrice = 10.00m },
            new() { ProductId = 2, Quantity = 1, UnitPrice = 25.00m }
        }
    };
    order.Dump("Test Input");
    
    // Act
    var processor = new OrderProcessor();
    var result = processor.CalculateTotal(order);
    result.Dump("Calculated Result");
    
    // Assert
    Assert.Equal(45.00m, result.Total);
}

Debugging Collection Assertions

[Fact]
public void GetActiveUsers_ShouldFilterCorrectly()
{
    // Arrange
    var users = GetTestUsers();
    users.Dump("All Users");
    
    // Act
    var activeUsers = _service.GetActiveUsers(users);
    activeUsers.Dump("Active Users");
    
    // Debug: Show which ones were filtered
    var filteredOut = users.Except(activeUsers);
    filteredOut.Dump("Filtered Out Users");
    
    // Assert
    Assert.All(activeUsers, u => Assert.True(u.IsActive));
}

Debugging Test Data

[Theory]
[MemberData(nameof(GetTestCases))]
public void Calculator_Add_ReturnsExpectedResult(int a, int b, int expected)
{
    var testCase = new { a, b, expected };
    testCase.Dump($"Test Case: {a} + {b}");
    
    var result = Calculator.Add(a, b);
    result.Dump("Result");
    
    Assert.Equal(expected, result);
}

Console Application Development

Interactive Menu Display

class Program
{
    static async Task Main(string[] args)
    {
        while (true)
        {
            Console.Clear();
            ShowMenu();
            
            var choice = Console.ReadLine();
            
            switch (choice)
            {
                case "1":
                    var users = await GetUsersAsync();
                    users.Dump("All Users");
                    break;
                    
                case "2":
                    Console.Write("Enter user ID: ");
                    var id = int.Parse(Console.ReadLine()!);
                    var user = await GetUserAsync(id);
                    user.Dump($"User #{id}");
                    break;
                    
                case "3":
                    var stats = await GetStatisticsAsync();
                    stats.Dump("System Statistics");
                    break;
                    
                case "q":
                    return;
            }
            
            Console.WriteLine("\nPress any key to continue...");
            Console.ReadKey();
        }
    }
}

CLI Tool Development

// dotnet run -- analyze --path ./data
var rootCommand = new RootCommand("Data Analysis Tool");

var analyzeCommand = new Command("analyze", "Analyze data files");
var pathOption = new Option<string>("--path", "Path to data directory");
analyzeCommand.AddOption(pathOption);

analyzeCommand.SetHandler(async (string path) =>
{
    Console.WriteLine($"Analyzing: {path}");
    
    var results = await AnalyzeDataAsync(path);
    
    results.Summary.Dump("Analysis Summary");
    results.Issues.Dump("Found Issues");
    results.Recommendations.Dump("Recommendations");
    
}, pathOption);

rootCommand.AddCommand(analyzeCommand);
await rootCommand.InvokeAsync(args);

Configuration Inspection

Options Pattern Debugging

services.Configure<MyOptions>(configuration.GetSection("MyOptions"));

services.AddSingleton(sp =>
{
    var options = sp.GetRequiredService<IOptions<MyOptions>>().Value;
    options.Dump("Loaded MyOptions");
    return options;
});

Feature Flag Inspection

public class FeatureFlagService
{
    private readonly IFeatureManager _featureManager;
    
    public async Task DumpFeatureFlagsAsync()
    {
        var flags = new Dictionary<string, bool>();
        
        await foreach (var name in _featureManager.GetFeatureNamesAsync())
        {
            flags[name] = await _featureManager.IsEnabledAsync(name);
        }
        
        flags.Dump("Feature Flags");
    }
}

Data Transformation Pipelines

ETL Pipeline Debugging

public async Task<ProcessingResult> ProcessDataAsync(DataSource source)
{
    // Extract
    var rawData = await ExtractAsync(source);
    rawData.Take(5).Dump("Extracted (sample)");
    
    // Transform
    var transformed = Transform(rawData);
    transformed.Take(5).Dump("Transformed (sample)");
    
    // Validate
    var (valid, invalid) = Partition(transformed, IsValid);
    valid.Count().Dump("Valid Records");
    invalid.Take(3).Dump("Invalid Records (sample)");
    
    // Load
    var result = await LoadAsync(valid);
    result.Dump("Load Result");
    
    return result;
}

LINQ Pipeline Debugging

var result = orders
    .Dump("1. All Orders")
    .Where(o => o.Status == OrderStatus.Completed)
    .Dump("2. Completed Orders")
    .GroupBy(o => o.CustomerId)
    .Dump("3. Grouped by Customer")
    .Select(g => new 
    { 
        CustomerId = g.Key, 
        TotalOrders = g.Count(),
        TotalValue = g.Sum(o => o.Total)
    })
    .Dump("4. Customer Summaries")
    .OrderByDescending(x => x.TotalValue)
    .Dump("5. Sorted by Value")
    .Take(10)
    .Dump("6. Top 10 Customers")
    .ToList();

Error Investigation

Exception Context Capture

public async Task<Result> ProcessAsync(Request request)
{
    try
    {
        return await ProcessInternalAsync(request);
    }
    catch (Exception ex)
    {
        var errorContext = new
        {
            Request = request,
            Timestamp = DateTime.UtcNow,
            Exception = new
            {
                ex.Message,
                ex.StackTrace,
                InnerMessage = ex.InnerException?.Message
            },
            Environment = new
            {
                MachineName = Environment.MachineName,
                OSVersion = Environment.OSVersion.ToString(),
                ProcessId = Environment.ProcessId
            }
        };
        
        errorContext.Dump("Error Context");
        
        // Log for production
        var contextText = errorContext.DumpText();
        _logger.LogError(ex, "Processing failed: {Context}", contextText);
        
        throw;
    }
}

State Comparison

public void InvestigateBug()
{
    var expected = LoadExpectedState();
    var actual = LoadActualState();
    
    expected.Dump("Expected State");
    actual.Dump("Actual State");
    
    // Find differences
    var differences = CompareStates(expected, actual);
    differences.Dump("State Differences");
}

Memory/Performance Debugging

public void AnalyzePerformance()
{
    var metrics = new
    {
        TotalMemory = GC.GetTotalMemory(false),
        Gen0Collections = GC.CollectionCount(0),
        Gen1Collections = GC.CollectionCount(1),
        Gen2Collections = GC.CollectionCount(2),
        ThreadCount = Process.GetCurrentProcess().Threads.Count,
        HandleCount = Process.GetCurrentProcess().HandleCount,
        WorkingSet = Process.GetCurrentProcess().WorkingSet64
    };
    
    metrics.Dump("Performance Metrics");
}

See Also