Skip to content

Configuration Error Handling

quyvu edited this page Oct 13, 2026 · 2 revisions

Error Handling

Configure how FxMap handles exceptions and errors during data mapping and request processing.

ThrowIfException Configuration

The ThrowIfException method controls whether FxMap throws exceptions when errors o

builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
 
    // Enable exception throwing (recommended for development)
    cfg.ThrowIfException();
});

Default Behavior vs ThrowIfException

Default Behavior

When ThrowIfException is NOT configured:

  • •Exceptions are caught and swallowed silently
  • •Properties that fail to map remain as their default values
  • •No error feedback is provided
  • •Application continues running

With ThrowIfException

When ThrowIfException IS configured:

  • Exceptions are thrown immediately when errors occur
  • Clear error messages help identify issues quickly
  • Easier debugging during development
  • Fail-fast behavior for better reliability

Common Errors FxMap Can Detect

When ThrowIfException is enabled, FxMap will throw exceptions for these common issues:

Missing Entity Config Registration

When an EntityConfigureOf class is used but not registered via AddEntitiesFromAssemblyContaining.

// Error: Distributed key 'UserDistributedKey' has no registered entity config
// Fix: cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();

Missing Entity Configuration

When a model has no EntityConfigureOf class defining its distributed key mapping.

// Error: No EntityConfigureOf found for 'User' with key 'UserDistributedKey'
// Fix: Create a class that extends EntityConfigureOf<User> and calls UseDistributedKey<UserDistributedKey>()

Invalid Expression Syntax

When an expression uses invalid syntax or references non-existent properties.

// Error: Property 'NonExistentField' not found on type 'User'
// Fix: Use a valid property name like 'Email'

Type Conversion Errors

When trying to convert incompatible types or missing strongly typed ID converters.

// Error: Cannot convert string to UserId
// Fix: Register a strongly typed ID converter

Data Provider Errors

Database connection issues, query failures, or data access errors.

// Error: Unable to connect to database
// Error: Invalid SQL query generated

Expressions the owner cannot build

An expression with an unknown function, a syntax error or an unknown property fails on the owner. By default that fails the whole request. When the owner turns on IsolateExpressionErrors() in its data provider (EF Core or MongoDB, 4.1.3+), it answers the other expressions and reports the broken ones, and you decide here:

  • With ThrowIfException(): FxMap throws a DistributedMapException.ExpressionsFailed that holds all the errors (Errors, and all the messages in Message).
  • Without it: FxMap writes a warning in the log for each error, leaves the properties of these expressions alone, and maps the others.

When to Use ThrowIfException

Enable During

  • Development: Immediate feedback on configuration errors
  • Testing: Catch bugs early in automated tests
  • Debugging: Troubleshooting mapping issues
  • Staging: Validate configuration before production

Consider Disabling For

  • Production: When you want graceful degradation
  • Partial data scenarios: When some failures are acceptable
  • High availability systems: Where uptime is critical

Environment-Based Configuration

A common pattern is to enable ThrowIfException in development and disable it in production:

var builder = WebApplication.CreateBuilder(args);
 
builder.Services.AddFxMap(cfg =>
{
    cfg.AddEntitiesFromAssemblyContaining<SomeEntityAssemblyMarker>();
    cfg.AddProfilesFromAssemblyContaining<SomeProfileAssemblyMarker>();
 
    // Enable exception throwing in development only
    if (builder.Environment.IsDevelopment())
    {
        cfg.ThrowIfException();
    }
});

Custom Error Handling

Even without ThrowIfException, you can implement custom error handling in your application:

public class OrderService
{
    private readonly IDistributedMapper _mapper;
    private readonly ILogger<OrderService> _logger;
 
    public OrderService(IDistributedMapper mapper, ILogger<OrderService> logger)
    {
        _mapper = mapper;
        _logger = logger;
    }
 
    public async Task<OrderResponse> GetOrderAsync(string orderId)
    {
        var response = new OrderResponse { Id = orderId };
 
        try
        {
            await _mapper.MapDataAsync(response);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to map data for order {OrderId}", orderId);
 
            // Decide how to handle the error:
            // 1. Rethrow the exception
            throw;
 
            // 2. Return partial data
            // return response;
 
            // 3. Return default/empty response
            // return new OrderResponse { Id = orderId };
        }
 
        return response;
    }
}

Logging Errors

FxMap integrates with ASP.NET Core logging. Even when exceptions are swallowed, they can be logged:

// Configure logging in appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "FxMap": "Warning",  // Log FxMap warnings and errors
      "FxMap.Core": "Debug"  // Detailed FxMap debugging
    }
  }
}

Best Practices

  • Always use ThrowIfException during development and testing
  • Consider environment-based configuration for production
  • Implement comprehensive logging regardless of ThrowIfException setting
  • Use try-catch blocks for critical operations
  • Test error scenarios explicitly in your test suite

Important Notes

  • ThrowIfException only affects FxMap-related errors, not application-level exceptions
  • Silent failures can make debugging difficult in production
  • Monitor logs even when exceptions are not thrown

Source: https://fxmapper.net/docs/configuration/error-handling/ — the website is always the most up to date version.

Clone this wiki locally