Acontplus.Utilities 1.3.6

dotnet add package Acontplus.Utilities --version 1.3.6
                    
NuGet\Install-Package Acontplus.Utilities -Version 1.3.6
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Acontplus.Utilities" Version="1.3.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Acontplus.Utilities" Version="1.3.6" />
                    
Directory.Packages.props
<PackageReference Include="Acontplus.Utilities" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Acontplus.Utilities --version 1.3.6
                    
#r "nuget: Acontplus.Utilities, 1.3.6"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Acontplus.Utilities@1.3.6
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Acontplus.Utilities&version=1.3.6
                    
Install as a Cake Addin
#tool nuget:?package=Acontplus.Utilities&version=1.3.6
                    
Install as a Cake Tool

Acontplus.Utilities

NuGet .NET License

A comprehensive .NET 9+ utility library providing common functionality for business applications. Async, extension methods, minimal API support, and more.

🚀 Features

  • Encryption - Data encryption/decryption utilities
  • External Validations - Third-party validation integrations
  • Barcode Generation - Barcode creation and processing
  • Custom Logging - Enhanced logging capabilities
  • Enum Extensions - Enhanced enum functionality
  • Picture Helper - Image processing utilities
  • Text Handlers - Text manipulation and processing
  • API Response Extensions - Convert results to IActionResult or IResult for MVC/Minimal APIs
  • Pagination & Metadata - Helpers for API metadata, pagination, and diagnostics

📦 Installation

NuGet Package Manager

Install-Package Acontplus.Utilities

.NET CLI

dotnet add package Acontplus.Utilities

PackageReference

<ItemGroup>
  <PackageReference Include="Acontplus.Utilities" Version="1.0.12" />
</ItemGroup>

🎯 Quick Start

1. API Response Extensions (Minimal API)

using Acontplus.Utilities.Extensions;

app.MapGet("/example", () =>
{
    var response = new ApiResponse<string>("Hello World");
    return response.ToMinimalApiResult();
});

2. API Response Extensions (Controller)

using Acontplus.Utilities.Extensions;

public IActionResult Get()
{
    var response = new ApiResponse<string>("Hello World");
    return response.ToActionResult();
}

3. Encryption Example

var encryptionService = new SensitiveDataEncryptionService();
byte[] encrypted = await encryptionService.EncryptToBytesAsync("password", "data");
string decrypted = await encryptionService.DecryptFromBytesAsync("password", encrypted);

4. Pagination Metadata Example

var metadata = new Dictionary<string, object>()
    .WithPagination(page: 1, pageSize: 10, totalItems: 100);

📄 Core Examples

PaginationQuery with Minimal APIs

The PaginationQuery record provides automatic parameter binding in minimal APIs with support for multiple filters, sorting, and pagination.

Backend (Minimal API)
// Program.cs or endpoint definition
app.MapGet("/api/users", async (PaginationQuery pagination, IUserService userService) =>
{
    var result = await userService.GetPaginatedUsersAsync(pagination);
    return Results.Ok(result);
})
.WithName("GetUsers")
.WithOpenApi();

