Releases: TRA-Tech/dotnet-api-commons
Releases · TRA-Tech/dotnet-api-commons
v2.0.0
Changelog
All notable changes to this project are documented here.
Format follows Keep a Changelog.
[2.0.0] — 2026-04-01
Breaking Changes
- Target framework upgraded from
net8.0tonet10.0. Consuming projects must target .NET 10. Response<T>removed. UseResult<TValue, Error>.ToActionResult()orMatchfor custom response shapes.BaseControllerremoved. Remove inheritance; use theToActionResult()extension method directly.GlobalErrorHandlerMiddlewarereplaced byIExceptionHandler-basedGlobalExceptionHandler. Register withAddExceptionHandler<T>()andapp.UseExceptionHandler().DbTransactionMiddlewareexception-handler overload removed. TheFunc<IServiceProvider, HttpContext, Exception, Task>constructor parameter no longer exists. UseIExceptionHandlerfor exception handling.PagedRequest.CurrentPage(1-based) renamed toPageIndex(0-based). Aligns with TanStack Table's server-side pagination contract.Skipcalculation updated accordingly.StringExtensionsdeleted. Methods usedConvert.*which has inconsistent null vs invalid-input behavior. Useint.TryParse,decimal.TryParseetc. directly.DoubleExtensionsdeleted.ToInt(this double)wraps a singleConvert.ToInt32call with no added value. Use(int)xorConvert.ToInt32(x)directly.ObjectExtensions.ToJson()removed. LeakedNewtonsoft.Jsontypes into caller APIs. UseSystem.Text.Json.JsonSerializer.Serialize(obj)directly.DateTimeExtensions.DateNow()removed. Hardcoded UTC+3 offset makes it unsuitable as a general-purpose utility. UseTimeZoneInfo.ConvertTime()explicitly.IsWeekday(),IsWeekend(), andToDateOnly()are retained.QueryableExtensions.ToHashSetAsync()removed. EF Core 10 provides a native asyncToHashSetAsync().Newtonsoft.Jsonpackage reference removed. The library now usesSystem.Text.Jsonexclusively.
Added
Result<TValue, TError>discriminated union withMatch,MatchAsync,Handle,HandleAsync,Map,Tap,Bind, andGetValueOrDefault.Result<TValue>shorthand type (equivalent toResult<TValue, Error>) for application code that always uses the library's error hierarchy.- Error hierarchy —
abstract record Errorwith concrete subtypes:NotFoundError,AlreadyExistsError,ConflictError,UnauthorizedError,ForbiddenError. Each carries contextual properties via positional constructor and owns its HTTP representation through virtualStatusCode,Detail, andCodeproperties. Subclass any type to add domain-specific context or override HTTP semantics without modifying library code. Unitstruct for void operations (Result<Unit, Error>).ResultExtensions—ToActionResult(),ToActionResult(int statusCode),ToActionResultAsync(), and the full async pipeline (BindAsync,Map,TapTask overloads). Error-to-HTTP mapping readsStatusCode,Detail, andCodedirectly from the error instance — no switch expression, extensible without library changes.GlobalExceptionHandler— defaultIExceptionHandlerimplementation that logs unhandled exceptions and returns a 500 ProblemDetails response.SortColumnrecord — mirrors TanStack Table's{ id, desc }sort state shape.SortedPagedRequest— extendsPagedRequestwithIReadOnlyList<SortColumn> Sorting. Multi-column sort applied automatically via expression trees + reflection inToPagedAsync.EnumerableExtensions—WhereIf,TakeIf,SkipIfforIEnumerable<T>(mirrorsQueryableExtensions).ConfigurationExtensions.GetRequired— returns a config value or throwsInvalidOperationExceptionwhen the key is missing. Fills the gap left byGetRequiredSection(sections only).HashExtensions.ToMd5— hashes a string to a lowercase MD5 hex string using UTF-8. For non-security use (cache keys, checksums, ETags).ClaimsPrincipalExtensions—GetId<T>,GetRequiredId<T>,GetEmail. UsesIParsable<T>constraint so callers choose the ID type (int,Guid,long, etc.) without separate overloads.BrotliHelper— static helper withCompress/Decompressoverloads forbyte[]andstring(UTF-8 + Base64 for string form).QueryableExtensions.WhereIf,TakeIf,SkipIfalready existed;ToPagedAsync(SortedPagedRequest)overload is new.ApiCommons.Testsproject — xUnit + FluentAssertions + coverlet test suite covering all phases.
Changed
DbTransactionMiddlewareupdated to primary constructor syntax (C# 13).QueryableExtensions.ToPagedAsyncverified compatible with EF Core 10.Microsoft.EntityFrameworkCoreupdated from8.0.22to10.0.4.
Migration Guide — v1.x → v2.x
| # | What changed | Action required |
|---|---|---|
| 1 | net8.0 no longer targeted |
Upgrade consuming projects to .NET 10 |
| 2 | BaseController removed |
Remove inheritance; use ToActionResult() extension instead |
| 3 | Response<T> removed |
Use Result<TValue, Error>.ToActionResult() or Match for custom shapes |
| 4 | GlobalErrorHandlerMiddleware replaced |
Use AddGlobalExceptionHandler<T>() + UseGlobalErrorHandler(), or register IExceptionHandler manually |
| 5 | DbTransactionMiddleware error-handler overload removed |
Use IExceptionHandler for global exception handling |
| 6 | PagedRequest.CurrentPage (1-based) → PageIndex (0-based) |
Update all usages; aligns with TanStack Table server-side pagination |
| 7 | ObjectExtensions.ToJson() removed |
Use JsonSerializer.Serialize(obj) directly |
| 8 | DateTimeExtensions.DateNow() removed |
Use TimeZoneInfo.ConvertTime() explicitly |
| 9 | StringExtensions removed |
Use int.TryParse, decimal.TryParse etc. directly |
| 10 | DoubleExtensions.ToInt() removed |
Use (int)x or Convert.ToInt32(x) directly |
| 11 | QueryableExtensions.ToHashSetAsync() removed |
Use EF Core 10's built-in .ToHashSetAsync() |
| 12 | Newtonsoft.Json dependency removed |
Use System.Text.Json exclusively |
Before / After:
// v1 — error handling
app.UseGlobalErrorHandler(async (sp, ctx, ex) =>
{
ctx.Response.StatusCode = 500;
await ctx.Response.WriteAsync(Response<object>.Fail(...).ToJson());
});
// v2
builder.Services.AddGlobalExceptionHandler<MyExceptionHandler>();
app.UseGlobalErrorHandler();// v1 — controller response
Response<string> response = result.Match(s => s, e => string.Empty);
return response.ToActionResult();
// v2
return await _service.GetAsync(id, ct).ToActionResultAsync();// v1 — pagination (1-based)
var req = new PagedRequest(currentPage: 1, pageSize: 20);
// v2 — pagination (0-based, aligns with TanStack Table)
var req = new PagedRequest(pageIndex: 0, pageSize: 20);[1.1.0] — prior
- Initial release targeting .NET 8.