QueryStringSerializer Adds Quotes if field has comma in a dictionary

I’ve noticed that when a dictionary is run through the querystringserializer and the string value has a comma, it adds quotes around the value, however if it is an object it doesn’t. This simple code demonstrates it:

var obj2 = new { Field = "Some Field with comma, to demonstrate. "};
QueryStringSerializer.SerializeToString(obj2.ToObjectDictionary()).Print();  
 // Field=%22Some+Field+with+comma,+to+demonstrate.+%22
QueryStringSerializer.SerializeToString(obj2).Print();
// Field=Some+Field+with+comma,+to+demonstrate.+

I discovered this when I had an api fail with PostToUrl and a string dictionary.

I’m not sure it is a bug or anything just wondering about the differences?

It uses the JSV Format and quotes the value when it needs to:

https://docs.servicestack.net/serialization-deserialization#passing-complex-objects-in-the-query-string

Sure I get that but the same values in a poco vs a string dictionary produces different results:

Field=%22Some+Field+with+comma,+to+demonstrate.+%22
vs
Field=Some+Field+with+comma,+to+demonstrate.+

Do you have a specific issue with how the QueryString data is deserialized inside a request?

It is something I ran into today, the examples I posted are exactly the case. For instance, if I have a poco defined as:

public class A {
  public string Message {get;set;}
}

and I convert it to a string Dictionary (or object dictionary, ie new A().ToStringDictionary()) it will be querystring serialized differently than the poco if the string property (both are string in this case) has a comma in it. The dictionary when querystring serialized will wrap the value with quotes and the object will not. The behavior isn’t consistent which was why I wrote initially.

I found this out when working with an API (non service stack) that was sending messages wrapped in quotes when the object didn’t have them and only when there was a comma. When I removed the dictionary it worked but made me wonder why the differences between the serialization of the two.

I will see if I can post a standalone test for you.

Yes please provide a stand-alone repro if there’s an issue with the deserialized data populated on the Request DTO i.e. not how it’s encoded but if there’s an actual issue with the deserialized result.

The following question is regarding the populated DTO’s in a service and the HTTP utils. Should these produce identical results with regards to the populated DTO?

var data1= url.PostToUrl(new GetTest {Message = TestData.TestMessage }.ToStringDictionary());
vs.
var data2 = url.PostToUrl(new GetTest {Message = TestData.TestMessage });

Should
data1 == data 2 ?

    public class TestService: Service
    {
        public string Any(GetTest req)
        {
        
            return req.Message;
        }
    }

ok yeah the top-level string values should be URL encoded not JSV encoded. Now resolved in the latest v5.8.1 that’s now on MyGet.

Upgraded to 5.8.1. Still getting differences when there is a comma in the string value (Message in this case). Test program linked here.

Test program is basic (pasted here and linked above). When there is a comma in the string that is posted to the service, it deserializes the value differently.

class Program
{
    static void Main(string[] args)
    {

        const string BaseUri = "http://localhost:2000/";
       
        var appHost = new AppHost().Init().Start(BaseUri);
        var client = new JsonServiceClient(BaseUri);
        
        var data = (BaseUri + "test").PostToUrl(new GetTest {Message = TestData.TestMessage }.ToStringDictionary());

        var data2 = (BaseUri + "test").PostToUrl(new GetTest { Message = TestData.TestMessage });

        if (data != data2)
        {
            Console.WriteLine("The return values do not match");
        }
      
        Console.ReadKey();

    }
}

public static class TestData
{
    public static String TestMessage = "Has a, comma";
}

public class AppHost : AppSelfHostBase
{
    public AppHost() : base("Customer REST Example", typeof(TestService).Assembly) { }

    public override void Configure(Container container)
    {
       
    }
}

public class TestService: Service
{
    public string Any(GetTest req)
    {
        if (TestData.TestMessage != req.Message)
        {
            Console.WriteLine("Service:  Value doesn't match test data");
        }
        return req.Message;
    }
}

[Route("/test")]
public class GetTest //: IRequiresRequestStream
{
    public string Message { get;set;}


}

Both responses are the same, I’m assuming you never cleared your NuGet packages cache to download the latest v5.8.1 pre-release packages.

1 Like

Thanks, clearing the cache and rerunning the test program is confirmed to be working. Thanks for fixing it so quickly.