// Service implementation
public async Task<PagedResult<UserDto>> GetPaginatedUsersAsync(PaginationQuery pagination)
{
    var spParameters = new Dictionary<string, object>
    {
        ["@PageIndex"] = pagination.PageIndex,
        ["@PageSize"] = pagination.PageSize,
        ["@SearchTerm"] = pagination.SearchTerm ?? (object)DBNull.Value,
        ["@SortBy"] = pagination.SortBy ?? "CreatedAt",
        ["@SortDirection"] = (pagination.SortDirection ?? SortDirection.Asc).ToString()
    };

    // Add filters from PaginationQuery.Filters
    if (pagination.Filters != null)
    {
        foreach (var filter in pagination.Filters)
        {
            var paramName = $"@{filter.Key}";
            spParameters[paramName] = filter.Value ?? DBNull.Value;
        }
    }

    // Execute stored procedure with all parameters
    var dataSet = await _adoRepository.GetDataSetAsync("sp_GetPaginatedUsers", spParameters);
    // Process results and return PagedResult
}
Frontend (JavaScript/TypeScript)
// API client function
async function getUsers(filters: UserFilters = {}) {
    const params = new URLSearchParams({
        pageIndex: '1',
        pageSize: '20',
        searchTerm: filters.searchTerm || '',
        sortBy: 'createdAt',
        sortDirection: 'desc'
    });

    // Add filters
    if (filters.status) params.append('filters[status]', filters.status);
    if (filters.role) params.append('filters[role]', filters.role);
    if (filters.isActive !== undefined) params.append('filters[isActive]', filters.isActive.toString());
    if (filters.createdDate) params.append('filters[createdDate]', filters.createdDate);

    const response = await fetch(`/api/users?${params.toString()}`);
    return response.json();
}

// Usage examples
const users = await getUsers({
    searchTerm: 'john',
    status: 'active',
    role: 'admin',
    isActive: true
});

// URL generated: /api/users?pageIndex=1&pageSize=20&searchTerm=john&sortBy=createdAt&sortDirection=desc&filters[status]=active&filters[role]=admin&filters[isActive]=true
React Component Example
import React, { useState, useEffect } from 'react';

interface UserFilters {
    searchTerm?: string;
    status?: string;
    role?: string;
    isActive?: boolean;
}

const UserList: React.FC = () => {
    const [users, setUsers] = useState([]);
    const [filters, setFilters] = useState<UserFilters>({});
    const [pagination, setPagination] = useState({ pageIndex: 1, pageSize: 20 });

    const fetchUsers = async () => {
        const params = new URLSearchParams({
            pageIndex: pagination.pageIndex.toString(),
            pageSize: pagination.pageSize.toString(),
            sortBy: 'createdAt',
            sortDirection: 'desc'
        });

        // Add search term
        if (filters.searchTerm) {
            params.append('searchTerm', filters.searchTerm);
        }

        // Add filters
        Object.entries(filters).forEach(([key, value]) => {
            if (value !== undefined && key !== 'searchTerm') {
                params.append(`filters[${key}]`, value.toString());
            }
        });

        const response = await fetch(`/api/users?${params.toString()}`);
        const data = await response.json();
        setUsers(data.items);
    };

    useEffect(() => {
        fetchUsers();
    }, [filters, pagination]);

    return (
        <div>
            {/* Filter controls */}
            <input
                type="text"
                placeholder="Search users..."
                onChange={(e) => setFilters(prev => ({ ...prev, searchTerm: e.target.value }))}
            />
            <select onChange={(e) => setFilters(prev => ({ ...prev, status: e.target.value }))}>
                <option value="">All Status</option>
                <option value="active">Active</option>
                <option value="inactive">Inactive</option>
            </select>
            
            {/* User list */}
            {users.map(user => (
                <div key={user.id}>{user.name}</div>
            ))}
        </div>
    );
};
Query Parameter Examples
# Basic pagination
GET /api/users?pageIndex=1&pageSize=20

# With search and sorting
GET /api/users?pageIndex=1&pageSize=20&searchTerm=john&sortBy=name&sortDirection=asc

# With multiple filters
GET /api/users?pageIndex=1&pageSize=20&filters[status]=active&filters[role]=admin&filters[isActive]=true

# Complex filter combinations
GET /api/users?pageIndex=1&pageSize=20&searchTerm=john&filters[status]=active&filters[role]=admin&filters[createdDate]=2024-01-01&filters[departments][]=IT&filters[departments][]=HR

Result & API Response Patterns with Usuario Module

Controller Usage
[HttpGet("{id:int}")]
public async Task<IActionResult> GetUsuario(int id)
{
    var result = await _usuarioService.GetByIdAsync(id);
    return result.ToGetActionResult();
}

