Setup and Configuration

Complete guide to setting up and configuring EasyMessages in ASP.NET Core applications.


Table of Contents

  1. Installation
  2. Basic Setup
  3. Configuration Methods
  4. Configuration Options
  5. Environment-Specific Configuration
  6. Advanced Setup
  7. Troubleshooting

Installation

Package Installation

Install the package via NuGet:

# .NET CLI
dotnet add package RecurPixel.EasyMessages --version 1.0.0

# Package Manager Console
Install-Package RecurPixel.EasyMessages -Version 1.0.0

No DI registration is required — the package works without any AddEasyMessages() call.


Project File Reference

Your .csproj file should include:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="RecurPixel.EasyMessages" Version="1.0.0" />
  </ItemGroup>
</Project>

Supported .NET Versions: .NET 5.0 - 10.0


Basic Setup

Minimal Setup

Program.cs:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();
app.Run();

No additional registration is needed. Import RecurPixel.EasyMessages in your controllers and use the Msg facades directly.


Controller Usage

UsersController.cs:

using Microsoft.AspNetCore.Mvc;
using RecurPixel.EasyMessages;

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly ILogger<UsersController> _logger;

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

    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        var user = _userRepository.FindById(id);

        if (user == null)
        {
            var notFound = Msg.Crud.NotFound("User")
                .WithMetadata("userId", id)
                .Log(_logger);
            return StatusCode(notFound.HttpStatusCode ?? 404, notFound.ToJsonObject());
        }

        var ok = Msg.Crud.Retrieved("User").WithData(user);
        return StatusCode(ok.HttpStatusCode ?? 200, ok.ToJsonObject());
    }
}

Minimal API Usage

Program.cs:

using RecurPixel.EasyMessages;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/api/users/{id}", (int id, ILogger<Program> logger) =>
{
    var user = userRepository.FindById(id);

    if (user == null)
    {
        var notFound = Msg.Crud.NotFound("User").WithMetadata("userId", id).Log(logger);
        return Results.Json(notFound.ToJsonObject(), statusCode: notFound.HttpStatusCode ?? 404);
    }

    var ok = Msg.Crud.Retrieved("User").WithData(user);
    return Results.Json(ok.ToJsonObject(), statusCode: ok.HttpStatusCode ?? 200);
});

app.Run();

Configuration Methods

EasyMessages formatter behavior can be configured at startup or inline:

1. appsettings.json (Custom Messages Storage)

Use appsettings to configure the custom messages file path:

appsettings.json:

{
  "EasyMessages": {
    "Storage": {
      "CustomMessagesPath": "messages/custom.json"
    }
  }
}

Load it at startup:

Program.cs:

var customPath = builder.Configuration["EasyMessages:Storage:CustomMessagesPath"];
if (!string.IsNullOrEmpty(customPath))
{
    MessageRegistry.LoadCustomMessages(customPath);
}

2. FormatterConfiguration

Configure formatter options globally using FormatterConfiguration.Configure():

Program.cs:

using RecurPixel.EasyMessages.Configuration;

FormatterConfiguration.Configure(options =>
{
    options.IncludeTimestamp = true;
    options.IncludeMetadata = true;
    options.IncludeNullFields = false;
});

3. Inline per Message

Override options inline per-call:

var json = Msg.Crud.Created("User")
    .WithData(user)
    .ToJson(options => options.IncludeTimestamp = false);

Configuration Options

FormatterOptions

Controls which fields are included in formatted output (JSON, XML, etc.).

public class FormatterOptions
{
    public bool IncludeTimestamp { get; set; } = true;
    public bool IncludeCorrelationId { get; set; } = true;
    public bool IncludeHttpStatusCode { get; set; } = true;
    public bool IncludeMetadata { get; set; } = true;
    public bool IncludeData { get; set; } = true;
    public bool IncludeParameters { get; set; } = true;
    public bool IncludeHint { get; set; } = true;
    public bool IncludeNullFields { get; set; } = false;
}

Use Cases:

  • Production: Minimal fields (performance)
  • Development: All fields (debugging)
  • API Clients: Essential fields only
  • Logging: Verbose fields

Environment-Specific Configuration

Development Environment

Program.cs:

if (builder.Environment.IsDevelopment())
{
    FormatterConfiguration.Configure(options =>
    {
        options.IncludeTimestamp = true;
        options.IncludeMetadata = true;
        options.IncludeNullFields = true;
    });
}

Production Environment

Program.cs:

if (builder.Environment.IsProduction())
{
    FormatterConfiguration.Configure(options =>
    {
        options.IncludeTimestamp = false;
        options.IncludeMetadata = false;
        options.IncludeNullFields = false;
    });
}

Using Environment Variables

You can also configure via environment variables (loaded by ASP.NET Core automatically):

EasyMessages__Storage__CustomMessagesPath=messages/custom.json

Then in Program.cs:

var customPath = builder.Configuration["EasyMessages:Storage:CustomMessagesPath"];
if (!string.IsNullOrEmpty(customPath))
{
    MessageRegistry.LoadCustomMessages(customPath);
}

Advanced Setup

Custom Messages

Load custom messages from a JSON file:

MessageRegistry.LoadCustomMessages("messages/custom.json");

Custom Message File Format:

{
  "CUSTOM_001": {
    "type": "Success",
    "title": "Payment Successful",
    "description": "Payment of ${amount} was processed successfully.",
    "httpStatusCode": 200
  },
  "CUSTOM_002": {
    "type": "Error",
    "title": "Payment Failed",
    "description": "Payment failed: {reason}",
    "httpStatusCode": 402
  }
}

Usage:

var msg = Msg.Custom("CUSTOM_001").WithParams(new { amount = "$50.00" });
return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());

Custom Interceptors

Register custom interceptors programmatically:

MessageRegistry.AddInterceptor(new AuditLoggingInterceptor());
MessageRegistry.AddInterceptor(new PerformanceTrackingInterceptor());

Troubleshooting

Issue: Custom Messages Not Loading

Symptoms: Custom message codes not found at runtime

Solution:

var path = "messages/custom.json";
var fullPath = Path.GetFullPath(path);
Console.WriteLine($"Loading messages from: {fullPath}");
Console.WriteLine($"File exists: {File.Exists(fullPath)}");

MessageRegistry.LoadCustomMessages(path);

var codes = MessageRegistry.GetAllCodes();
Console.WriteLine($"Loaded message codes: {string.Join(", ", codes)}");

Issue: HttpStatusCode is null

Symptoms: msg.HttpStatusCode returns null

Solution: Use a fallback value:

return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());

Issue: Log messages not appearing

Symptoms: .Log(_logger) calls produce no output

Causes:

  1. Logger category filtered by log level
  2. Message type below minimum log level

Solution:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

Next Steps


Questions? Ask in Discussions