Search code examples
.netjsonwcfdatacontract

CollectionDataContract to be used to consume Json array


Suppose there is this json produced by a service:

[{"key1": 12, "key2": "ab"}, {"key1": 10, "key2": "bc"}]

is this possible to be retrieved by wcf rest and parsed using CollectionDataContract as a list then parsed again automatically with DataContract?

I tried doing so, but always giving 'root level is invalid, line 1,position 1'


Solution

  • There's nothing special about [CDC] and JSON - it should just work - see the code below. Try to compare it with yours, including the networking traces (as seen in a tool such as Fiddler) and see what is different.

    public class StackOverflow_15343502
    {
        const string JSON = "[{\"key1\": 12, \"key2\": \"ab\"}, {\"key1\": 10, \"key2\": \"bc\"}]";
        public class MyDC
        {
            public int key1 { get; set; }
            public string key2 { get; set; }
    
            public override string ToString()
            {
                return string.Format("[key1={0},key2={1}]", key1, key2);
            }
        }
    
        [CollectionDataContract]
        public class MyCDC : List<MyDC> { }
    
        [ServiceContract]
        public class Service
        {
            [WebGet]
            public Stream GetData()
            {
                WebOperationContext.Current.OutgoingResponse.ContentType = "application/json";
                return new MemoryStream(Encoding.UTF8.GetBytes(JSON));
            }
        }
    
        [ServiceContract]
        public interface ITest
        {
            [WebGet(ResponseFormat = WebMessageFormat.Json)]
            MyCDC GetData();
        }
    
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
            host.Open();
            Console.WriteLine("Host opened");
    
            WebChannelFactory<ITest> factory = new WebChannelFactory<ITest>(new Uri(baseAddress));
            ITest proxy = factory.CreateChannel();
            var result = proxy.GetData();
            Console.WriteLine(string.Join(", ", result));
            ((IClientChannel)proxy).Close();
            factory.Close();
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }