Advanced foundational library with cutting-edge C# features and 17 global business enums for multi-application standardization. Includes domain-driven design patterns, comprehensive error handling with HTTP mapping, specification pattern interfaces, functional result types, JSON utilities, validation helpers, and enterprise-ready abstractions. Features ready-to-use enums for business status, priorities, document types, demographics, currencies, payment methods, user roles, industries, company sizes, event types, and internationalization. Built with collection expressions, required properties, record structs, and source generation for optimal performance. Clean architecture with no persistence dependencies.
$ dotnet add package Acontplus.CoreA modern .NET 9+ foundational library providing enterprise-grade components with domain-driven design patterns, comprehensive error handling, and modern C# features.
[] syntaxAcontplus.Core provides high-performance, secure JSON utilities via Extensions/JsonExtensions:
using Acontplus.Core.Extensions;
// Serialize with enterprise defaults
var json = myObject.SerializeModern();
// Serialize with pretty formatting (for debugging)
var prettyJson = myObject.SerializeModern(pretty: true);
// Deserialize with enterprise defaults
var obj = jsonString.DeserializeModern<MyType>();
// Safe deserialization with fallback
var objOrDefault = jsonString.DeserializeModernSafe<MyType>(fallback: new MyType());
// Deep clone via JSON
var clone = myObject.CloneViaJson();
// Use options directly (for ASP.NET Core, etc.)
var options = JsonExtensions.DefaultOptions;Install-Package Acontplus.Coredotnet add package Acontplus.Core<PackageReference Include="Acontplus.Core" Version="1.2.0" />public class Product : AuditableEntity<int>
{
public required string Name { get; set; }
public required decimal Price { get; set; }
public string? Description { get; set; }
// Factory method for creating products
public static Product Create(int id, string name, decimal price, int createdByUserId)
{
return new Product
{
Id = id,
Name = name,
Price = price,
CreatedAt = DateTime.UtcNow,
CreatedByUserId = createdByUserId
};
}
}// Create domain errors
var validationError = DomainError.Validation(
code: "PRODUCT_INVALID_PRICE",
message: "Product price must be greater than zero",
target: "price"
);
var notFoundError = DomainError.NotFound(
code: "PRODUCT_NOT_FOUND",
message: "Product with ID {id} was not found",
target: "id"
);
// Convert to API response
var response = validationError.ToApiResponse<ProductDto>();public async Task<Result<Product>> GetProductAsync(int id)
{
var product = await _repository.GetByIdAsync(id);
return product is not null
? Result<Product>.Success(product)
: Result<Product>.Failure(DomainError.NotFound("PRODUCT_NOT_FOUND", $"Product {id} not found"));
}
// Usage with pattern matching
var result = await GetProductAsync(123);
var response = result.Match(
success: product => ApiResponse<Product>.Success(product),
failure: error => error.ToApiResponse<Product>()
);public class ActiveProductsSpecification : BaseSpecification<Product>
{
public ActiveProductsSpecification(PaginationDto pagination) : base(p => p.IsActive)
{
ApplyPaging(pagination);
AddOrderBy(p => p.CreatedAt, isDescending: true);
AddInclude(p => p.Category);
}
}
// Usage
var spec = new ActiveProductsSpecification(new PaginationDto { Page = 1, PageSize = 10 });
var products = await _repository.FindWithSpecificationAsync(spec);[HttpGet("{id}")]
public async Task<ApiResponse<ProductDto>> GetProduct(int id)
{
var product = await _productService.GetByIdAsync(id);
if (product is null)
{
return ApiResponse<ProductDto>.Failure(
DomainError.NotFound("PRODUCT_NOT_FOUND", $"Product {id} not found")
);
}
return ApiResponse<ProductDto>.Success(product.ToDto());
}public class ProductCreatedEvent : IDomainEvent
{
public int ProductId { get; }
public string ProductName { get; }
public DateTime OccurredOn { get; }
public ProductCreatedEvent(int productId, string productName)
{
ProductId = productId;
ProductName = productName;
OccurredOn = DateTime.UtcNow;
}
}
// In your entity
public void MarkAsCreated()
{
AddDomainEvent(new ProductCreatedEvent(Id, Name));
}public interface IProductRepository : IRepository<Product, int>
{
Task<IReadOnlyList<Product>> GetByCategoryAsync(int categoryId);
Task<bool> ExistsByNameAsync(string name);
}
public class ProductRepository : BaseRepository<Product, int>, IProductRepository
{
public ProductRepository(DbContext context) : base(context) { }
public async Task<IReadOnlyList<Product>> GetByCategoryAsync(int categoryId)
{
return await FindAsync(p => p.CategoryId == categoryId);
}
public async Task<bool> ExistsByNameAsync(string name)
{
return await ExistsAsync(p => p.Name == name);
}
}public async Task<Result<Product>> CreateProductAsync(CreateProductRequest request)
{
var errors = new List<DomainError>();
if (string.IsNullOrWhiteSpace(request.Name))
errors.Add(DomainError.Validation("INVALID_NAME", "Product name is required"));
if (request.Price <= 0)
errors.Add(DomainError.Validation("INVALID_PRICE", "Price must be greater than zero"));
if (await _repository.ExistsByNameAsync(request.Name))
errors.Add(DomainError.Conflict("DUPLICATE_NAME", "Product name already exists"));
if (errors.Any())
return Result<Product>.Failure(errors.GetMostSevereError());
var product = Product.Create(request.Name, request.Price, request.CreatedByUserId);
await _repository.AddAsync(product);
return Result<Product>.Success(product);
}// XML Validation
if (!DataValidation.IsXml(xmlContent))
{
return DomainError.Validation("INVALID_XML", "Invalid XML format");
}
// JSON Validation
if (!DataValidation.IsValidJson(jsonContent))
{
return DomainError.Validation("INVALID_JSON", "Invalid JSON format");
}
// IP Address Validation
var validIp = DataValidation.ValidateIpAddress("192.168.1.1");Entity<TId> - Base entity with domain eventsAuditableEntity<TId> - Entity with audit trail and soft deleteBaseEntity - Convenience base for int-keyed entitiesApiResponse<T> - Standardized API response formatPaginationDto - Pagination parametersApiError - Detailed error informationDomainError - Business logic errorsResult<T> - Functional result patternErrorType - Categorized error typesIRepository<TEntity, TId> - Generic repository interfaceISpecification<T> - Query specification patternPagedResult<T> - Paginated query resultsWe welcome contributions! Please see our Contributing Guidelines for details.
git clone https://github.com/Acontplus-S-A-S/acontplus-dotnet-libs.git
cd acontplus-dotnet-libs
dotnet restore
dotnet buildThis project is licensed under the MIT License - see the LICENSE file for details.
Ivan Paz - @iferpaz7
Acontplus S.A.S. - Enterprise software solutions
Built with ❤️ for the .NET community