[HttpPost]
public async Task<IActionResult> CreateUsuario([FromBody] UsuarioDto dto)
{
    var usuario = ObjectMapper.Map<UsuarioDto, Usuario>(dto);
    var result = await _usuarioService.AddAsync(usuario);
    if (result.IsSuccess && result.Value is not null)
    {
        var locationUri = $"/api/Usuario/{result.Value.Id}";
        return ApiResponse<Usuario>.Success(result.Value, new ApiResponseOptions { Message = "Usuario creado exitosamente." }).ToActionResult();
    }
    return result.ToActionResult();
}

[HttpPut("{id:int}")]
public async Task<IActionResult> UpdateUsuario(int id, [FromBody] UsuarioDto dto)
{
    var usuario = ObjectMapper.Map<UsuarioDto, Usuario>(dto);
    var result = await _usuarioService.UpdateAsync(id, usuario);
    if (result.IsSuccess)
    {
        return ApiResponse<Usuario>.Success(result.Value, new ApiResponseOptions { Message = "Usuario actualizado correctamente." }).ToActionResult();
    }
    return result.ToActionResult();
}

[HttpDelete("{id:int}")]
public async Task<IActionResult> DeleteUsuario(int id)
{
    var result = await _usuarioService.DeleteAsync(id);
    return result.ToDeleteActionResult();
}
Minimal API Usage
app.MapGet("/usuarios/{id:int}", async (int id, IUsuarioService service) =>
{
    var result = await service.GetByIdAsync(id);
    return result.ToMinimalApiResult();
});
Service Layer Example
public async Task<Result<Usuario, DomainErrors>> AddAsync(Usuario usuario)
{
    var errors = new List<DomainError>();
    if (string.IsNullOrWhiteSpace(usuario.Username))
        errors.Add(DomainError.Validation("USERNAME_REQUIRED", "Username is required"));
    if (string.IsNullOrWhiteSpace(usuario.Email))
        errors.Add(DomainError.Validation("EMAIL_REQUIRED", "Email is required"));

    if (errors.Count > 0)
        return DomainErrors.Multiple(errors);

    // ... check for existing user, add, etc.
}

🗃️ Data Utilities

DataConverters

using Acontplus.Utilities.Data;

// Convert DataTable to JSON
string json = DataConverters.DataTableToJson(myDataTable);

// Convert DataSet to JSON
string json = DataConverters.DataSetToJson(myDataSet);

// Convert JSON to DataTable
DataTable table = DataConverters.JsonToDataTable(jsonString);

// Serialize any object (with DataTable/DataSet support)
string json = DataConverters.SerializeObjectCustom(myObject);

// Serialize and sanitize complex objects
string json = DataConverters.SerializeSanitizedData(myObject);

DataTableMapper

using Acontplus.Utilities.Data;

// Map a DataRow to a strongly-typed model
var model = DataTableMapper.MapDataRowToModel<MyModel>(dataRow);

// Map a DataTable to a list of models
List<MyModel> models = DataTableMapper.MapDataTableToList<MyModel>(dataTable);

🧩 JSON Utilities

JsonHelper

using Acontplus.Utilities.Json;

// Validate JSON
var result = JsonHelper.ValidateJson(jsonString);
if (!result.IsValid) Console.WriteLine(result.ErrorMessage);

// Get a property value from JSON
string? value = JsonHelper.GetJsonProperty<string>(jsonString, "propertyName");

// Merge two JSON objects
string merged = JsonHelper.MergeJson(json1, json2);

// Compare two JSON strings (ignoring property order)
bool areEqual = JsonHelper.AreEqual(json1, json2);

JsonManipulationExtensions

using Acontplus.Utilities.Json;

// Validate JSON using extension
bool isValid = jsonString.IsValidJson();

// Get property value using extension
int? id = jsonString.GetJsonProperty<int>("id");

