Skip to content

Releases: quyvu01/OfX

OfX v8.1.0 Release Note

Choose a tag to compare

@quyvu01 quyvu01 released this 11 Jan 11:14

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 $getField for field extraction
  • Collection projection uses $map for array transformations

Example MongoDB output for {Id, Name, Country.Name as CountryName}:

{
  "Id": "$Id",
  "Name": "$Name",
  "CountryName": "$Country.Name"
}

LINQ Expression Builder

  • New BuildPropertyPath method 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 aliases
  • BsonProjectionBuilderTests - MongoDB projection document generation
  • ProjectionBuilderTests - LINQ expression building for EF Core

Upgrade Guide

  1. Update all OfX packages to version 8.1.0
  2. If you have custom code accessing RootProjectionNode.Properties, update to use ProjectionProperty type
  3. 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

Choose a tag to compare

@quyvu01 quyvu01 released this 18 Nov 16:38

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

Choose a tag to compare

@quyvu01 quyvu01 released this 16 Oct 02:49

πŸš€ 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

Choose a tag to compare

@quyvu01 quyvu01 released this 07 Oct 09:59

πŸš€ OfX v7.1.6 Release Notes

New Features

  • Added SetRetryPolicy configuration

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 (3 in 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

Choose a tag to compare

@quyvu01 quyvu01 released this 05 Oct 02:31

πŸš€ 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 defaultReceivedHandler and 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 SslOption could be null when initializing the client.

⚑ Enhancements

  • EfQueryHandler<,>: updated ImplementFactory to 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

Choose a tag to compare

@quyvu01 quyvu01 released this 23 Sep 06:11

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

Choose a tag to compare

@quyvu01 quyvu01 released this 13 Aug 15:30

πŸ“’ 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

Choose a tag to compare

@quyvu01 quyvu01 released this 07 Aug 04:43

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

Choose a tag to compare

@quyvu01 quyvu01 released this 04 Aug 08:38

πŸ“¦ 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 DynamicExpression engine.
  • 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

Choose a tag to compare

@quyvu01 quyvu01 released this 06 Jul 14:02

🟩 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, SslKeyPassword
    • SslCertificateLocation, SslCaLocation
    • SslSigalgsList, 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.