Releases: quyvu01/OfX
Release list
OfX v8.1.0 Release Note
Release Notes - OfX v8.1.0
Overview
Version 8.1.0 introduces significant enhancements to the Expression DSL, bringing powerful new capabilities for data projection, filtering, and aggregation. This release focuses on making the Expression language more expressive and flexible.
New Features
1. Root Projection with Navigation & Alias Support
Project specific fields directly from the root object with support for navigation paths and custom aliases.
Syntax: {Property1, Property2, Navigation.Property as Alias}
// Before: Had to create separate expressions for each field
[ProvinceOf(nameof(ProvinceId), Expression = "Name")]
public string ProvinceName { get; set; }
[ProvinceOf(nameof(ProvinceId), Expression = "Country.Name")]
public string CountryName { get; set; }
// After: Single expression with aliases
[ProvinceOf(nameof(ProvinceId), Expression = "{Id, Name, Country.Name as CountryName}")]
public ProvinceComplexResponse ProvinceData { get; set; }Features:
- Simple properties:
{Id, Name} - Navigation properties:
{Id, Country.Name}(output key is last segment "Name") - Aliased properties:
{Id, Country.Name as CountryName}(output key is "CountryName") - Deep navigation:
{Id, Province.City.District.Name as DistrictName}
2. Single Object Projection
Project specific fields from a single navigation object (not just collections).
Syntax: Navigation.{Property1, Property2}
// Project specific fields from a single object
[ProvinceOf(nameof(ProvinceId), Expression = "Country.{Id, Name}")]
public Dictionary<string, object> CountryInfo { get; set; }Output:
{
"Id": "country_123",
"Name": "Vietnam"
}3. Collection Projection Enhancements
Project specific fields from collection items with filter support.
// Basic collection projection
[UserOf(nameof(UserId), Expression = "Orders.{Id, Status}")]
public List<Dictionary<string, object>> OrderSummaries { get; set; }
// With filter
[UserOf(nameof(UserId), Expression = "Orders(Status = 'Done').{Id, Total}")]
public List<Dictionary<string, object>> CompletedOrderSummaries { get; set; }4. New as Keyword for Aliasing
The as keyword allows renaming output fields in projections.
// Rename navigation property output
Expression = "{Country.Name as CountryName}"
// Multiple aliases
Expression = "{Id, Address.City.Name as CityName, Department.Manager.Name as ManagerName}"Improvements
Enhanced Expression DSL Grammar
Updated grammar now supports:
Expression := RootProjection | Segment ('.' Segment)*
RootProjection := '{' ProjectionProperty (',' ProjectionProperty)* '}'
ProjectionProperty := PropertyPath ('as' Identifier)?
PropertyPath := Identifier ('.' Identifier)*
MongoDB Support
Full MongoDB support for all new projection features:
- Root projection with aliases generates proper BSON projection documents
- Single object projection uses
$getFieldfor field extraction - Collection projection uses
$mapfor array transformations
Example MongoDB output for {Id, Name, Country.Name as CountryName}:
{
"Id": "$Id",
"Name": "$Name",
"CountryName": "$Country.Name"
}LINQ Expression Builder
- New
BuildPropertyPathmethod for handling navigation in projections - Projections now return
Dictionary<string, object>for proper JSON serialization - Collection projections return
IEnumerable<Dictionary<string, object>>
TokenType.As
New token type added for the as keyword in expressions.
Examples
Complete Example: User with Province Data
public sealed class UserResponse
{
public string Id { get; set; }
public string UserEmail { get; set; }
public string ProvinceId { get; set; }
[ProvinceOf(nameof(ProvinceId), Expression = "{Id, Name, Country.Name as CountryName}")]
public ProvinceComplexResponse ProvinceResponse { get; set; }
}
public class ProvinceComplexResponse
{
public Guid Id { get; set; }
public string Name { get; set; }
public string CountryName { get; set; } // Mapped from Country.Name
}Combining Features
// Filter + Sort + Take + Navigate + Project
[CountryOf(nameof(CountryId),
Expression = "Provinces(Population > 1000000)[0 desc Population].{Id, Name, Capital.Name as CapitalName}")]
public Dictionary<string, object> LargestProvinceInfo { get; set; }Testing
All new features are covered by unit tests:
ExpressionParserTests- parsing of root projection with navigation and aliasesBsonProjectionBuilderTests- MongoDB projection document generationProjectionBuilderTests- LINQ expression building for EF Core
Upgrade Guide
- Update all OfX packages to version 8.1.0
- If you have custom code accessing
RootProjectionNode.Properties, update to useProjectionPropertytype - Take advantage of new alias syntax to simplify your DTOs
What's Next
- Support for aliases in collection projection
.{Id, Name as ItemName} - Conditional projection based on runtime parameters
- Nested projection support
{Id, Orders.{Id, Status}}
Full Changelog: v7.2.0...v8.1.0
OfX v7.2.0
This release introduces a major enhancement to Expression handling, improved GraphQL integration, and various optimizations. It also marks the first beta support for passing parameters into GraphQL and MapDataAsync.
Sample:
Expression = ${someIndex|0}
- someIndex is resolved dynamically.
- 0 is the fallback default value when the parameter is missing.
This feature is now fully supported in MapDataAsync and works consistently across the mapping engine.
GraphQL Parameters
Sample:
public List<MemberResponse> GetMembers([Parameters] GetMembersParameters parameters)
{
return
[
.. Enumerable.Range(1, 3).Select(a => new MemberResponse
{
Id = a.ToString(),
UserId = a.ToString(), MemberAdditionalId = a.ToString(),
MemberSocialId = a.ToString(),
MemberAddressId = a.ToString()
})
];
}{
members(parameters: { userAlias: "Name", take: 2, skip: 1 })
{
userName
userEmail
provinces {
id
name
}
}
}
We just need to use [Parameters] attribute to indicate the parameters for GraphQl method.
MapDataAsync Parameters
Sample:
Task MapDataAsync(object value, object parameters = null, CancellationToken token = default);The parameters will be passed to all [OfXAttribute]
i.e:
[UserOf(nameof(UserId), Expression = "${UserAlias|Email}")]
public string UserEmail { get; set; }
//...
[CountryOf(nameof(CountryId), Expression = "Provinces[${Skip|0} ${Take|1} asc Name]")]
public List<ProvinceResponse> Provinces { get; set; }This is one of the biggest enhancements to OfX expressions to date.
Full Changelog: v7.1.8...v7.2.0
v7.1.8
π OfX.Azure.ServiceBus β Release Note v7.1.8
Release Date: October 15, 2025
Package: OfX-Azure.ServiceBus
NuGet: OfX-Azure.ServiceBus
β¨ Summary
This release introduces v7.1.8 of OfX.Azure.ServiceBus, focusing on improved configuration flexibility, session management support, and enhanced developer experience for distributed OfX-based systems using Azure Service Bus.
Document:OfX.Azure.ServiceBus
OfX v7.1.6
π OfX v7.1.6 Release Notes
New Features
- Added
SetRetryPolicyconfiguration
Introduced a new configuration method to define retry behavior for transient or recoverable operations during the mapping or data-handling process.
cfg.SetRetryPolicy(3, retryAttempt => retryAttempt * TimeSpan.FromSeconds(2),
(e, ts) => Console.WriteLine($"Error: {e.Message}"));This function configures the retry mechanism for transient or recoverable operations during the mapping or data-handling process.
- maxRetryCount (
3in this example): The maximum number of retry attempts before the operation is considered failed. - retryDelayProvider (
retryAttempt => retryAttempt * TimeSpan.FromSeconds(2)): A function that determines the waiting time before each retry. Here, it uses an exponential backoff patternβeach retry waits longer than the last (e.g., 2s, 4s, 6sβ¦). - onRetry (
(e, ts) => Console.WriteLine($"Error: {e.Message}")): A callback triggered whenever a retry occurs, useful for logging or monitoring.
By default, OfX executes operations without retrying on failure. Using SetRetryPolicy helps improve resilience when dealing with unstable external dependencies, ensuring temporary issues don't cause the entire mapping process to fail.
OfX v7.1.5
π OfX v7.1.5 Release Notes
π§ Improvements
- ExpressionHelpers / ExpressionQueryableData updated for better maintainability and performance.
- Added IdToStringMemberAssignment to
QueryHandlerBuilder(non-thread-safe, but acceptable for this use case). - Improved documentation: updated comments for BuildFilter and BuildResponse.
- File renaming for clearer, more meaningful naming conventions.
π οΈ Fixes
- Removed
defaultReceivedHandlerand added a runtime check for ambiguous Received handlers (now detects if a single attribute is configured for multiple models more than once). - Fixed a RabbitMQ bug where
SslOptioncould benullwhen initializing the client.
β‘ Enhancements
- EfQueryHandler<,>: updated
ImplementFactoryto support caching for improved efficiency.
This version focuses on cleaner abstractions, improved caching, and stronger runtime validation to make OfX more robust and easier to extend.
Update document for OfX. Enhance security
On this version. All the abstraction layer has been added the comment.
Further, I've update the code to make them cleaner!
OfX v7.1.0 is released
π’ OfX Release Notes
π What's New
This update brings significant improvements across core modules, installers, and common utilities β making OfX more powerful, readable, and extensible.
πΉ Installer Improvements
- Updated installers for OfX, OfX.EFCore, and OfX.MongoDb.
- Benefits:
- More memory efficient
- Easier to maintain and extend in future development
πΉ Common Functions Refactoring
- Moved common utilities (e.g., Expression Builder functions like
BuildFilter,BuildResponse) into the OfX core. - This paves the way for upcoming Expression-evaluate features.
π‘ Summary
OfX has been refined for performance, flexibility, and future scalability β empowering developers with a cleaner, more robust foundation for building distributed data mapping solutions.
Fix bug for custom expression behavior
On this version.
The CustomExpressionBehavior pipelines are fixed.
Previously, the CustomExpressionBehavior is added by IServiceCollection.TryAdd.
We should use Add instead of TryAdd.
Fix ReceivedPipelineOrchestrator to handle CustomExpressionBehavior for multiple Expression
CustomExpressionBehaviors-DynamicExpression
π¦ OfX Release Notes β v7.0.4 (2025-08-04)
β¨ New Features
Custom Expression Behaviors
- Introduced a new extension point:
CustomExpressionBehaviors. - Enables custom handling of expressions for advanced use cases such as:
- Aggregations
- External data fetching
- Specialized transformation logic
- Adds flexibility and extensibility to expression processing in OfX pipelines.
DynamicExpresso Integration
- OfX now integrates DynamicExpresso as a new
DynamicExpressionengine. - A powerful step forward to support more dynamic and configurable scenarios in future versions.
π Improvements
Code Quality Enhancements
- General code formatting and cleanup for improved readability.
- Added inline comments throughout the codebase for better maintainability and clarification.
OfX 7.0.3 - Transportation security options
π© OfX 7.0.3 - Release Notes
Release Date: 2025-07-06
β¨ Highlights
This release focuses on enhancing the security of distributed messaging by introducing configurable support for SSL/TLS across multiple connectors. It improves deployment flexibility in secure environments and supports compliance with enterprise-grade standards.
π New Features
OfX-Nats
- Added support for TLS/SSL connections.
- New options to configure certificate files and secure context.
OfX-RabbitMQ
- TLS options now available for AMQP connections.
- Added configuration for client certificate authentication and secure port support.
OfX-Kafka
- Enabled full SSL configuration, including:
SslKeyLocation,SslKeyPasswordSslCertificateLocation,SslCaLocationSslSigalgsList,SslCipherSuites,SslCurvesList
π§ Improvements
- Refined connection configuration schema for better consistency across message broker modules.
- Improved validation for SSL-related settings at startup.
π Security
- Messaging modules (Nats, RabbitMQ, Kafka) now support encrypted connections to ensure data confidentiality and integrity.
- Secure-by-default behavior can be toggled with explicit configuration for development or testing environments.
π¦ Package Updates
- All packages updated to maintain compatibility with the new security features.
- Minor dependency bumps across components.