// Merge JSON using extension
string merged = json1.MergeJson(json2);

// Compare JSON using extension
bool equal = json1.JsonEquals(json2);

🔄 Object Mapping

ObjectMapper

using Acontplus.Utilities.Mapping;

// Map between objects (AutoMapper-like)
var target = ObjectMapper.Map<SourceType, TargetType>(sourceObject);

// Configure custom mapping
ObjectMapper.CreateMap<SourceType, TargetType>()
    .ForMember(dest => dest.SomeProperty, src => src.OtherProperty)
    .Ignore(dest => dest.IgnoredProperty);

// Map with configuration
var mapped = ObjectMapper.Map<SourceType, TargetType>(sourceObject);

🔧 Advanced Usage

File Name Sanitization

string safeName = FileExtensions.SanitizeFileName("my*illegal:file?.txt");

Base64 Conversion

string base64 = FileExtensions.GetBase64FromByte(myBytes);

Compression Utilities

byte[] compressed = CompressionUtils.CompressGZip(data);
byte[] decompressed = CompressionUtils.DecompressGZip(compressed);

📚 API Documentation

  • SensitiveDataEncryptionService - AES encryption/decryption helpers
  • FileExtensions - File name and byte array utilities
  • CompressionUtils - GZip/Deflate compression helpers
  • TextHandlers - String formatting and splitting
  • ApiResponseExtensions - API response helpers for MVC/Minimal APIs
  • DirectoryHelper / EnvironmentHelper - Runtime and environment utilities

🤝 Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

Development Setup

git clone https://github.com/Acontplus-S-A-S/acontplus-dotnet-libs.git
cd acontplus-dotnet-libs
dotnet restore
dotnet build

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🆘 Support

  • 📧 Email: proyectos@acontplus.com
  • 🐛 Issues: GitHub Issues
  • 📖 Documentation: Wiki

👨‍💻 Author

Ivan Paz - @iferpaz7

🏢 Company

Acontplus S.A.S. - Software solutions


Built with ❤️ for the .NET community

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Acontplus.Utilities:

Package Downloads
Acontplus.FactElect

Complete library for electronic invoicing and SRI integration in Ecuador. Includes models, services, XML validation, SRI web service support, and embedded XSD schemas for compliance.

Acontplus.Notifications

Comprehensive library for notification services. Includes email (MailKit, Amazon SES), WhatsApp, push notifications, templating with Scriban, queue management, and enterprise-ready delivery patterns for cloud-native applications.

Acontplus.Reports

Advanced library for comprehensive report generation and management. Includes RDLC report processing, PDF/Excel export capabilities, ReportViewer integration, template support, and enterprise-ready reporting patterns for business applications.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.6 121 8/21/2025
1.3.5 118 8/19/2025
1.3.4 142 8/8/2025
1.3.3 127 8/8/2025
1.3.2 208 8/7/2025
1.3.1 198 8/7/2025
1.3.0 200 8/7/2025
1.2.5 227 8/5/2025
1.2.4 490 7/23/2025
1.2.3 61 7/18/2025
1.2.2 135 7/15/2025
1.2.1 145 7/15/2025
1.2.0 150 7/14/2025
1.1.4 154 7/14/2025
1.1.3 103 7/11/2025
1.1.2 99 7/11/2025
1.1.1 153 7/10/2025
1.1.0 147 7/10/2025
1.0.13 141 7/10/2025
1.0.12 157 7/9/2025
1.0.11 184 7/7/2025
1.0.10 148 7/6/2025
1.0.9 154 7/6/2025
1.0.8 105 7/4/2025
1.0.7 157 7/3/2025
1.0.6 158 7/2/2025
1.0.5 157 7/2/2025
1.0.4 154 7/1/2025

Enhanced with cutting-edge C# features, comprehensive utility functions, encryption with BCrypt, IO operations, text processing, time utilities, JSON helpers, and enterprise-ready cross-cutting concerns.