Search code examples
c#query-stringcultureinfo

Query string with dot as decimal separator in C#


I would like to build a query string with a dot as decimal separator but I can not figure out how / where I should use the CultureInfo to convert the comma to the dot in the Account property value.

Person person = new()
{
    Name = "Tom",
    Account = 1000.123m,
};

var properties = from p in person.GetType().GetProperties()
                 where p.GetValue(person, null) != null
                 select p.Name.ToLower() + "=" + p.GetValue(person);

Console.WriteLine(String.Join("&", properties.ToArray()));


class Person
{
    public string Name { get; set; } = String.Empty;
    public decimal Account { get; set; }
}

Current output: name=Tom&account=1000,123

Expected output: name=Tom&account=1000.123

I guess there is something to add to + p.GetValue(person)

Can you help me please? Many thanks.


Solution

  • To format numeric property values using a period instead of a comma for the decimal separator, call Convert.ToString(Object, IFormatProvider) and pass the invariant culture as the second argument:

    using System.Globalization;
    
    // ...
    
    select p.Name.ToLower() + "=" + Convert.ToString(p.GetValue(person), CultureInfo.InvariantCulture);
    
    // or you can use string interpolation:
    // select FormattableString.Invariant($"{p.Name.ToLower()}={p.GetValue(person)}");
    

    This particular overload of Convert.ToString calls IConvertible.ToString, IFormattable.ToString, or just Object.ToString depending on the interfaces implemented by the value.


    By the way, for the property name, you should call String.ToLowerInvariant instead of ToLower to avoid the Turkish "i" problem: In the tr-TR culture, "I".ToLower() returns "ı" (dotless i) instead of "i". You should also ensure that special characters in the property value are correctly encoded in the query string:

    select p.Name.ToLowerInvariant() + "=" +
        Uri.EscapeDataString(Convert.ToString(p.GetValue(person), CultureInfo.InvariantCulture)!);