From 599204d85848a2b504322e9292a45ccab68245eb Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brule Date: Thu, 25 Dec 2025 11:47:56 -0500 Subject: [PATCH] fix: use InvariantCulture for decimal/DateTime parsing in gRPC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The generated gRPC service code was using locale-dependent parsing for decimal and DateTime values. On French locale systems, this caused FormatException when parsing "0.95" because the system expected a comma as decimal separator. Now uses CultureInfo.InvariantCulture for all decimal.Parse() and DateTime.Parse() calls to ensure consistent behavior across locales. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs b/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs index 62247a5..71b4b27 100644 --- a/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs +++ b/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs @@ -627,11 +627,11 @@ namespace Svrnty.CQRS.Grpc.Generators { if (prop.IsNullable) { - return $"{indent}{prop.Name} = string.IsNullOrEmpty({source}) ? null : decimal.Parse({source}),"; + return $"{indent}{prop.Name} = string.IsNullOrEmpty({source}) ? null : decimal.Parse({source}, System.Globalization.CultureInfo.InvariantCulture),"; } else { - return $"{indent}{prop.Name} = decimal.Parse({source}),"; + return $"{indent}{prop.Name} = decimal.Parse({source}, System.Globalization.CultureInfo.InvariantCulture),"; } } @@ -707,11 +707,11 @@ namespace Svrnty.CQRS.Grpc.Generators { if (prop.IsNullable) { - return $"{indent}{prop.Name} = string.IsNullOrEmpty({source}) ? null : decimal.Parse({source}),"; + return $"{indent}{prop.Name} = string.IsNullOrEmpty({source}) ? null : decimal.Parse({source}, System.Globalization.CultureInfo.InvariantCulture),"; } else { - return $"{indent}{prop.Name} = decimal.Parse({source}),"; + return $"{indent}{prop.Name} = decimal.Parse({source}, System.Globalization.CultureInfo.InvariantCulture),"; } } @@ -1990,16 +1990,16 @@ namespace Svrnty.CQRS.Grpc.Generators if (prop.IsDecimal) { if (prop.IsNullable) - return $"string.IsNullOrEmpty({accessor}) ? null : decimal.Parse({accessor})"; - return $"decimal.Parse({accessor})"; + return $"string.IsNullOrEmpty({accessor}) ? null : decimal.Parse({accessor}, System.Globalization.CultureInfo.InvariantCulture)"; + return $"decimal.Parse({accessor}, System.Globalization.CultureInfo.InvariantCulture)"; } // Handle string → DateTime conversion (proto uses string for DateTime) if (prop.IsDateTime) { if (prop.IsNullable) - return $"string.IsNullOrEmpty({accessor}) ? null : global::System.DateTime.Parse({accessor})"; - return $"global::System.DateTime.Parse({accessor})"; + return $"string.IsNullOrEmpty({accessor}) ? null : global::System.DateTime.Parse({accessor}, System.Globalization.CultureInfo.InvariantCulture)"; + return $"global::System.DateTime.Parse({accessor}, System.Globalization.CultureInfo.InvariantCulture)"; } // Handle proto enum → domain enum conversion