Nera.Lib.Core
1.0.20
dotnet add package Nera.Lib.Core --version 1.0.20
NuGet\Install-Package Nera.Lib.Core -Version 1.0.20
<PackageReference Include="Nera.Lib.Core" Version="1.0.20" />
<PackageVersion Include="Nera.Lib.Core" Version="1.0.20" />
<PackageReference Include="Nera.Lib.Core" />
paket add Nera.Lib.Core --version 1.0.20
#r "nuget: Nera.Lib.Core, 1.0.20"
#:package Nera.Lib.Core@1.0.20
#addin nuget:?package=Nera.Lib.Core&version=1.0.20
#tool nuget:?package=Nera.Lib.Core&version=1.0.20
Nera.Lib.Core
A comprehensive .NET 9 library providing core utilities, extensions, validation, CQRS patterns, logging, and common components for Nera applications.
๐ฆ Installation
dotnet add package Nera.Lib.Core
๐ Quick Start
using Nera.Lib.Core.Builders;
using Nera.Lib.Core.Middlewares;
var builder = WebApplication.CreateBuilder(args);
// Configure Nera Core with fluent API
builder.Services
.AddNeraCore(builder.Configuration)
.WithCoreOptions(options =>
{
options.ApplicationName = "MyApp";
options.Version = "v1";
})
.WithMediatR()
.WithValidation()
.WithLogging()
.WithTimestampConverter()
.Build();
var app = builder.Build();
// Use Nera middleware for response transformation
app.UseMiddleware<ResultTransformationMiddleware>();
app.Run();
๐ Table of Contents
- Features
- Configuration
- Core Components
- Middleware
- Logging
- JSON Serialization
- DateTime Handling
- Exception Handling
- API Response Format
โจ Features
| Feature | Description |
|---|---|
| CQRS | MediatR integration with Command/Query separation |
| Validation | FluentValidation with automatic pipeline integration |
| Logging | Serilog with Elasticsearch, Console, and File sinks |
| Result Pattern | MethodResult<T> for consistent API responses |
| Pagination | Built-in pagination support with metadata |
| Exception Handling | Global exception handling with localized messages |
| JSON Converters | Unix timestamp converters for DateTime |
| Response Transformation | Automatic API response wrapping |
โ๏ธ Configuration
Builder Pattern
Use the fluent CoreBuilder API to configure services:
builder.Services
.AddNeraCore(builder.Configuration)
// Core application options
.WithCoreOptions(options =>
{
options.ApplicationName = "MyApp";
options.Version = "v1";
options.Environment = "Production";
options.AcceptedLanguages = "en-US,vi-VN";
})
// Database configuration
.WithDatabase(options =>
{
options.ConnectionString = "Host=localhost;...";
options.MaxPoolSize = 100;
options.CommandTimeout = 30;
})
// Or simply:
// .WithDatabase("Host=localhost;...")
// Redis caching
.WithRedis(options =>
{
options.ConnectionString = "localhost:6379";
options.InstanceName = "myapp:";
options.DefaultExpirationMinutes = 60;
})
// RabbitMQ messaging
.WithRabbitMq(options =>
{
options.ConnectionString = "amqp://guest:guest@localhost:5672";
options.ExchangeName = "my_exchange";
options.QueueName = "my_queue";
})
// Elasticsearch for logging
.WithElasticsearch(options =>
{
options.Url = "http://localhost:9200";
options.IndexFormat = "logs-{0:yyyy.MM.dd}";
})
// MediatR with behaviors
.WithMediatR()
// FluentValidation
.WithValidation()
// Serilog logging
.WithLogging(options =>
{
options.MinimumLevel = Serilog.Events.LogEventLevel.Information;
options.UseConsoleLogging = true;
options.UseFileLogging = true;
options.LogFilePath = "logs/app.log";
})
// JSON serialization with Unix timestamps
.WithTimestampConverter(useSeconds: false) // milliseconds by default
// Scan assemblies for handlers/validators
.WithAssemblies(typeof(Program).Assembly)
.Build();
Configuration File (appsettings.json)
All options can be configured via appsettings.json:
{
"NeraCore": {
"ApplicationName": "MyApp",
"Version": "v1",
"Environment": "Production",
"AcceptedLanguages": "en-US,vi-VN",
"AllowOrigin": "*"
},
"Database": {
"ConnectionString": "Host=localhost;Port=5432;Database=mydb;Username=postgres;Password=postgres",
"EnablePooling": true,
"MinPoolSize": 1,
"MaxPoolSize": 100,
"ConnectionTimeout": 30,
"CommandTimeout": 30
},
"Redis": {
"Enabled": true,
"ConnectionString": "localhost:6379",
"InstanceName": "myapp:",
"DefaultExpirationMinutes": 60,
"UseSsl": false
},
"RabbitMq": {
"Enabled": true,
"ConnectionString": "amqp://guest:guest@localhost:5672",
"ExchangeName": "my_exchange",
"QueueName": "my_queue",
"RoutingKey": "my_routing_key"
},
"Elasticsearch": {
"Enabled": true,
"Url": "http://localhost:9200",
"Username": "elastic",
"Password": "changeme",
"IndexFormat": "logs-{0:yyyy.MM.dd}"
},
"JsonSerialization": {
"UseUnixTimestamp": true,
"UseSeconds": false,
"UseCamelCase": true,
"IgnoreNullValues": true
},
"ResponseTransformation": {
"Enabled": true,
"IncludeTraceId": true,
"IncludeProcessingTime": true,
"ExcludePaths": ["/swagger*", "/health*"]
}
}
Environment Variables
Environment variables take precedence over configuration files:
| Variable | Description | Default |
|---|---|---|
APPLICATION_NAME |
Application name | Nera.Lib.Core |
APP_VERSION |
Application version | v1 |
ENV_CONNECTION_STRING |
Database connection string | - |
ENV_REDIS_CONNECTION_STRING |
Redis connection string | localhost:6379 |
ENV_REDIS_CACHE_ENABLE |
Enable Redis caching | false |
ENV_RABBITMQ_CONNECTION_STRING |
RabbitMQ connection string | - |
ENV_ES_URL |
Elasticsearch URL | http://localhost:9200 |
ENV_ES_LOGS_ENABLE |
Enable Elasticsearch logging | false |
ENV_ACCEPT_LANGUAGES |
Accepted languages | en-US |
ALLOW_ORIGIN |
CORS allowed origins | * |
๐๏ธ Core Components
CQRS Pattern
Commands
using Nera.Lib.Core.CQRS;
using Nera.Lib.Core.Results.ActionResult;
// Define a command
public record CreateUserCommand(string Name, string Email) : ICommand<MethodResult<UserDto>>;
// Implement the handler
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand, MethodResult<UserDto>>
{
private readonly IUserRepository _repository;
public CreateUserCommandHandler(IUserRepository repository)
{
_repository = repository;
}
public async Task<MethodResult<UserDto>> Handle(
CreateUserCommand request,
CancellationToken cancellationToken)
{
var user = new User { Name = request.Name, Email = request.Email };
await _repository.AddAsync(user, cancellationToken);
var result = new MethodResult<UserDto>();
result.AddResult(user.Adapt<UserDto>());
return result;
}
}
Queries
// Define a query
public record GetUserByIdQuery(Guid Id) : IQuery<MethodResult<UserDto>>;
// Implement the handler
public class GetUserByIdQueryHandler : IQueryHandler<GetUserByIdQuery, MethodResult<UserDto>>
{
private readonly IUserRepository _repository;
public async Task<MethodResult<UserDto>> Handle(
GetUserByIdQuery request,
CancellationToken cancellationToken)
{
var user = await _repository.GetByIdAsync(request.Id, cancellationToken);
var result = new MethodResult<UserDto>();
if (user == null)
{
result.AddError("NOT_FOUND", "User not found", "User not found", new ErrorResult());
return result;
}
result.AddResult(user.Adapt<UserDto>());
return result;
}
}
Validation
Validators are automatically discovered and integrated into the MediatR pipeline:
using FluentValidation;
using Nera.Lib.Core.Validation;
public class CreateUserCommandValidator : AbstractValidator<CreateUserCommand>
{
public CreateUserCommandValidator()
{
RuleFor(x => x.Name)
.NotEmpty().WithMessage("Name is required")
.MaximumLength(100).WithMessage("Name must not exceed 100 characters");
RuleFor(x => x.Email)
.NotEmpty().WithMessage("Email is required")
.EmailAddress().WithMessage("Invalid email format");
}
}
Common Validation Rules
using Nera.Lib.Core.Validation;
public class MyValidator : AbstractValidator<MyCommand>
{
public MyValidator()
{
// Use common validation rules
RuleFor(x => x.PhoneNumber).ValidPhoneNumber();
RuleFor(x => x.Url).ValidUrl();
RuleFor(x => x.Date).ValidDate();
}
}
Result Pattern
MethodResult<T>
using Nera.Lib.Core.Results.ActionResult;
// Success result
var result = new MethodResult<UserDto>();
result.AddResult(userDto);
result.AddMessage("User created successfully");
// Error result
var errorResult = new MethodResult<UserDto>();
errorResult.AddError(
code: "USER_EXISTS",
message: "User already exists",
errorMessage: "A user with this email already exists",
errorResult: new ErrorResult { Details = "email@example.com" }
);
VoidMethodResult
// For operations without return data
var result = new VoidMethodResult();
result.AddMessage("Operation completed successfully");
Pagination
using Nera.Lib.Core.Results.Pagination;
// Create paginated result
var paginatedResult = new PaginatedResult<UserDto>(
page: 1,
pageSize: 10,
count: totalCount,
data: users
);
// Convert entity to DTO
var dtoResult = paginatedResult.ToResult<UserResponseDto>();
๐ง Middleware
ResultTransformationMiddleware
Automatically wraps API responses in a standard format:
var app = builder.Build();
// Add before other middleware
app.UseMiddleware<ResultTransformationMiddleware>();
app.MapControllers();
Features:
- Wraps all responses in standard format
- Adds metadata (traceId, processingTime, timestamp)
- Handles pagination metadata automatically
- Translates error messages based on Accept-Language header
- Excludes gRPC requests automatically
- Excludes file responses (PDF, images, etc.)
๐ Logging
Basic Configuration
builder.Services
.AddNeraCore(builder.Configuration)
.WithLogging(options =>
{
options.MinimumLevel = LogEventLevel.Information;
options.UseConsoleLogging = true;
options.UseFileLogging = true;
options.LogFilePath = "logs/app.log";
})
.Build();
With Elasticsearch
.WithLogging(options =>
{
options.UseElasticsearch = true;
options.ElasticsearchUrl = "http://localhost:9200";
options.IndexFormat = "myapp-logs-{0:yyyy.MM.dd}";
})
Pre-configured Environments
using Nera.Lib.Core.Logging;
// Development
.WithLogging(_ => SerilogExtensions.CreateDevelopmentOptions())
// Production
.WithLogging(_ => SerilogExtensions.CreateProductionOptions())
// Testing
.WithLogging(_ => SerilogExtensions.CreateTestingOptions())
Sensitive Data Masking
The following data is automatically masked in logs:
- Passwords, secrets, credentials
- API keys, tokens
- Credit card numbers
- Email addresses, phone numbers
- SSN, personal identifiers
๐ JSON Serialization
Unix Timestamp Converter
Configure DateTime to be serialized as Unix timestamps:
builder.Services
.AddNeraCore(builder.Configuration)
.WithTimestampConverter(useSeconds: false) // milliseconds
.Build();
// Or with full options
.WithJsonOptions(options =>
{
options.UseUnixTimestamp = true;
options.UseSeconds = false; // Use milliseconds
options.UseCamelCase = true;
options.IgnoreNullValues = true;
})
Manual Configuration
using Nera.Lib.Core.Extensions;
// Get pre-configured JsonSerializerOptions
var options = JsonOptionsExtensions.CreateNeraJsonOptions(useSeconds: false);
// Or configure MVC JSON options
builder.Services.AddNeraJsonOptions(useSeconds: false);
๐ DateTime Handling
Request (Input)
The library accepts both formats in requests:
// ISO 8601 format
{ "createdAt": "2025-12-03T10:30:00Z" }
// Unix timestamp (milliseconds)
{ "createdAt": 1733224200000 }
// Unix timestamp (seconds) - auto-detected
{ "createdAt": 1733224200 }
Response (Output)
All DateTime values are returned as Unix timestamps (milliseconds):
{
"data": {
"id": "123",
"createdAt": 1733224200000,
"updatedAt": 1733310600000
},
"_metadata": {
"timestamp": 1733224200000
}
}
โ ๏ธ Exception Handling
Built-in Exceptions
using Nera.Lib.Core.Exceptions;
// 400 Bad Request
throw new BadRequestException("Invalid input");
throw new InvalidValidatorException("Validation failed");
throw new BusinessRuleViolationException("Business rule violated");
// 401 Unauthorized
throw new UnAuthorizeException("Authentication required");
// 403 Forbidden
throw new ForbidException("Access denied");
// 404 Not Found
throw new NotFoundException("Resource not found");
// 500 Internal Server Error
throw new InternalServerException("An error occurred");
Exception to HTTP Status Mapping
| Exception | Status Code |
|---|---|
BadRequestException |
400 |
InvalidValidatorException |
400 |
BusinessRuleViolationException |
400 |
UnAuthorizeException |
401 |
ForbidException |
403 |
NotFoundException |
404 |
InternalServerException |
500 |
Localized Error Messages
Error messages are automatically translated based on Accept-Language header:
// Add error resources
// Resources/CommonErrors-en.json
{
"USER_NOT_FOUND": "User not found"
}
// Resources/CommonErrors-vi.json
{
"USER_NOT_FOUND": "Khรดng tรฌm thแบฅy ngฦฐแปi dรนng"
}
๐ API Response Format
Success Response
{
"status": "Success",
"message": "Success",
"data": {
"id": "123",
"name": "John Doe",
"createdAt": 1733224200000
},
"_metadata": {
"traceId": "0HNEFIIB8HKSG:00000001",
"processingTime": 45,
"timestamp": 1733224200000
}
}
Paginated Response
{
"status": "Success",
"message": "Success",
"data": [
{ "id": "1", "name": "User 1" },
{ "id": "2", "name": "User 2" }
],
"_metadata": {
"traceId": "0HNEFIIB8HKSG:00000001",
"processingTime": 120,
"timestamp": 1733224200000,
"pagination": {
"page": 1,
"pageSize": 10,
"count": 2,
"total": 50,
"totalPages": 5,
"hasPreviousPage": false,
"hasNextPage": true
}
}
}
Error Response
{
"status": "Fail",
"message": "Validation failed",
"data": null,
"error": {
"code": "VALIDATION_ERROR",
"message": "One or more validation errors occurred",
"details": [
{ "field": "email", "message": "Invalid email format" }
]
},
"_metadata": {
"traceId": "0HNEFIIB8HKSG:00000001",
"processingTime": 5,
"timestamp": 1733224200000
}
}
๐๏ธ Requirements
- .NET 9.0 or later
- ASP.NET Core 9.0 (for web features)
๐ฆ Dependencies
- FluentValidation 12.x
- MediatR 13.x
- Serilog 4.x
- Mapster 7.x
- System.Text.Json 9.x
๐ Examples
See the Examples folder for complete working examples.
๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ข About
Developed by Nextera Systems for building robust .NET applications.
Version: 1.0.0
Target Framework: .NET 9.0
Repository: https://github.com/nextera-systems/nera-lib-core
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- FluentValidation (>= 12.0.0)
- FluentValidation.DependencyInjectionExtensions (>= 12.0.0)
- Mapster (>= 7.4.0)
- MediatR (>= 13.1.0)
- Microsoft.AspNetCore.Mvc.Versioning (>= 5.1.0)
- Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer (>= 5.1.0)
- Microsoft.Extensions.Configuration (>= 9.0.10)
- Microsoft.Extensions.Hosting (>= 9.0.10)
- Newtonsoft.Json (>= 13.0.4)
- Serilog (>= 4.3.0)
- Serilog.Enrichers.Environment (>= 3.0.1)
- Serilog.Extensions.Hosting (>= 9.0.0)
- Serilog.Extensions.Logging (>= 9.0.2)
- Serilog.Sinks.Console (>= 6.0.0)
- Serilog.Sinks.Elasticsearch (>= 10.0.0)
- Serilog.Sinks.File (>= 7.0.0)
- Swashbuckle.AspNetCore.SwaggerGen (>= 9.0.6)
- System.Text.Json (>= 9.0.9)
NuGet packages (11)
Showing the top 5 NuGet packages that depend on Nera.Lib.Core:
| Package | Downloads |
|---|---|
|
Nera.Lib.Web
Web models, business rules, aggregates, value objects, and domain services for Nera applications |
|
|
Nera.Lib.Database
Database access layer with Entity Framework Core, Repository pattern, Specification pattern, and advanced querying capabilities for Nera applications |
|
|
Nera.Lib.Messaging.Abstractions
Complete messaging abstractions with MassTransit implementation |
|
|
Nera.Lib.Domain
Domain models, business rules, aggregates, value objects, and domain services for Nera applications |
|
|
Nera.Lib.Infrastructure
Infrastructure services and implementations for Nera applications |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.20 | 680 | 12/2/2025 |
| 1.0.19 | 277 | 11/27/2025 |
| 1.0.18 | 588 | 11/13/2025 |
| 1.0.17 | 709 | 11/9/2025 |
| 1.0.16 | 200 | 11/9/2025 |
| 1.0.15 | 166 | 11/9/2025 |
| 1.0.14 | 787 | 10/18/2025 |
| 1.0.13 | 261 | 10/13/2025 |
| 1.0.12 | 175 | 10/12/2025 |
| 1.0.11 | 474 | 9/28/2025 |
| 1.0.10 | 174 | 9/27/2025 |
| 1.0.9 | 267 | 9/15/2025 |
| 1.0.8 | 1,291 | 9/9/2025 |
| 1.0.7 | 192 | 9/2/2025 |
| 1.0.6 | 911 | 8/3/2025 |
| 1.0.5 | 141 | 8/2/2025 |
| 1.0.4 | 100 | 8/2/2025 |
| 1.0.3 | 99 | 8/1/2025 |
| 1.0.2 | 161 | 7/31/2025 |
| 1.0.1 | 683 | 7/27/2025 |
| 1.0.0 | 306 | 7/27/2025 |