From 7f9d4c58f43e9b678732d2810ef6149ec792cd7c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 28 Nov 2025 18:48:04 +0000
Subject: [PATCH 1/5] Initial plan
From 567c723d6d696c924aa182c7c8452a1455ecbd6b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 28 Nov 2025 18:55:44 +0000
Subject: [PATCH 2/5] Use CultureInfo.InvariantCulture for IFormattable types
in AddParameter methods
Co-authored-by: alexeyzimarev <2821205+alexeyzimarev@users.noreply.github.com>
---
src/RestSharp/Extensions/ObjectExtensions.cs | 31 +++
src/RestSharp/Parameters/ObjectParser.cs | 4 +-
src/RestSharp/Parameters/Parameter.cs | 9 +-
.../Request/RestRequestExtensions.Query.cs | 4 +-
.../Request/RestRequestExtensions.Url.cs | 4 +-
.../Request/RestRequestExtensions.cs | 6 +-
.../InvariantCultureParameterTests.cs | 177 ++++++++++++++++++
7 files changed, 226 insertions(+), 9 deletions(-)
create mode 100644 src/RestSharp/Extensions/ObjectExtensions.cs
create mode 100644 test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
diff --git a/src/RestSharp/Extensions/ObjectExtensions.cs b/src/RestSharp/Extensions/ObjectExtensions.cs
new file mode 100644
index 000000000..15ca49eea
--- /dev/null
+++ b/src/RestSharp/Extensions/ObjectExtensions.cs
@@ -0,0 +1,31 @@
+// Copyright (c) .NET Foundation and Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using System.Globalization;
+
+namespace RestSharp.Extensions;
+
+static class ObjectExtensions {
+ ///
+ /// Converts a value to its string representation using invariant culture for IFormattable types.
+ ///
+ /// The type of value to convert
+ /// The value to convert
+ /// String representation using invariant culture, or null if value is null
+ internal static string? ToStringInvariant(this T value) => value switch {
+ null => null,
+ IFormattable f => f.ToString(null, CultureInfo.InvariantCulture),
+ _ => value.ToString()
+ };
+}
diff --git a/src/RestSharp/Parameters/ObjectParser.cs b/src/RestSharp/Parameters/ObjectParser.cs
index 3f3464d97..1f0f50850 100644
--- a/src/RestSharp/Parameters/ObjectParser.cs
+++ b/src/RestSharp/Parameters/ObjectParser.cs
@@ -13,7 +13,9 @@
// limitations under the License.
//
+using System.Globalization;
using System.Reflection;
+using RestSharp.Extensions;
namespace RestSharp;
@@ -72,7 +74,7 @@ IEnumerable GetArray(PropertyInfo propertyInfo, object? value)
bool IsAllowedProperty(string propertyName)
=> includedProperties.Length == 0 || includedProperties.Length > 0 && includedProperties.Contains(propertyName);
- string? ParseValue(string? format, object? value) => format == null ? value?.ToString() : string.Format($"{{0:{format}}}", value);
+ string? ParseValue(string? format, object? value) => format == null ? value.ToStringInvariant() : string.Format(CultureInfo.InvariantCulture, $"{{0:{format}}}", value);
}
}
diff --git a/src/RestSharp/Parameters/Parameter.cs b/src/RestSharp/Parameters/Parameter.cs
index b23c592dc..cc6f1434a 100644
--- a/src/RestSharp/Parameters/Parameter.cs
+++ b/src/RestSharp/Parameters/Parameter.cs
@@ -13,6 +13,7 @@
// limitations under the License.
using System.Diagnostics;
+using RestSharp.Extensions;
namespace RestSharp;
@@ -76,10 +77,10 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode
public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true)
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
=> type switch {
- ParameterType.GetOrPost => new GetOrPostParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString(), encode),
- ParameterType.UrlSegment => new UrlSegmentParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString()!, encode),
- ParameterType.HttpHeader => new HeaderParameter(name!, value?.ToString()!),
- ParameterType.QueryString => new QueryParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString(), encode),
+ ParameterType.GetOrPost => new GetOrPostParameter(Ensure.NotEmptyString(name, nameof(name)), value.ToStringInvariant(), encode),
+ ParameterType.UrlSegment => new UrlSegmentParameter(Ensure.NotEmptyString(name, nameof(name)), value.ToStringInvariant()!, encode),
+ ParameterType.HttpHeader => new HeaderParameter(name!, value.ToStringInvariant()!),
+ ParameterType.QueryString => new QueryParameter(Ensure.NotEmptyString(name, nameof(name)), value.ToStringInvariant(), encode),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
diff --git a/src/RestSharp/Request/RestRequestExtensions.Query.cs b/src/RestSharp/Request/RestRequestExtensions.Query.cs
index 265dc360d..1ae2f026f 100644
--- a/src/RestSharp/Request/RestRequestExtensions.Query.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.Query.cs
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using RestSharp.Extensions;
+
namespace RestSharp;
public static partial class RestRequestExtensions {
@@ -37,6 +39,6 @@ public RestRequest AddQueryParameter(string name, string? value, bool encode = t
/// Encode the value or not, default true
///
public RestRequest AddQueryParameter(string name, T value, bool encode = true) where T : struct
- => request.AddQueryParameter(name, value.ToString(), encode);
+ => request.AddQueryParameter(name, value.ToStringInvariant(), encode);
}
}
\ No newline at end of file
diff --git a/src/RestSharp/Request/RestRequestExtensions.Url.cs b/src/RestSharp/Request/RestRequestExtensions.Url.cs
index 499c629df..546cc5c56 100644
--- a/src/RestSharp/Request/RestRequestExtensions.Url.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.Url.cs
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using RestSharp.Extensions;
+
namespace RestSharp;
public static partial class RestRequestExtensions {
@@ -37,6 +39,6 @@ public RestRequest AddUrlSegment(string name, string? value, bool encode = true)
/// Encode the value or not, default true
///
public RestRequest AddUrlSegment(string name, T value, bool encode = true) where T : struct
- => request.AddUrlSegment(name, value.ToString(), encode);
+ => request.AddUrlSegment(name, value.ToStringInvariant(), encode);
}
}
\ No newline at end of file
diff --git a/src/RestSharp/Request/RestRequestExtensions.cs b/src/RestSharp/Request/RestRequestExtensions.cs
index 82323d07b..be53a9f0c 100644
--- a/src/RestSharp/Request/RestRequestExtensions.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.cs
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+using RestSharp.Extensions;
+
namespace RestSharp;
[PublicAPI]
@@ -52,7 +54,7 @@ public RestRequest AddParameter(string? name, object value, ParameterType type,
/// Encode the value or not, default true
/// This request
public RestRequest AddParameter(string name, T value, bool encode = true) where T : struct
- => request.AddParameter(name, value.ToString(), encode);
+ => request.AddParameter(name, value.ToStringInvariant(), encode);
///
/// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
@@ -72,7 +74,7 @@ public RestRequest AddOrUpdateParameter(string name, string? value, bool encode
/// Encode the value or not, default true
/// This request
public RestRequest AddOrUpdateParameter(string name, T value, bool encode = true) where T : struct
- => request.AddOrUpdateParameter(name, value.ToString(), encode);
+ => request.AddOrUpdateParameter(name, value.ToStringInvariant(), encode);
RestRequest AddParameters(IEnumerable parameters) {
request.Parameters.AddParameters(parameters);
diff --git a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
new file mode 100644
index 000000000..f5ec68145
--- /dev/null
+++ b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
@@ -0,0 +1,177 @@
+using System.Globalization;
+
+namespace RestSharp.Tests.Parameters;
+
+public class InvariantCultureParameterTests {
+ [Fact]
+ public void AddParameter_Double_UsesInvariantCulture() {
+ // Save original culture
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ // Set a culture that uses comma as decimal separator
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var request = new RestRequest();
+ request.AddParameter("value", 1.234);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddOrUpdateParameter_Double_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var request = new RestRequest();
+ request.AddOrUpdateParameter("value", 1.234);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddQueryParameter_Double_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var request = new RestRequest();
+ request.AddQueryParameter("value", 1.234);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddUrlSegment_Double_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var request = new RestRequest("{value}");
+ request.AddUrlSegment("value", 1.234);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void CreateParameter_Double_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var parameter = Parameter.CreateParameter("value", 1.234, ParameterType.GetOrPost);
+
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddParameter_Decimal_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
+
+ var request = new RestRequest();
+ request.AddParameter("value", 123.456m);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("123.456");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddParameter_Float_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
+
+ var request = new RestRequest();
+ request.AddParameter("value", 2.5f);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("2.5");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddParameter_DateTime_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var dateTime = new DateTime(2024, 12, 25, 10, 30, 0, DateTimeKind.Unspecified);
+ var request = new RestRequest();
+ request.AddParameter("date", dateTime);
+
+ var parameter = request.Parameters.First();
+ // DateTime.ToString with InvariantCulture uses MM/dd/yyyy format
+ parameter.Value.Should().Be("12/25/2024 10:30:00");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddParameter_Integer_WorksWithAnyCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var request = new RestRequest();
+ request.AddParameter("value", 12345);
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("12345");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddObject_WithDoubleProperty_UsesInvariantCulture() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var request = new RestRequest();
+ request.AddObject(new { Amount = 1.234 });
+
+ var parameter = request.Parameters.First();
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+}
From 8059e9b8cb1f888213ac10e72b698280868b5ff0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 29 Nov 2025 23:59:48 +0000
Subject: [PATCH 3/5] Make invariant culture formatting opt-in via new method
overloads
Co-authored-by: alexeyzimarev <2821205+alexeyzimarev@users.noreply.github.com>
---
src/RestSharp/Parameters/ObjectParser.cs | 4 +-
src/RestSharp/Parameters/Parameter.cs | 9 ++-
.../Request/RestRequestExtensions.Query.cs | 15 +++-
.../Request/RestRequestExtensions.Url.cs | 15 +++-
.../Request/RestRequestExtensions.cs | 28 +++++++-
.../InvariantCultureParameterTests.cs | 70 +++++++++----------
6 files changed, 91 insertions(+), 50 deletions(-)
diff --git a/src/RestSharp/Parameters/ObjectParser.cs b/src/RestSharp/Parameters/ObjectParser.cs
index 1f0f50850..3f3464d97 100644
--- a/src/RestSharp/Parameters/ObjectParser.cs
+++ b/src/RestSharp/Parameters/ObjectParser.cs
@@ -13,9 +13,7 @@
// limitations under the License.
//
-using System.Globalization;
using System.Reflection;
-using RestSharp.Extensions;
namespace RestSharp;
@@ -74,7 +72,7 @@ IEnumerable GetArray(PropertyInfo propertyInfo, object? value)
bool IsAllowedProperty(string propertyName)
=> includedProperties.Length == 0 || includedProperties.Length > 0 && includedProperties.Contains(propertyName);
- string? ParseValue(string? format, object? value) => format == null ? value.ToStringInvariant() : string.Format(CultureInfo.InvariantCulture, $"{{0:{format}}}", value);
+ string? ParseValue(string? format, object? value) => format == null ? value?.ToString() : string.Format($"{{0:{format}}}", value);
}
}
diff --git a/src/RestSharp/Parameters/Parameter.cs b/src/RestSharp/Parameters/Parameter.cs
index cc6f1434a..b23c592dc 100644
--- a/src/RestSharp/Parameters/Parameter.cs
+++ b/src/RestSharp/Parameters/Parameter.cs
@@ -13,7 +13,6 @@
// limitations under the License.
using System.Diagnostics;
-using RestSharp.Extensions;
namespace RestSharp;
@@ -77,10 +76,10 @@ protected Parameter(string? name, object? value, ParameterType type, bool encode
public static Parameter CreateParameter(string? name, object? value, ParameterType type, bool encode = true)
// ReSharper disable once SwitchExpressionHandlesSomeKnownEnumValuesWithExceptionInDefault
=> type switch {
- ParameterType.GetOrPost => new GetOrPostParameter(Ensure.NotEmptyString(name, nameof(name)), value.ToStringInvariant(), encode),
- ParameterType.UrlSegment => new UrlSegmentParameter(Ensure.NotEmptyString(name, nameof(name)), value.ToStringInvariant()!, encode),
- ParameterType.HttpHeader => new HeaderParameter(name!, value.ToStringInvariant()!),
- ParameterType.QueryString => new QueryParameter(Ensure.NotEmptyString(name, nameof(name)), value.ToStringInvariant(), encode),
+ ParameterType.GetOrPost => new GetOrPostParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString(), encode),
+ ParameterType.UrlSegment => new UrlSegmentParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString()!, encode),
+ ParameterType.HttpHeader => new HeaderParameter(name!, value?.ToString()!),
+ ParameterType.QueryString => new QueryParameter(Ensure.NotEmptyString(name, nameof(name)), value?.ToString(), encode),
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
};
diff --git a/src/RestSharp/Request/RestRequestExtensions.Query.cs b/src/RestSharp/Request/RestRequestExtensions.Query.cs
index 1ae2f026f..01697ed53 100644
--- a/src/RestSharp/Request/RestRequestExtensions.Query.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.Query.cs
@@ -39,6 +39,19 @@ public RestRequest AddQueryParameter(string name, string? value, bool encode = t
/// Encode the value or not, default true
///
public RestRequest AddQueryParameter(string name, T value, bool encode = true) where T : struct
- => request.AddQueryParameter(name, value.ToStringInvariant(), encode);
+ => request.AddQueryParameter(name, value.ToString(), encode);
+
+ ///
+ /// Adds a query string parameter to the request. The request resource should not contain any placeholders for this parameter.
+ /// The parameter will be added to the request URL as a query string using name=value format.
+ /// The value will be converted to string using invariant culture for IFormattable types.
+ ///
+ /// Parameter name
+ /// Parameter value
+ /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
+ /// Encode the value or not, default true
+ ///
+ public RestRequest AddQueryParameter(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
+ => request.AddQueryParameter(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
}
}
\ No newline at end of file
diff --git a/src/RestSharp/Request/RestRequestExtensions.Url.cs b/src/RestSharp/Request/RestRequestExtensions.Url.cs
index 546cc5c56..1dba74e07 100644
--- a/src/RestSharp/Request/RestRequestExtensions.Url.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.Url.cs
@@ -39,6 +39,19 @@ public RestRequest AddUrlSegment(string name, string? value, bool encode = true)
/// Encode the value or not, default true
///
public RestRequest AddUrlSegment(string name, T value, bool encode = true) where T : struct
- => request.AddUrlSegment(name, value.ToStringInvariant(), encode);
+ => request.AddUrlSegment(name, value.ToString(), encode);
+
+ ///
+ /// Adds a URL segment parameter to the request. The resource URL must have a placeholder for the parameter for it to work.
+ /// For example, if you add a URL segment parameter with the name "id", the resource URL should contain {id} in its path.
+ /// The value will be converted to string using invariant culture for IFormattable types.
+ ///
+ /// Name of the parameter; must be matching a placeholder in the resource URL as {name}
+ /// Value of the parameter
+ /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
+ /// Encode the value or not, default true
+ ///
+ public RestRequest AddUrlSegment(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
+ => request.AddUrlSegment(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
}
}
\ No newline at end of file
diff --git a/src/RestSharp/Request/RestRequestExtensions.cs b/src/RestSharp/Request/RestRequestExtensions.cs
index be53a9f0c..a855cba89 100644
--- a/src/RestSharp/Request/RestRequestExtensions.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.cs
@@ -54,7 +54,19 @@ public RestRequest AddParameter(string? name, object value, ParameterType type,
/// Encode the value or not, default true
/// This request
public RestRequest AddParameter(string name, T value, bool encode = true) where T : struct
- => request.AddParameter(name, value.ToStringInvariant(), encode);
+ => request.AddParameter(name, value.ToString(), encode);
+
+ ///
+ /// Adds a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT).
+ /// The value will be converted to string using invariant culture for IFormattable types.
+ ///
+ /// Name of the parameter
+ /// Value of the parameter
+ /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
+ /// Encode the value or not, default true
+ /// This request
+ public RestRequest AddParameter(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
+ => request.AddParameter(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
///
/// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
@@ -74,7 +86,19 @@ public RestRequest AddOrUpdateParameter(string name, string? value, bool encode
/// Encode the value or not, default true
/// This request
public RestRequest AddOrUpdateParameter(string name, T value, bool encode = true) where T : struct
- => request.AddOrUpdateParameter(name, value.ToStringInvariant(), encode);
+ => request.AddOrUpdateParameter(name, value.ToString(), encode);
+
+ ///
+ /// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT).
+ /// The value will be converted to string using invariant culture for IFormattable types.
+ ///
+ /// Name of the parameter
+ /// Value of the parameter
+ /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
+ /// Encode the value or not, default true
+ /// This request
+ public RestRequest AddOrUpdateParameter(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
+ => request.AddOrUpdateParameter(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
RestRequest AddParameters(IEnumerable parameters) {
request.Parameters.AddParameters(parameters);
diff --git a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
index f5ec68145..d1ca82f90 100644
--- a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
+++ b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
@@ -4,7 +4,7 @@ namespace RestSharp.Tests.Parameters;
public class InvariantCultureParameterTests {
[Fact]
- public void AddParameter_Double_UsesInvariantCulture() {
+ public void AddParameter_Double_UsesInvariantCulture_WhenOptIn() {
// Save original culture
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
@@ -12,7 +12,7 @@ public void AddParameter_Double_UsesInvariantCulture() {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
var request = new RestRequest();
- request.AddParameter("value", 1.234);
+ request.AddParameter("value", 1.234, useInvariantCulture: true);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -23,16 +23,19 @@ public void AddParameter_Double_UsesInvariantCulture() {
}
[Fact]
- public void AddOrUpdateParameter_Double_UsesInvariantCulture() {
+ public void AddParameter_Double_UsesCurrentCulture_ByDefault() {
+ // Save original culture
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
+ // Set a culture that uses comma as decimal separator
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
var request = new RestRequest();
- request.AddOrUpdateParameter("value", 1.234);
+ request.AddParameter("value", 1.234);
var parameter = request.Parameters.First();
- parameter.Value.Should().Be("1.234");
+ // Default behavior uses current culture (comma as decimal separator)
+ parameter.Value.Should().Be("1,234");
}
finally {
Thread.CurrentThread.CurrentCulture = originalCulture;
@@ -40,13 +43,13 @@ public void AddOrUpdateParameter_Double_UsesInvariantCulture() {
}
[Fact]
- public void AddQueryParameter_Double_UsesInvariantCulture() {
+ public void AddOrUpdateParameter_Double_UsesInvariantCulture_WhenOptIn() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
var request = new RestRequest();
- request.AddQueryParameter("value", 1.234);
+ request.AddOrUpdateParameter("value", 1.234, useInvariantCulture: true);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -57,13 +60,13 @@ public void AddQueryParameter_Double_UsesInvariantCulture() {
}
[Fact]
- public void AddUrlSegment_Double_UsesInvariantCulture() {
+ public void AddQueryParameter_Double_UsesInvariantCulture_WhenOptIn() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
- var request = new RestRequest("{value}");
- request.AddUrlSegment("value", 1.234);
+ var request = new RestRequest();
+ request.AddQueryParameter("value", 1.234, useInvariantCulture: true);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -74,13 +77,15 @@ public void AddUrlSegment_Double_UsesInvariantCulture() {
}
[Fact]
- public void CreateParameter_Double_UsesInvariantCulture() {
+ public void AddUrlSegment_Double_UsesInvariantCulture_WhenOptIn() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
- var parameter = Parameter.CreateParameter("value", 1.234, ParameterType.GetOrPost);
+ var request = new RestRequest("{value}");
+ request.AddUrlSegment("value", 1.234, useInvariantCulture: true);
+ var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
}
finally {
@@ -89,13 +94,13 @@ public void CreateParameter_Double_UsesInvariantCulture() {
}
[Fact]
- public void AddParameter_Decimal_UsesInvariantCulture() {
+ public void AddParameter_Decimal_UsesInvariantCulture_WhenOptIn() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
var request = new RestRequest();
- request.AddParameter("value", 123.456m);
+ request.AddParameter("value", 123.456m, useInvariantCulture: true);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("123.456");
@@ -106,13 +111,13 @@ public void AddParameter_Decimal_UsesInvariantCulture() {
}
[Fact]
- public void AddParameter_Float_UsesInvariantCulture() {
+ public void AddParameter_Float_UsesInvariantCulture_WhenOptIn() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
var request = new RestRequest();
- request.AddParameter("value", 2.5f);
+ request.AddParameter("value", 2.5f, useInvariantCulture: true);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("2.5");
@@ -123,14 +128,14 @@ public void AddParameter_Float_UsesInvariantCulture() {
}
[Fact]
- public void AddParameter_DateTime_UsesInvariantCulture() {
+ public void AddParameter_DateTime_UsesInvariantCulture_WhenOptIn() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
var dateTime = new DateTime(2024, 12, 25, 10, 30, 0, DateTimeKind.Unspecified);
var request = new RestRequest();
- request.AddParameter("date", dateTime);
+ request.AddParameter("date", dateTime, useInvariantCulture: true);
var parameter = request.Parameters.First();
// DateTime.ToString with InvariantCulture uses MM/dd/yyyy format
@@ -142,33 +147,22 @@ public void AddParameter_DateTime_UsesInvariantCulture() {
}
[Fact]
- public void AddParameter_Integer_WorksWithAnyCulture() {
+ public void AddParameter_Integer_SameValueWithOrWithoutInvariantCulture() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
- var request = new RestRequest();
- request.AddParameter("value", 12345);
+ var requestWithInvariant = new RestRequest();
+ requestWithInvariant.AddParameter("value", 12345, useInvariantCulture: true);
- var parameter = request.Parameters.First();
- parameter.Value.Should().Be("12345");
- }
- finally {
- Thread.CurrentThread.CurrentCulture = originalCulture;
- }
- }
-
- [Fact]
- public void AddObject_WithDoubleProperty_UsesInvariantCulture() {
- var originalCulture = Thread.CurrentThread.CurrentCulture;
- try {
- Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+ var requestWithoutInvariant = new RestRequest();
+ requestWithoutInvariant.AddParameter("value", 12345);
- var request = new RestRequest();
- request.AddObject(new { Amount = 1.234 });
+ var parameterWithInvariant = requestWithInvariant.Parameters.First();
+ var parameterWithoutInvariant = requestWithoutInvariant.Parameters.First();
- var parameter = request.Parameters.First();
- parameter.Value.Should().Be("1.234");
+ parameterWithInvariant.Value.Should().Be("12345");
+ parameterWithoutInvariant.Value.Should().Be("12345");
}
finally {
Thread.CurrentThread.CurrentCulture = originalCulture;
From 45021670d46b0b14ee192e9e343479cebd38c9be Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 30 Nov 2025 07:57:53 +0000
Subject: [PATCH 4/5] Add CultureForParameters option to RestClientOptions for
culture-aware parameter formatting
Co-authored-by: alexeyzimarev <2821205+alexeyzimarev@users.noreply.github.com>
---
src/RestSharp/Extensions/ObjectExtensions.cs | 9 +-
src/RestSharp/Options/RestClientOptions.cs | 7 +
.../Request/RestRequestExtensions.Culture.cs | 71 ++++++++++
.../Request/RestRequestExtensions.Query.cs | 15 ---
.../Request/RestRequestExtensions.Url.cs | 15 ---
.../Request/RestRequestExtensions.cs | 26 ----
src/RestSharp/RestClient.Extensions.Params.cs | 41 ++++++
.../InvariantCultureParameterTests.cs | 125 +++++++++++++++---
8 files changed, 234 insertions(+), 75 deletions(-)
create mode 100644 src/RestSharp/Request/RestRequestExtensions.Culture.cs
diff --git a/src/RestSharp/Extensions/ObjectExtensions.cs b/src/RestSharp/Extensions/ObjectExtensions.cs
index 15ca49eea..5a596d8ba 100644
--- a/src/RestSharp/Extensions/ObjectExtensions.cs
+++ b/src/RestSharp/Extensions/ObjectExtensions.cs
@@ -18,14 +18,15 @@ namespace RestSharp.Extensions;
static class ObjectExtensions {
///
- /// Converts a value to its string representation using invariant culture for IFormattable types.
+ /// Converts a value to its string representation using the specified culture for IFormattable types.
///
/// The type of value to convert
/// The value to convert
- /// String representation using invariant culture, or null if value is null
- internal static string? ToStringInvariant(this T value) => value switch {
+ /// The culture to use for formatting. If null, uses the current culture.
+ /// String representation using the specified culture, or null if value is null
+ internal static string? ToStringWithCulture(this T value, CultureInfo? culture) => value switch {
null => null,
- IFormattable f => f.ToString(null, CultureInfo.InvariantCulture),
+ IFormattable f => f.ToString(null, culture),
_ => value.ToString()
};
}
diff --git a/src/RestSharp/Options/RestClientOptions.cs b/src/RestSharp/Options/RestClientOptions.cs
index d30e34f92..3017fd985 100644
--- a/src/RestSharp/Options/RestClientOptions.cs
+++ b/src/RestSharp/Options/RestClientOptions.cs
@@ -13,6 +13,7 @@
// limitations under the License.
//
+using System.Globalization;
using System.Net.Http.Headers;
using System.Net.Security;
using System.Reflection;
@@ -230,4 +231,10 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
/// Custom function to encode a string for use in a URL query.
///
public Func EncodeQuery { get; set; } = (s, encoding) => s.UrlEncode(encoding)!;
+
+ ///
+ /// Culture to use for formatting IFormattable parameter values. Default is null which uses the current culture.
+ /// Set to to ensure consistent formatting across different locales.
+ ///
+ public CultureInfo? CultureForParameters { get; set; }
}
diff --git a/src/RestSharp/Request/RestRequestExtensions.Culture.cs b/src/RestSharp/Request/RestRequestExtensions.Culture.cs
new file mode 100644
index 000000000..335e88aaf
--- /dev/null
+++ b/src/RestSharp/Request/RestRequestExtensions.Culture.cs
@@ -0,0 +1,71 @@
+// Copyright (c) .NET Foundation and Contributors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+using RestSharp.Extensions;
+
+namespace RestSharp;
+
+public static partial class RestRequestExtensions {
+ ///
+ /// Adds a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT).
+ /// The value will be converted to string using the culture specified in .
+ ///
+ /// The RestClient instance containing the culture settings
+ /// The request to add the parameter to
+ /// Name of the parameter
+ /// Value of the parameter
+ /// Encode the value or not, default true
+ /// This request
+ public static RestRequest AddParameter(this RestRequest request, IRestClient client, string name, T value, bool encode = true) where T : struct
+ => request.AddParameter(name, value.ToStringWithCulture(client.Options.CultureForParameters), encode);
+
+ ///
+ /// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT).
+ /// The value will be converted to string using the culture specified in .
+ ///
+ /// The RestClient instance containing the culture settings
+ /// The request to add the parameter to
+ /// Name of the parameter
+ /// Value of the parameter
+ /// Encode the value or not, default true
+ /// This request
+ public static RestRequest AddOrUpdateParameter(this RestRequest request, IRestClient client, string name, T value, bool encode = true) where T : struct
+ => request.AddOrUpdateParameter(name, value.ToStringWithCulture(client.Options.CultureForParameters), encode);
+
+ ///
+ /// Adds a query string parameter to the request.
+ /// The value will be converted to string using the culture specified in .
+ ///
+ /// The RestClient instance containing the culture settings
+ /// The request to add the parameter to
+ /// Parameter name
+ /// Parameter value
+ /// Encode the value or not, default true
+ ///
+ public static RestRequest AddQueryParameter(this RestRequest request, IRestClient client, string name, T value, bool encode = true) where T : struct
+ => request.AddQueryParameter(name, value.ToStringWithCulture(client.Options.CultureForParameters), encode);
+
+ ///
+ /// Adds a URL segment parameter to the request.
+ /// The value will be converted to string using the culture specified in .
+ ///
+ /// The RestClient instance containing the culture settings
+ /// The request to add the parameter to
+ /// Name of the parameter; must be matching a placeholder in the resource URL as {name}
+ /// Value of the parameter
+ /// Encode the value or not, default true
+ ///
+ public static RestRequest AddUrlSegment(this RestRequest request, IRestClient client, string name, T value, bool encode = true) where T : struct
+ => request.AddUrlSegment(name, value.ToStringWithCulture(client.Options.CultureForParameters), encode);
+}
diff --git a/src/RestSharp/Request/RestRequestExtensions.Query.cs b/src/RestSharp/Request/RestRequestExtensions.Query.cs
index 01697ed53..265dc360d 100644
--- a/src/RestSharp/Request/RestRequestExtensions.Query.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.Query.cs
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using RestSharp.Extensions;
-
namespace RestSharp;
public static partial class RestRequestExtensions {
@@ -40,18 +38,5 @@ public RestRequest AddQueryParameter(string name, string? value, bool encode = t
///
public RestRequest AddQueryParameter(string name, T value, bool encode = true) where T : struct
=> request.AddQueryParameter(name, value.ToString(), encode);
-
- ///
- /// Adds a query string parameter to the request. The request resource should not contain any placeholders for this parameter.
- /// The parameter will be added to the request URL as a query string using name=value format.
- /// The value will be converted to string using invariant culture for IFormattable types.
- ///
- /// Parameter name
- /// Parameter value
- /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
- /// Encode the value or not, default true
- ///
- public RestRequest AddQueryParameter(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
- => request.AddQueryParameter(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
}
}
\ No newline at end of file
diff --git a/src/RestSharp/Request/RestRequestExtensions.Url.cs b/src/RestSharp/Request/RestRequestExtensions.Url.cs
index 1dba74e07..499c629df 100644
--- a/src/RestSharp/Request/RestRequestExtensions.Url.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.Url.cs
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using RestSharp.Extensions;
-
namespace RestSharp;
public static partial class RestRequestExtensions {
@@ -40,18 +38,5 @@ public RestRequest AddUrlSegment(string name, string? value, bool encode = true)
///
public RestRequest AddUrlSegment(string name, T value, bool encode = true) where T : struct
=> request.AddUrlSegment(name, value.ToString(), encode);
-
- ///
- /// Adds a URL segment parameter to the request. The resource URL must have a placeholder for the parameter for it to work.
- /// For example, if you add a URL segment parameter with the name "id", the resource URL should contain {id} in its path.
- /// The value will be converted to string using invariant culture for IFormattable types.
- ///
- /// Name of the parameter; must be matching a placeholder in the resource URL as {name}
- /// Value of the parameter
- /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
- /// Encode the value or not, default true
- ///
- public RestRequest AddUrlSegment(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
- => request.AddUrlSegment(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
}
}
\ No newline at end of file
diff --git a/src/RestSharp/Request/RestRequestExtensions.cs b/src/RestSharp/Request/RestRequestExtensions.cs
index a855cba89..82323d07b 100644
--- a/src/RestSharp/Request/RestRequestExtensions.cs
+++ b/src/RestSharp/Request/RestRequestExtensions.cs
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-using RestSharp.Extensions;
-
namespace RestSharp;
[PublicAPI]
@@ -56,18 +54,6 @@ public RestRequest AddParameter(string? name, object value, ParameterType type,
public RestRequest AddParameter(string name, T value, bool encode = true) where T : struct
=> request.AddParameter(name, value.ToString(), encode);
- ///
- /// Adds a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT).
- /// The value will be converted to string using invariant culture for IFormattable types.
- ///
- /// Name of the parameter
- /// Value of the parameter
- /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
- /// Encode the value or not, default true
- /// This request
- public RestRequest AddParameter(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
- => request.AddParameter(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
-
///
/// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
///
@@ -88,18 +74,6 @@ public RestRequest AddOrUpdateParameter(string name, string? value, bool encode
public RestRequest AddOrUpdateParameter(string name, T value, bool encode = true) where T : struct
=> request.AddOrUpdateParameter(name, value.ToString(), encode);
- ///
- /// Adds or updates a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT).
- /// The value will be converted to string using invariant culture for IFormattable types.
- ///
- /// Name of the parameter
- /// Value of the parameter
- /// When true, uses invariant culture for IFormattable types (e.g., numbers, dates)
- /// Encode the value or not, default true
- /// This request
- public RestRequest AddOrUpdateParameter(string name, T value, bool useInvariantCulture, bool encode = true) where T : struct
- => request.AddOrUpdateParameter(name, useInvariantCulture ? value.ToStringInvariant() : value.ToString(), encode);
-
RestRequest AddParameters(IEnumerable parameters) {
request.Parameters.AddParameters(parameters);
return request;
diff --git a/src/RestSharp/RestClient.Extensions.Params.cs b/src/RestSharp/RestClient.Extensions.Params.cs
index cd3bb635c..33531d908 100644
--- a/src/RestSharp/RestClient.Extensions.Params.cs
+++ b/src/RestSharp/RestClient.Extensions.Params.cs
@@ -13,6 +13,8 @@
// limitations under the License.
//
+using RestSharp.Extensions;
+
namespace RestSharp;
public static partial class RestClientExtensions {
@@ -38,6 +40,17 @@ public IRestClient AddDefaultParameter(Parameter parameter) {
public IRestClient AddDefaultParameter(string name, string value)
=> client.AddDefaultParameter(new GetOrPostParameter(name, value));
+ ///
+ /// Adds a default HTTP parameter (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT)
+ /// Used on every request made by this client instance. The value will be formatted using the culture
+ /// specified in .
+ ///
+ /// Name of the parameter
+ /// Value of the parameter
+ /// This request
+ public IRestClient AddDefaultParameter(string name, T value) where T : struct
+ => client.AddDefaultParameter(new GetOrPostParameter(name, value.ToStringWithCulture(client.Options.CultureForParameters)));
+
///
/// Adds a default parameter to the client options. There are four types of parameters:
/// - GetOrPost: Either a QueryString value or encoded form value based on method
@@ -82,6 +95,16 @@ public IRestClient AddDefaultHeaders(Dictionary headers) {
public IRestClient AddDefaultUrlSegment(string name, string value)
=> client.AddDefaultParameter(new UrlSegmentParameter(name, value));
+ ///
+ /// Adds a default URL segment parameter to the RestClient. Used on every request made by this client instance.
+ /// The value will be formatted using the culture specified in .
+ ///
+ /// Name of the segment to add
+ /// Value of the segment to add
+ ///
+ public IRestClient AddDefaultUrlSegment(string name, T value) where T : struct
+ => client.AddDefaultParameter(new UrlSegmentParameter(name, value.ToStringWithCulture(client.Options.CultureForParameters)));
+
///
/// Adds a default URL query parameter to the RestClient. Used on every request made by this client instance.
///
@@ -90,5 +113,23 @@ public IRestClient AddDefaultUrlSegment(string name, string value)
///
public IRestClient AddDefaultQueryParameter(string name, string value)
=> client.AddDefaultParameter(new QueryParameter(name, value));
+
+ ///
+ /// Adds a default URL query parameter to the RestClient. Used on every request made by this client instance.
+ /// The value will be formatted using the culture specified in .
+ ///
+ /// Name of the query parameter to add
+ /// Value of the query parameter to add
+ ///
+ public IRestClient AddDefaultQueryParameter(string name, T value) where T : struct
+ => client.AddDefaultParameter(new QueryParameter(name, value.ToStringWithCulture(client.Options.CultureForParameters)));
+
+ ///
+ /// Formats the value using the culture specified in .
+ ///
+ /// Value to format
+ /// String representation of the value using the client's culture setting
+ public string? FormatValue(T value) where T : struct
+ => value.ToStringWithCulture(client.Options.CultureForParameters);
}
}
diff --git a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
index d1ca82f90..e517f92ac 100644
--- a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
+++ b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
@@ -1,18 +1,21 @@
using System.Globalization;
+using RichardSzalay.MockHttp;
namespace RestSharp.Tests.Parameters;
public class InvariantCultureParameterTests {
[Fact]
- public void AddParameter_Double_UsesInvariantCulture_WhenOptIn() {
+ public void AddParameter_Double_UsesInvariantCulture_WhenConfigured() {
// Save original culture
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
// Set a culture that uses comma as decimal separator
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest();
- request.AddParameter("value", 1.234, useInvariantCulture: true);
+ request.AddParameter(client, "value", 1.234);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -43,13 +46,15 @@ public void AddParameter_Double_UsesCurrentCulture_ByDefault() {
}
[Fact]
- public void AddOrUpdateParameter_Double_UsesInvariantCulture_WhenOptIn() {
+ public void AddOrUpdateParameter_Double_UsesInvariantCulture_WhenConfigured() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest();
- request.AddOrUpdateParameter("value", 1.234, useInvariantCulture: true);
+ request.AddOrUpdateParameter(client, "value", 1.234);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -60,13 +65,15 @@ public void AddOrUpdateParameter_Double_UsesInvariantCulture_WhenOptIn() {
}
[Fact]
- public void AddQueryParameter_Double_UsesInvariantCulture_WhenOptIn() {
+ public void AddQueryParameter_Double_UsesInvariantCulture_WhenConfigured() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest();
- request.AddQueryParameter("value", 1.234, useInvariantCulture: true);
+ request.AddQueryParameter(client, "value", 1.234);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -77,13 +84,15 @@ public void AddQueryParameter_Double_UsesInvariantCulture_WhenOptIn() {
}
[Fact]
- public void AddUrlSegment_Double_UsesInvariantCulture_WhenOptIn() {
+ public void AddUrlSegment_Double_UsesInvariantCulture_WhenConfigured() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest("{value}");
- request.AddUrlSegment("value", 1.234, useInvariantCulture: true);
+ request.AddUrlSegment(client, "value", 1.234);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("1.234");
@@ -94,13 +103,87 @@ public void AddUrlSegment_Double_UsesInvariantCulture_WhenOptIn() {
}
[Fact]
- public void AddParameter_Decimal_UsesInvariantCulture_WhenOptIn() {
+ public void AddDefaultParameter_Double_UsesInvariantCulture_WhenConfigured() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
+ client.AddDefaultParameter("value", 1.234);
+
+ var parameter = client.DefaultParameters.First(p => p.Name == "value");
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddDefaultQueryParameter_Double_UsesInvariantCulture_WhenConfigured() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
+ client.AddDefaultQueryParameter("value", 1.234);
+
+ var parameter = client.DefaultParameters.First(p => p.Name == "value");
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddDefaultUrlSegment_Double_UsesInvariantCulture_WhenConfigured() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
+ client.AddDefaultUrlSegment("value", 1.234);
+
+ var parameter = client.DefaultParameters.First(p => p.Name == "value");
+ parameter.Value.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void FormatValue_Double_UsesInvariantCulture_WhenConfigured() {
+ var originalCulture = Thread.CurrentThread.CurrentCulture;
+ try {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
+
+ var formattedValue = client.FormatValue(1.234);
+
+ formattedValue.Should().Be("1.234");
+ }
+ finally {
+ Thread.CurrentThread.CurrentCulture = originalCulture;
+ }
+ }
+
+ [Fact]
+ public void AddParameter_Decimal_UsesInvariantCulture_WhenConfigured() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest();
- request.AddParameter("value", 123.456m, useInvariantCulture: true);
+ request.AddParameter(client, "value", 123.456m);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("123.456");
@@ -111,13 +194,15 @@ public void AddParameter_Decimal_UsesInvariantCulture_WhenOptIn() {
}
[Fact]
- public void AddParameter_Float_UsesInvariantCulture_WhenOptIn() {
+ public void AddParameter_Float_UsesInvariantCulture_WhenConfigured() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest();
- request.AddParameter("value", 2.5f, useInvariantCulture: true);
+ request.AddParameter(client, "value", 2.5f);
var parameter = request.Parameters.First();
parameter.Value.Should().Be("2.5");
@@ -128,14 +213,16 @@ public void AddParameter_Float_UsesInvariantCulture_WhenOptIn() {
}
[Fact]
- public void AddParameter_DateTime_UsesInvariantCulture_WhenOptIn() {
+ public void AddParameter_DateTime_UsesInvariantCulture_WhenConfigured() {
var originalCulture = Thread.CurrentThread.CurrentCulture;
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
var dateTime = new DateTime(2024, 12, 25, 10, 30, 0, DateTimeKind.Unspecified);
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var request = new RestRequest();
- request.AddParameter("date", dateTime, useInvariantCulture: true);
+ request.AddParameter(client, "date", dateTime);
var parameter = request.Parameters.First();
// DateTime.ToString with InvariantCulture uses MM/dd/yyyy format
@@ -152,8 +239,10 @@ public void AddParameter_Integer_SameValueWithOrWithoutInvariantCulture() {
try {
Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
+ var options = new RestClientOptions { CultureForParameters = CultureInfo.InvariantCulture };
+ using var client = new RestClient(options);
var requestWithInvariant = new RestRequest();
- requestWithInvariant.AddParameter("value", 12345, useInvariantCulture: true);
+ requestWithInvariant.AddParameter(client, "value", 12345);
var requestWithoutInvariant = new RestRequest();
requestWithoutInvariant.AddParameter("value", 12345);
@@ -168,4 +257,10 @@ public void AddParameter_Integer_SameValueWithOrWithoutInvariantCulture() {
Thread.CurrentThread.CurrentCulture = originalCulture;
}
}
+
+ [Fact]
+ public void CultureForParameters_DefaultValue_IsNull() {
+ var options = new RestClientOptions();
+ options.CultureForParameters.Should().BeNull();
+ }
}
From 1fb26deb968574ac7e268a9426e73238933df914 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sun, 30 Nov 2025 08:02:03 +0000
Subject: [PATCH 5/5] Remove unused import in test file
Co-authored-by: alexeyzimarev <2821205+alexeyzimarev@users.noreply.github.com>
---
.../RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
index e517f92ac..43d5ccf50 100644
--- a/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
+++ b/test/RestSharp.Tests/Parameters/InvariantCultureParameterTests.cs
@@ -1,5 +1,4 @@
using System.Globalization;
-using RichardSzalay.MockHttp;
namespace RestSharp.Tests.Parameters;