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:
- Use
StatusCode(msg.HttpStatusCode ?? N, msg.ToJsonObject())for controllers - Use
Results.Json(msg.ToJsonObject(), statusCode: msg.HttpStatusCode ?? N)for Minimal APIs - Use
.Log(_logger)before returning — chain logging - Use
.WithData()for payloads — return data to clients - 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:
- Don’t use
.ToJson()in controllers — use.ToJsonObject()withStatusCode()instead - Don’t hardcode HTTP status codes — trust
msg.HttpStatusCodefrom the message - Don’t skip logging errors — always log failures
- Don’t include sensitive data in metadata — security risk
- 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:
- Setup and Configuration - Complete setup guide
- Configuration Presets - Environment presets
- API Response Patterns - Response patterns
- Logging Integration - Logging strategies
Questions? Ask in Discussions