PortiaNet.Helper
2.1.1
dotnet add package PortiaNet.Helper --version 2.1.1
NuGet\Install-Package PortiaNet.Helper -Version 2.1.1
<PackageReference Include="PortiaNet.Helper" Version="2.1.1" />
<PackageVersion Include="PortiaNet.Helper" Version="2.1.1" />
<PackageReference Include="PortiaNet.Helper" />
paket add PortiaNet.Helper --version 2.1.1
#r "nuget: PortiaNet.Helper, 2.1.1"
#:package PortiaNet.Helper@2.1.1
#addin nuget:?package=PortiaNet.Helper&version=2.1.1
#tool nuget:?package=PortiaNet.Helper&version=2.1.1
PortiaNet.Helper
A comprehensive .NET class library providing enterprise-grade utilities, helpers, and extensions for ASP.NET applications. This library streamlines common development tasks including data pagination, encryption/decryption, audit logging, AI-powered vision processing, and reference data management.
Table of Contents
- AI Vision Processing
- Database & Auditing
- Security & Encryption
- Pagination
- Master Data Reference
- Extension Methods
AI Vision Processing
Overview
The Vision Processing module provides intelligent card and document extraction capabilities powered by AI and optical character recognition (OCR). It extracts structured data from card images including payment cards, ID cards, and business cards.
Key Features
- Multi-format Support: Process card front and back images
- Built-in Extractors: 20+ pre-configured field extractors (card numbers, names, contact details, etc.)
- Extensibility: Register custom extractors for specialized data extraction
- Confidence Scoring: Get confidence levels for extracted fields
- Image Quality Assessment: Evaluate extracted image quality
Quick Start
using PortiaNet.Helper.Ai.Vision;
// Initialize the processor
var processor = new VisionProcessor();
// Process a card from Base64 strings
var result = processor.ProcessCard(frontBase64, backBase64);
// Access extracted data
foreach (var field in result.Fields)
{
var fieldType = field.Key;
var value = field.Value.Value;
var confidence = field.Value.Confidence;
Console.WriteLine($"{fieldType}: {value} (Confidence: {confidence:P})");
}
// Check overall confidence
Console.WriteLine($"Overall Confidence: {result.OverallConfidence:P}");
Console.WriteLine($"Image Quality: {result.ImageQuality}");
Supported Field Types
- Card numbers and security details (CVV, expiry date, cardholder name)
- Contact information (phone, mobile, WhatsApp, email)
- Personal identifiers (name, title, designation)
- Business information (company name, branch, website)
- Social media handles (Instagram)
- Physical addresses and QR codes
Register Custom Extractors
// Implement IFieldExtractor interface
public class CustomExtractor : IFieldExtractor
{
public CardFieldType FieldType { get; }
public CardFieldExtraction Extract(string text) { /* ... */ }
}
// Register with processor
var processor = new VisionProcessor();
processor.RegisterExtractor(new CustomExtractor());
Database & Auditing
Overview
The Database module provides advanced Entity Framework Core integration with built-in audit logging and secure data handling. Choose between standard auditing or encrypted auditing based on your security requirements.
Key Features
- Automatic Audit Trails: Track all entity changes with user attribution
- Encrypted Auditing: Optional field-level encryption for sensitive data
- Change History: Complete audit log of created, modified, and deleted records
- Flexible Configuration: Exclude specific columns or entities from auditing
- ASP.NET Identity Integration: Built-in support for Identity users
Setup
Option 1: Standard Auditable Context
// In Startup.cs
services.AddDbContext<YourDbContext>(options =>
options.UseSqlServer(connectionString));
// Your DbContext class
public class YourDbContext : AuditableIdentityDbContext<IdentityUser, YourDbContext>
{
public YourDbContext(DbContextOptions<YourDbContext> options)
: base(options)
{
// Optionally exclude columns from auditing
NonAuditedColumns.Add("LastSyncDate");
}
public DbSet<YourEntity> YourEntities { get; set; }
}
// Save changes with audit tracking
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
await context.SaveChangesAsync(userId);
Option 2: Encrypted + Auditable Context
// Configure encryption first
services.AddEncryptionDecryptionHelper(options =>
{
options.Key = "your-32-character-encryption-key!"; // Must be exactly 32 chars
});
// Add DbContext
services.AddDbContext<YourSecureDbContext>(options =>
options.UseSqlServer(connectionString));
// Your DbContext class
public class YourSecureDbContext : SecureAuditableIdentityDbContext<IdentityUser, YourSecureDbContext>
{
public YourSecureDbContext(DbContextOptions<YourSecureDbContext> options,
EncryptionDecryptionHelper encDecHelper)
: base(options, encDecHelper)
{
}
public DbSet<YourEntity> YourEntities { get; set; }
}
Exclude Entities/Fields from Auditing
// On entity class - do not audit entire entity
[NoAudit]
public class NonAuditedEntity
{
public int Id { get; set; }
}
// On property - encrypt this field automatically (Secure context only)
[Encrypt]
public string SensitiveData { get; set; }
Access Audit Logs
// Retrieve audit history
var auditLogs = context.AuditLogs
.Where(a => a.TableName == "Users" && a.RecordId == userId)
.OrderByDescending(a => a.DateTime)
.ToList();
foreach (var log in auditLogs)
{
Console.WriteLine($"Action: {log.Action}");
Console.WriteLine($"User: {log.UserId}");
Console.WriteLine($"Date: {log.DateTime}");
Console.WriteLine($"Old Values: {log.OldValues}");
Console.WriteLine($"New Values: {log.NewValues}");
}
Security & Encryption
Overview
The Security Helper provides AES-128 encryption and decryption functionality through dependency injection, enabling seamless integration with your application's security architecture.
Setup
using PortiaNet.Helper.SecurityHelper;
// In Startup.cs or Program.cs
services.AddEncryptionDecryptionHelper(options =>
{
options.Key = "your-32-character-encryption-key!"; // IMPORTANT: Must be exactly 32 characters
});
Usage
public class UserService
{
private readonly EncryptionDecryptionHelper _encDecHelper;
public UserService(EncryptionDecryptionHelper encDecHelper)
{
_encDecHelper = encDecHelper;
}
public string StoreUserCredential(string credential)
{
// Encrypt before storing
string encrypted = _encDecHelper.EncryptString(credential);
// Save to database
return encrypted;
}
public string RetrieveUserCredential(string encryptedCredential)
{
// Decrypt when needed
string decrypted = _encDecHelper.DecryptString(encryptedCredential);
return decrypted;
}
}
Error Handling
try
{
var encrypted = _encDecHelper.EncryptString(sensitiveData);
var decrypted = _encDecHelper.DecryptString(encrypted);
}
catch (EncryptDecryptException ex)
{
Console.WriteLine($"Encryption error: {ex.Message}");
// Handle error appropriately
}
Pagination
Overview
The Pagination module simplifies server-side pagination, filtering, and sorting with a fluent API. It handles complex queries and returns properly structured paginated results with comprehensive metadata.
Key Features
- Efficient Querying: Skip/take pattern for optimal database performance
- Filtering: Declarative filtering with LINQ
- Sorting: Custom sort implementations
- Mapping: Automatic entity-to-DTO transformation
- Metadata: Total records, filtered records, page information
Basic Usage
using PortiaNet.Helper.Pagination;
public class UserService
{
private readonly AppDbContext _context;
public UserService(AppDbContext context)
{
_context = context;
}
public Task<PaginationModel<UserViewModel>> GetUsersAsync(
string filter = null,
int pageIndex = 1,
int pageSize = 10)
{
return PaginationHelper.GetPaginationAsync(
allData: _context.Users.AsQueryable(),
// Define filtering logic
filter: query =>
{
if (!string.IsNullOrEmpty(filter))
{
query = query.Where(u =>
u.FirstName.Contains(filter) ||
u.LastName.Contains(filter) ||
u.Email.Contains(filter));
}
return query;
},
// Define sorting logic
sort: query => query.OrderBy(u => u.FirstName).ThenBy(u => u.LastName),
// Define mapping logic (entity to ViewModel)
mapping: entities => entities.Select(u => new UserViewModel
{
Id = u.Id,
FullName = $"{u.FirstName} {u.LastName}",
Email = u.Email
}).ToList(),
pageSize: pageSize,
pageIndex: pageIndex
);
}
}
Complex Filtering Example
public Task<PaginationModel<OrderViewModel>> GetOrdersAsync(
string searchTerm,
DateTime? fromDate,
DateTime? toDate,
decimal? minAmount,
int pageIndex = 1,
int pageSize = 20)
{
return PaginationHelper.GetPaginationAsync(
allData: _context.Orders.Include(o => o.Customer).AsQueryable(),
filter: query =>
{
if (!string.IsNullOrEmpty(searchTerm))
query = query.Where(o =>
o.OrderNumber.Contains(searchTerm) ||
o.Customer.Name.Contains(searchTerm));
if (fromDate.HasValue)
query = query.Where(o => o.CreatedDate >= fromDate.Value);
if (toDate.HasValue)
query = query.Where(o => o.CreatedDate <= toDate.Value);
if (minAmount.HasValue)
query = query.Where(o => o.TotalAmount >= minAmount.Value);
return query;
},
sort: query => query.OrderByDescending(o => o.CreatedDate),
mapping: entities => entities.Select(o => new OrderViewModel
{
Id = o.Id,
OrderNumber = o.OrderNumber,
Customer = o.Customer.Name,
Amount = o.TotalAmount,
Date = o.CreatedDate
}).ToList(),
pageSize: pageSize,
pageIndex: pageIndex
);
}
Response Model
public class PaginationModel<T>
{
public List<T> Items { get; set; } // Current page items
public int TotalRecords { get; set; } // Total records before filtering
public int FilteredRecords { get; set; } // Total records after filtering
public int PageIndex { get; set; } // Current page (1-based)
public int PageSize { get; set; } // Items per page
public int CurrentPageRecordsCount { get; set; }// Items on current page
}
Master Data Reference
Overview
Master Data provides access to commonly used reference information including geographical data, currencies, languages, and time zones. This data is static and optimized for quick lookup.
Available Masters
| Master | Data |
|---|---|
| Continent | 7 continents |
| Country | All countries with country codes and regions |
| Region | States, provinces, and regions per country |
| Currency | Currency codes and denominations |
| Language | Language codes and names |
| TimeZone | Timezone information and UTC offsets |
Usage
using PortiaNet.Helper.MasterData;
// Get all continents
var continents = Continent.GetAll();
foreach (var continent in continents)
{
Console.WriteLine($"{continent.Id}: {continent.Name}");
}
// Get all countries
var countries = Country.GetAll();
var usaCountry = countries.FirstOrDefault(c => c.Code == "US");
// Get countries by continent
var asianCountries = Country.GetAll()
.Where(c => c.ContinentId == continentId)
.ToList();
// Get regions/states for a country
var usStates = Region.GetAll()
.Where(r => r.CountryId == usaCountry.Id)
.ToList();
// Get currencies
var currencies = Currency.GetAll();
var usdCurrency = currencies.FirstOrDefault(c => c.Code == "USD");
// Get languages
var languages = Language.GetAll();
// Get timezones
var timezones = TimeZone.GetAll();
var utc = timezones.FirstOrDefault(tz => tz.Name == "UTC");
Integration with Forms
// In your controller or service
public IActionResult GetCountriesByContinent(int continentId)
{
var countries = Country.GetAll()
.Where(c => c.ContinentId == continentId)
.Select(c => new { c.Id, c.Name })
.ToList();
return Json(countries);
}
// In your view (Blazor, MVC, etc.)
<select id="countrySelect">
<option value="">-- Select Country --</option>
@foreach (var country in Model.Countries)
{
<option value="@country.Id">@country.Name</option>
}
</select>
Extension Methods
Overview
Extension Methods provide globally available utility functions for common operations including string manipulation, enum handling, and reflection. These methods are in the System namespace and automatically available throughout your application.
String Extensions
// Extract controller name from type name
string controllerName = nameof(HomeController).GetControllerName();
// Result: "Home"
string name = "UsersController".GetControllerName();
// Result: "Users"
Enum Extensions
public enum Gender
{
[Display(Name = "Male")]
Male = 1,
[Display(Name = "Female")]
Female = 2
}
// Get display name
string displayName = Gender.Male.GetDisplayName();
// Result: "Male"
// Get enum description
string description = Gender.Male.GetEnumDescription();
// Get all enum values with names as dictionary
var genderOptions = GetEnumValueNames(typeof(Gender));
// Result: { 1: "Male", 2: "Female" }
// Get display group (if applicable)
string group = Gender.Male.GetDisplayGroup();
Enum Helper Example
public class FormHelper
{
public static Dictionary<int, string> GetSelectOptions(Type enumType)
{
return GetEnumValueNames(enumType);
}
}
// In view
<select>
@foreach (var option in FormHelper.GetSelectOptions(typeof(Gender)))
{
<option value="@option.Key">@option.Value</option>
}
</select>
Installation & Setup
NuGet Package
Install-Package PortiaNet.Helper
Target Frameworks
- .NET 5.0
- .NET 6.0
- .NET 8.0
- .NET 9.0
- .NET Standard 2.0
Support & Troubleshooting
Common Issues
Q: Encryption key must be 32 characters
A: The AES-128 encryption requires a key of exactly 32 characters. Generate a secure key or use new EncryptionDecryptionConfig { Key = "your-32-character-key-here!!!!" }.
Q: Why is my audit log empty?
A: Ensure you're calling SaveChangesAsync(userId) or SaveChanges(userId) with a valid user ID. Non-audited entities or unchanged records won't appear in the log.
Q: How do I paginate async operations?
A: Use GetPaginationAsync() with async delegates for filter, sort, and mapping operations.
Best Practices
- Security: Always use 32-character encryption keys; rotate regularly
- Performance: Use pagination for large datasets; include only necessary fields in mappings
- Auditing: Always provide user context when saving changes
- Validation: Validate image quality before processing cards; check confidence scores
- Error Handling: Wrap encryption/decryption operations in try-catch blocks
License
This project is licensed under the MIT License. See LICENSE.txt for details.
Contributing
Contributions are welcome! Please follow our coding standards and include unit tests for new features.
| 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
- Microsoft.AspNetCore.Identity.EntityFrameworkCore (>= 9.0.5)
- Microsoft.EntityFrameworkCore (>= 9.0.5)
- Microsoft.ML.OnnxRuntime (>= 1.22.0)
- Newtonsoft.Json (>= 13.0.3)
- System.Drawing.Common (>= 9.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.1.1 | 101 | 4/30/2026 |
| 2.1.0 | 102 | 4/27/2026 |
| 1.6.0 | 305 | 3/30/2025 |
| 1.5.0 | 405 | 3/23/2025 |
| 1.4.4 | 382 | 10/9/2023 |
| 1.4.3 | 248 | 10/8/2023 |
| 1.4.2 | 236 | 9/29/2023 |
| 1.4.1 | 251 | 9/27/2023 |
| 1.4.0 | 250 | 9/21/2023 |
| 1.3.1 | 467 | 2/17/2023 |
| 1.3.0 | 394 | 2/15/2023 |
| 1.2.0 | 459 | 1/2/2023 |
| 1.1.0 | 441 | 12/26/2022 |
| 1.0.3 | 480 | 12/5/2022 |
| 1.0.2 | 503 | 12/3/2022 |
| 1.0.1 | 489 | 12/3/2022 |
| 1.0.0 | 483 | 12/3/2022 |