ASP.NET Core Integration Overview

RecurPixel.EasyMessages works seamlessly with ASP.NET Core web APIs out of the box — no separate package needed.

Table of contents

Single Package for Everything

In v1.0.0, RecurPixel.EasyMessages is a single unified package that works for console apps, background workers, and ASP.NET Core web APIs. There is no separate RecurPixel.EasyMessages.AspNetCore package.

Web-Specific Features

Feature Description Benefit
.ToJsonObject() Returns a serializable response object Use with StatusCode() for REST API responses
.Log(ILogger) Logs the message via Microsoft.Extensions.Logging Integrated observability
.WithData() Attach data payloads Return data to clients
.WithMetadata() Attach key/value metadata Additional context
HTTP status codes Each message has a mapped status code Consistent API contracts

Package Comparison

RecurPixel.EasyMessages — single package for all scenarios

For: Console apps, background workers, desktop apps, class libraries, and ASP.NET Core web APIs

// Console output
Msg.Auth.LoginFailed().ToConsole(useColors: true);

// JSON string
var json = Msg.Crud.Created("User").ToJson();

// API response (controllers)
var msg = Msg.Crud.NotFound("User").WithMetadata("id", id);
return StatusCode(msg.HttpStatusCode ?? 404, msg.ToJsonObject());

// Logging
Msg.System.Error().WithMetadata("error", ex.Message).Log(_logger);

Features:

  • [✓] Message creation (Msg.Auth, Msg.Crud, etc.)
  • [✓] Formatters (JSON, XML, Console, PlainText)
  • [✓] Message stores (File, Embedded, etc.)
  • [✓] Interceptors (custom cross-cutting concerns)
  • [✓] Extension methods (WithData, WithMetadata, WithCorrelationId, etc.)
  • [✓] .Log(ILogger) — integrated logging
  • [✓] .ToJsonObject() — serializable object for API responses

Quick Start

Installation

dotnet add package RecurPixel.EasyMessages --version 1.0.0

No DI registration is required. No AddEasyMessages() call needed.


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());
    }

    [HttpPost]
    public IActionResult Create(CreateUserDto dto)
    {
        var user = _userRepository.Create(dto);

        var created = Msg.Crud.Created("User")
            .WithData(user)
            .Log(_logger);
        return StatusCode(created.HttpStatusCode ?? 200, created.ToJsonObject());
    }

    [HttpPut("{id}")]
    public IActionResult Update(int id, UpdateUserDto dto)
    {
        var user = _userRepository.Update(id, dto);

        var updated = Msg.Crud.Updated("User")
            .WithData(user)
            .Log(_logger);
        return StatusCode(updated.HttpStatusCode ?? 200, updated.ToJsonObject());
    }

    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        _userRepository.Delete(id);

        var deleted = Msg.Crud.Deleted("User").Log(_logger);
        return StatusCode(deleted.HttpStatusCode ?? 200, deleted.ToJsonObject());
    }
}

Minimal API Usage

Program.cs:

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

var users = app.MapGroup("/api/users");

users.MapGet("/{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);
});

users.MapPost("/", (CreateUserDto dto, ILogger<Program> logger) =>
{
    var user = userRepository.Create(dto);

    var created = Msg.Crud.Created("User")
        .WithData(user)
        .Log(logger);
    return Results.Json(created.ToJsonObject(), statusCode: created.HttpStatusCode ?? 200);
});

app.Run();

API Response Format

All messages converted via .ToJsonObject() use a standardized JSON format:

Success Response

Code:

var msg = Msg.Crud.Created("User")
    .WithData(new { Id = 123, Name = "John Doe" });
return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());

HTTP Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "success": true,
  "code": "CRUD_001",
  "type": "success",
  "title": "User Created",
  "description": "User has been created successfully.",
  "data": {
    "id": 123,
    "name": "John Doe"
  },
  "timestamp": "2026-01-09T14:30:00.000Z",
  "metadata": null
}

Error Response

Code:

var msg = Msg.Crud.NotFound("User")
    .WithMetadata("userId", 999);
return StatusCode(msg.HttpStatusCode ?? 404, msg.ToJsonObject());

HTTP Response:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "success": false,
  "code": "CRUD_004",
  "type": "error",
  "title": "User Not Found",
  "description": "The requested User could not be found.",
  "data": null,
  "timestamp": "2026-01-09T14:30:00.000Z",
  "metadata": {
    "userId": 999
  }
}

Validation Error Response

Code:

var msg = Msg.Validation.Failed()
    .WithData(new
    {
        errors = new Dictionary<string, string[]>
        {
            ["Email"] = new[] { "Invalid email format" },
            ["Password"] = new[] { "Password too weak" }
        }
    });
return StatusCode(msg.HttpStatusCode ?? 422, msg.ToJsonObject());

HTTP Response:

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "success": false,
  "code": "VAL_001",
  "type": "error",
  "title": "Validation Failed",
  "description": "One or more validation errors occurred.",
  "data": {
    "errors": {
      "Email": ["Invalid email format"],
      "Password": ["Password too weak"]
    }
  },
  "timestamp": "2026-01-09T14:30:00.000Z",
  "metadata": null
}

Logging Integration

Manual Logging

