RoZ.Api.Core
20265.12.13.18
dotnet add package RoZ.Api.Core --version 20265.12.13.18
NuGet\Install-Package RoZ.Api.Core -Version 20265.12.13.18
<PackageReference Include="RoZ.Api.Core" Version="20265.12.13.18" />
<PackageVersion Include="RoZ.Api.Core" Version="20265.12.13.18" />
<PackageReference Include="RoZ.Api.Core" />
paket add RoZ.Api.Core --version 20265.12.13.18
#r "nuget: RoZ.Api.Core, 20265.12.13.18"
#:package RoZ.Api.Core@20265.12.13.18
#addin nuget:?package=RoZ.Api.Core&version=20265.12.13.18
#tool nuget:?package=RoZ.Api.Core&version=20265.12.13.18
Roz.Api.Core
A reusable ASP.NET Core library providing foundational components for API development, including Entity Framework integration, caching, authentication, authorization, and common utilities.
Installation
Reference this project in your API project. Ensure .NET 10.0+ is targeted.
Table of Contents
- Entities
- EntityFramework
- Exception Handling
- Constants
- Models
- Repositories
- Services
- Settings
- Authorization
- Validation Attributes
- Serilog
Entities
BaseEntity<T>
Base class for entities with a strongly-typed primary key and auditing support.
public class Product : BaseEntity<long> { }
Properties:
Id(T) - Primary key with auto-generationGuid(Guid) - Global unique identifierCreatedBy(Guid?) - Creator's user IDCreatedTime(DateTime) - Creation timestamp (UTC)ModifiedBy(Guid?) - Last modifier's user IDModifiedTime(DateTime) - Last modification timestamp (UTC)
BaseEntityWithSoftDelete<T>
Extends BaseEntity<T> with soft deletion support.
public class Product : BaseEntityWithSoftDelete<long> { }
Additional Properties:
DeletedBy(Guid?) - User who deletedDeletedTime(DateTime?) - Deletion timestampIsDeleted(bool) - Soft delete flag
ISoftDelete
Interface for entities supporting soft deletion.
IModificationAudited<TAudited>
Interface for entities tracking creation/modification audit info.
DefaultUserEntity
Extends IdentityUser<long> with audit and soft delete support. Includes all BaseEntity properties plus ASP.NET Identity properties.
EntityFramework
BaseDbContext<TUser, TRole, TKey>
Base DbContext integrating ASP.NET Core Identity with Entity Framework Core. Configures Npgsql for UTC timestamp handling.
public class AppDbContext : BaseDbContext<DefaultUserEntity, IdentityRole<long>, long>
{
public AppDbContext(DbContextOptions options, IHttpContextAccessor httpContext)
: base(options, httpContext) { }
}
UtcDateTimeConverters
Value converters ensuring all DateTime values are stored/retrieved as UTC.
Usage in entity configuration:
modelBuilder.Entity<Product>()
.Property(p => p.CreatedTime)
.HasConversion(UtcDateTimeConverters.DateTimeToUtc);
SoftDeleteQueryExtension
Adds global query filter for soft-delete functionality:
modelBuilder.Entity<Product>().AddSoftDeleteQueryFilter();
SortableExtension
Extension methods for dynamic sorting on IQueryable.
ApplySorting<T>(data, sortedField, isDescending)
Applies sorting by property name.
var sorted = context.Products.ApplySorting("Name", false);
ApplyVietnameseSorting<T>(data, getFullName, getLastName?)
Vietnamese-aware sorting for names (uses vi-VN culture).
var sorted = people.ApplyVietnameseSorting(p => p.FullName);
GetFieldNameExpression<TEntity>(propertyName)
Creates a delegate to retrieve property values by name for sorting.
QueryableExtensions
Paging extension methods for IQueryable.
Paging<T>(data, pageIndex, pageSize)
Simple pagination using Skip/Take.
var page = context.Products.Paging(2, 10);
Paging<T>(data, pageIndex, pageSize, fieldName, isDescending)
Paginate with sorting. Defaults to CreatedTime or Id.
Paging<T>(data, filterable)
Paginate using a Filterable object.
OrderedPaging<T>(data, pageIndex, pageSize)
Paginate an already-ordered query.
Exception Handling
Custom Exceptions
| Exception | HTTP Status | Usage |
|---|---|---|
BadRequestException |
400 | Invalid input |
UnauthorizedException |
401 | Not authenticated |
ForbiddenException |
403 | Access denied |
NotFoundException |
404 | Resource not found |
CustomException |
500 | Generic application error |
throw new NotFoundException("Product with ID {0} not found", productId);
ExceptionMiddleware
Global exception handler middleware. Catches exceptions, logs them, and converts to standardized API responses.
Registration in Program.cs:
app.UseMiddleware<ExceptionMiddleware>();
Constants
ErrorFeedbackConstants
Vietnamese validation error messages.
ErrorFeedbackConstants.Required // "{0} không được để trống"
ErrorFeedbackConstants.MinLength // "{0} phải có độ dài tối thiểu là {1} ký tự"
ErrorFeedbackConstants.MaxLength
ErrorFeedbackConstants.Regex
ErrorFeedbackConstants.RegexName
ErrorFeedbackConstants.Name
ErrorFeedbackConstants.Password
ErrorFeedbackConstants.NumericRange
ErrorFeedbackConstants.MinItems
RegexConstants
Pre-built regex patterns for validation.
RegexConstants.Email // Email validation
RegexConstants.Password // Requires lower, upper, digit, special char (min 6)
RegexConstants.PhoneNumber
RegexConstants.Name // Unicode letters and spaces
RegexConstants.NameWithDashAndDot
Models
Filterable
Extends Pageable with sorting. Use with repository queries.
var filter = new Filterable(pageIndex: 1, pageSize: 20, "Name", true);
var result = await repo.Query().Paging(filter).ToListAsync();
Properties:
PageIndex(int) - 1-based page indexPageSize(int) - Items per page (default 10)FieldName(string?) - Sort fieldIsDescending(bool?) - Sort directionSortable- ConstructsSortablefrom FieldName/IsDescendingOffset(int) - Calculated:(PageIndex-1)*PageSize
Pageable
Simple pagination parameters.
var paging = new Pageable(pageIndex: 1, pageSize: 10);
Sortable
Sorting parameters.
var sort = new Sortable(fieldName: "CreatedTime", isDescending: true);
ServiceResponse<T>
Paginated response wrapper.
var response = new ServiceResponse<T>(totalCount, filter, data);
Properties:
PageIndex,PageSize,TotalCount,Data,TotalPages
SearchRequest
Base for search requests with keyword.
public class ProductSearch : SearchRequest
{
public string? Category { get; set; }
}
DefaultReponseDto
Simple response with Code and Message.
BaseDto
Base DTO with Guid property.
AppSettings
Application configuration model.
services.Configure<AppSettings>(configuration.GetSection("App"));
Properties:
Id,Name,Origins(CORS),Authentication(JwtSettings),AllowedSwagger,AllowedCaching
JwtSettings
JWT token configuration.
public class JwtSettings {
public string Secret { get; set; }
public string? Issuer { get; set; }
public string? Audience { get; set; }
public int AccessTokenValidityInMinutes { get; set; } = 10;
public int? RefreshTokenValidityInMinutes { get; set; }
}
RedisConfig
Redis connection configuration.
public class RedisConfig {
public List<string> Hosts { get; set; }
public string? Password { get; set; }
public int Database { get; set; }
public bool UseCluster { get; set; }
}
Repositories
IRepository<TEntity, TKey>
Generic repository interface with full CRUD + soft delete support.
Key Methods:
GetAllAsync()- Get all entities (no tracking)FindByIdAsync(TKey id)- Find by primary keyFindByGuidAsync(Guid guid)- Find by Guid propertyAddAsync(entity, autoSave)- Add entityUpdateAsync(entity, autoSave)- Update entityDeleteAsync(entity, autoSave)- Delete entityGetByIdAsync(id, includeDeleted)- Get with optional soft-deletedRestoreByIdAsync(id)- Restore soft-deleted entityPurgeByIdAsync(id)- Hard deleteQuery(tracking, includeDeleted)- Create queryAnyAsync(predicate)- Check existence
BaseRepository<TEntity, TKey, TContext>
Abstract implementation of IRepository. Extend in your application:
public class ProductRepository : BaseRepository<Product, long, AppDbContext>
{
public ProductRepository(AppDbContext context) : base(context) { }
}
Services
JwtService
JWT token generation and AES encryption/decryption.
var service = new JwtService(jwtSettings);
// Generate token
var token = service.GenerateToken(new Dictionary<string, object>
{
["Guid"] = userGuid,
["Region"] = "ADMIN"
});
// Encrypt/decrypt data
var encrypted = service.Encrypt(plainText);
var decrypted = service.Decrypt(cipherText);
IdentityService
Service for extracting user identity information from JWT tokens.
// Get current user GUID
var userGuid = await identityService.GetCurrentUserGuid();
// Check region access
var hasRegion = await identityService.IsHaveRegion("ADMIN");
// Check module access
var accessResult = await identityService.IsHaveAccess("Product");
IAppCache / Implementations
Caching abstraction with multiple backing stores.
Implementations:
NoCacheAppCache- Disabled caching (no-op)MemoryAppCache-IMemoryCachebackingRedisAppCache- Redis backing
// Get or create
var data = await cache.GetOrCreateAsync("key", () => FetchData(), TimeSpan.FromMinutes(5));
// Set directly
await cache.SetAsync("key", data, TimeSpan.FromMinutes(5));
// Remove
await cache.RemoveAsync("key");
IRedisCacheService
Redis-specific cache operations.
await redis.SetAsync("key", value, TimeSpan.FromDays(1));
var (found, value) = await redis.TryGetValue<T>("key");
await redis.RemoveAsync("key");
await redis.ExistsAsync("key");
var keys = await redis.GetAllKeysAsync("user:*");
IRedisKeyManager
Builds consistent cache keys with optional tenant scoping.
var key = keyManager.BuildKey("products", "123"); // "products:123"
var tenantKey = keyManager.BuildTenantKey("tenant1", "cache", "key", encrypt: true);
ServiceBase<T> / ServiceBaseWithMapper<T>
Base classes for application services.
public class ProductService : ServiceBaseWithMapper<ProductService>
{
public ProductService(ILogger<ProductService> logger, IMapper mapper)
: base(logger, mapper) { }
}
BaseSignalRService
Base class for SignalR hubs with [Authorize] by default.
public class NotificationHub : BaseSignalRService
{
public NotificationHub(ILogger<NotificationHub> logger) : base(logger) { }
}
Settings
DefaultSetting
Extension methods for configuring MVC, CORS, Swagger, JWT authentication, and hybrid cache.
// In Program.cs
services.AddDefaultConfigures(configuration, environment, "App", "Redis", null, "ADMIN");
app.UseDefaultConfigures(configuration, logging, "App", "ADMIN");
CacheSetting
Hybrid cache configuration. Automatically chooses Redis or in-memory based on configuration.
// Register cached service proxy
services.AddCachedService<IProductService, ProductService>();
Authorization
CustomAuthorizeAttribute
Authorization filter attribute for controllers/actions.
[CustomAuthorize(Region = "ADMIN", Access = "Product:3")]
public class ProductController : ControllerBase<ProductController>
{
}
CustomAuthorizeRequirement
Authorization requirement with Region and Access.
CustomAuthorizationHandler
Authorization handler validating encrypted Region/Access JWT claims.
CustomAuthorizationPolicyProvider
Policy provider for dynamic "CustomAuthorize" policies.
StaticFunction
Utility for authorization.
// Generate module access string with bitwise flags
var access = StaticFunction.GetModuleAccess("Product", ModuleInteractionEnum.Read, ModuleInteractionEnum.Create);
// Returns: "Product:3"
// Generate random string
var random = StaticFunction.GenerateString(16);
ModuleInteractionEnum / ModuleInteraction
Bitwise interaction flags for module permissions.
[Flags]
public enum ModuleInteractionEnum : int
{
None = 0,
Read = 1, // 1 << 0
Create = 2, // 1 << 1
Update = 4, // 1 << 2
Delete = 8 // 1 << 3
}
Validation Attributes
RequiredIfOtherHasValueAttribute
Makes a property required when another property has a value.
public class Dto
{
public string? AlternativeEmail { get; set; }
[RequiredIfOtherHasValue("AlternativeEmail")]
[EmailAddress]
public string? PrimaryEmail { get; set; }
}
RequiredIfOtherIsEmptyAttribute
Makes a property required when another property is empty.
public class Dto
{
public string? ReferenceCode { get; set; }
[RequiredIfOtherIsEmpty("ReferenceCode")]
public string? Name { get; set; }
}
MinItemsAttribute
Validates minimum item count in collections.
[MinItems(1)]
public List<string> Categories { get; set; }
NumericRangeAttribute
Validates numeric values within a range.
[NumericRange(0, 100)]
public int Percentage { get; set; }
Serilog
ClickHouseFormatter
Serilog text formatter outputting JSON for ClickHouse.
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new ClickHouseFormatter())
.CreateLogger();
Complete Setup Example
// Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDefaultConfigures(
builder.Configuration,
builder.Environment,
"App",
"Redis",
null,
"ADMIN");
var app = builder.Build();
app.UseDefaultConfigures(
app.Configuration,
app.Logging,
"App",
"ADMIN");
app.MapControllers();
app.Run();
appsettings.json Example
{
"App": {
"Name": "MyApp",
"Origins": ["http://localhost:3000"],
"Authentication": {
"Secret": "your-256-bit-secret-key-here-minimum-32-chars",
"Issuer": "MyApp",
"Audience": "MyApp",
"AccessTokenValidityInMinutes": 60
},
"AllowedSwagger": true,
"AllowedCaching": true
},
"Redis": {
"Hosts": ["localhost:6379"],
"Database": 0,
"UseCluster": false
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- AutoWrapper.Core (>= 4.5.1)
- Hangfire (>= 1.8.23)
- Hangfire.AspNetCore (>= 1.8.23)
- Hangfire.Core (>= 1.8.23)
- Hangfire.Dashboard.Basic.Authentication (>= 8.0.0)
- Hangfire.PostgreSql (>= 1.21.1)
- Mapster (>= 10.0.7)
- Mapster.DependencyInjection (>= 10.0.7)
- Microsoft.AspNetCore.Authentication.JwtBearer (>= 10.0.5)
- Microsoft.AspNetCore.Http.Abstractions (>= 2.3.9)
- Microsoft.AspNetCore.Identity.EntityFrameworkCore (>= 10.0.5)
- Microsoft.AspNetCore.Mvc.Core (>= 2.3.9)
- Microsoft.AspNetCore.Mvc.NewtonsoftJson (>= 10.0.5)
- Microsoft.AspNetCore.SignalR.Common (>= 10.0.7)
- Microsoft.AspNetCore.SignalR.Core (>= 1.2.9)
- Microsoft.AspNetCore.SignalR.Protocols.Json (>= 10.0.7)
- Microsoft.EntityFrameworkCore (>= 10.0.5)
- Microsoft.Extensions.Caching.StackExchangeRedis (>= 10.0.5)
- Microsoft.Extensions.Identity.Stores (>= 10.0.5)
- Microsoft.IdentityModel.Tokens (>= 8.17.0)
- Minio (>= 6.0.4)
- Newtonsoft.Json (>= 13.0.4)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 10.0.1)
- Scrutor (>= 7.0.0)
- Serilog.AspNetCore (>= 10.0.0)
- Serilog.Sinks.Http (>= 9.2.1)
- StackExchange.Redis (>= 2.12.14)
- Swashbuckle.AspNetCore (>= 10.1.7)
- Swashbuckle.AspNetCore.SwaggerGen (>= 10.1.7)
- Swashbuckle.AspNetCore.SwaggerUI (>= 10.1.7)
- System.IdentityModel.Tokens.Jwt (>= 8.17.0)
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 |
|---|---|---|
| 20265.12.13.18 | 74 | 5/12/2026 |
| 20265.11.14.16 | 88 | 5/11/2026 |
| 20265.11.10.43 | 89 | 5/11/2026 |
| 20265.11.10.26 | 80 | 5/11/2026 |
| 20265.8.13.55 | 103 | 5/8/2026 |
| 20265.8.13.37 | 84 | 5/8/2026 |
| 20265.7.23.18 | 89 | 5/7/2026 |
| 20265.6.20.57 | 89 | 5/6/2026 |
| 20265.5.16.43 | 84 | 5/5/2026 |
| 20265.5.16.40 | 67 | 5/5/2026 |
| 20265.5.16.30 | 73 | 5/5/2026 |
| 20265.5.16.27 | 86 | 5/5/2026 |
| 20265.4.11.24 | 96 | 5/4/2026 |
| 20265.4.11.12 | 82 | 5/4/2026 |
| 20265.4.10.58 | 83 | 5/4/2026 |
| 20264.28.14.4 | 88 | 4/28/2026 |
| 20264.28.10.8 | 82 | 4/28/2026 |
| 20264.28.10 | 91 | 4/28/2026 |
| 20264.28.9.51 | 90 | 4/28/2026 |