public IActionResult Create(CreateUserDto dto)
{
    var user = _userRepository.Create(dto);

    var msg = Msg.Crud.Created("User")
        .WithData(user)
        .Log(_logger); // ← Manually log before returning
    return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());
}

Log Levels by Message Type

Message Type Log Level
Success Information
Info Information
Warning Warning
Error Error
Critical Critical

HTTP Status Code Mapping

Messages automatically have appropriate HTTP status codes:

Message HTTP Status
Msg.Crud.Created() 200 OK
Msg.Crud.Retrieved() 200 OK
Msg.Crud.Updated() 200 OK
Msg.Crud.Deleted() 200 OK
Msg.Crud.NotFound() 404 Not Found
Msg.Auth.LoginFailed() 401 Unauthorized
Msg.Auth.Unauthorized() 403 Forbidden
Msg.Validation.Failed() 422 Unprocessable Entity
Msg.System.Error() 500 Internal Server Error
Msg.Database.ConnectionFailed() 503 Service Unavailable

Override if needed:

var msg = Msg.Crud.Created("User")
    .WithStatusCode(201); // ← Override to 201 Created
return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());

Common Patterns

REST API CRUD

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

[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    public IActionResult GetAll()
    {
        var msg = Msg.Crud.Retrieved("Products").WithData(_repo.GetAll());
        return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());
    }

    [HttpGet("{id}")]
    public IActionResult GetById(int id)
    {
        var product = _repo.FindById(id);
        if (product != null)
        {
            var ok = Msg.Crud.Retrieved("Product").WithData(product);
            return StatusCode(ok.HttpStatusCode ?? 200, ok.ToJsonObject());
        }
        var notFound = Msg.Crud.NotFound("Product").WithMetadata("id", id);
        return StatusCode(notFound.HttpStatusCode ?? 404, notFound.ToJsonObject());
    }

    [HttpPost]
    public IActionResult Create(CreateProductDto dto)
    {
        var msg = Msg.Crud.Created("Product").WithData(_repo.Create(dto));
        return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());
    }

    [HttpPut("{id}")]
    public IActionResult Update(int id, UpdateProductDto dto)
    {
        var msg = Msg.Crud.Updated("Product").WithData(_repo.Update(id, dto));
        return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());
    }

    [HttpDelete("{id}")]
    public IActionResult Delete(int id)
    {
        _repo.Delete(id);
        var msg = Msg.Crud.Deleted("Product");
        return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());
    }
}

Validation Results

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

[HttpPost]
public IActionResult Create(CreateUserDto dto)
{
    var validationResult = _validator.Validate(dto);

    if (!validationResult.IsValid)
    {
        var err = Msg.Validation.Failed()
            .WithData(new
            {
                errors = validationResult.Errors
                    .GroupBy(e => e.PropertyName)
                    .ToDictionary(
                        g => g.Key,
                        g => g.Select(e => e.ErrorMessage).ToArray()
                    )
            });
        return StatusCode(err.HttpStatusCode ?? 422, err.ToJsonObject()); // Returns 422 Unprocessable Entity
    }

    // ... create user
}

Error Handling

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

[HttpGet("{id}")]
public IActionResult GetById(int id)
{
    try
    {
        var user = _repo.FindById(id);
        if (user != null)
        {
            var ok = Msg.Crud.Retrieved("User").WithData(user);
            return StatusCode(ok.HttpStatusCode ?? 200, ok.ToJsonObject());
        }
        var notFound = Msg.Crud.NotFound("User").WithMetadata("id", id);
        return StatusCode(notFound.HttpStatusCode ?? 404, notFound.ToJsonObject());
    }
    catch (DbException ex)
    {
        var err = Msg.Database.TransactionFailed()
            .WithMetadata("error", ex.Message)
            .Log(_logger);
        return StatusCode(err.HttpStatusCode ?? 500, err.ToJsonObject()); // Returns 500 Internal Server Error
    }
}

Best Practices

[✓] DO:

  1. Use StatusCode(msg.HttpStatusCode ?? N, msg.ToJsonObject()) for controllers
  2. Use Results.Json(msg.ToJsonObject(), statusCode: msg.HttpStatusCode ?? N) for Minimal APIs
  3. Use .Log(_logger) before returning — chain logging
  4. Use .WithData() for payloads — return data to clients
  5. Use .WithMetadata() for debugging — additional context
// Good
var msg = Msg.Crud.Created("User")
    .WithData(user)
    .WithMetadata("source", "WebAPI")
    .Log(_logger);
return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject());

[ ] DON’T:

  1. Don’t use .ToJson() in controllers — use .ToJsonObject() with StatusCode() instead
  2. Don’t hardcode HTTP status codes — trust msg.HttpStatusCode from the message
  3. Don’t skip logging errors — always log failures
  4. Don’t include sensitive data in metadata — security risk
  5. Don’t use console formatters in APIs — wrong output format
// Bad
return Ok(Msg.Crud.Created("User").ToJson()); // Wrong!

// Good
var msg = Msg.Crud.Created("User").WithData(user);
return StatusCode(msg.HttpStatusCode ?? 200, msg.ToJsonObject()); // Correct

Next Steps

Explore the ASP.NET Core integration in depth:


Questions? Ask in Discussions