2

I'm trying to output a Dictionary via WCF as JSON. The first problem I had that the JSON was riddled with the 'Key' 'Value' elements, but I fixed this by using my own JsonDictionary (code from StackOverflow).

What I now get is:

{
    "_x0030_": {
        "__type": "Car:#WcfService",
        "Brand": "Ford",
        "Model": "Focus"
    },
    "_x0031_": {
        "__type": "Car:#WcfService",
        "Brand": "Renault",
        "Model": "Megane"
    }
}

The __type__ doesn't concern me (great that it can be removed, but not my focus currently). The problem is the index. The integer is converted to 'x0030' for 0 for example. I would expect to have:

{
    "0": {
        "__type": "Car:#WcfService",
        "Brand": "Ford",
        "Model": "Focus"
    },
    "1": {
        "__type": "Car:#WcfService",
        "Brand": "Renault",
        "Model": "Megane"
    }
}

I see on MSDN that this is default behavior, but no solution how to prevent this. Any ideas?

My code:

//Interface
[WebGet(UriTemplate = "car", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
JsonDictionary<int, Car> GetCars();

//Implementation
public class CarService : ICarService
{
    private JsonDictionary<int, Car> cars = new JsonDictionary<int, Car>();
    private int lastIndex = 0;        

    public CarService()
    {
        cars.Add(lastIndex++, new Car("Ford", "Focus"));
        cars.Add(lastIndex++, new Car("Renault", "Megane"));
    }

    public JsonDictionary<int, Car> GetCars()
    {
        return cars;
    }
}

[DataContract]
public class Car
{
    public Car(string brand, string model)
    {
        this.Brand = brand;
        this.Model = model;
    }

    [DataMember]
    public string Brand { get; private set; }

    [DataMember]
    public string Model { get; private set; }
}

[Serializable]
[KnownType(typeof(Car))]
public class JsonDictionary<TKey, TValue> : ISerializable
{
    public Dictionary<TKey, TValue> dictionary;

    public JsonDictionary()
    {
        dictionary = new Dictionary<TKey, TValue>();
    }

    public JsonDictionary(SerializationInfo info, StreamingContext context)
    {
        dictionary = new Dictionary<TKey, TValue>();
    }

    public TValue this[TKey key]
    {
        get { return dictionary[key]; }
        set { dictionary[key] = value; }
    }

    public void Add(TKey key, TValue value)
    {
        dictionary.Add(key, value);
    }

    public bool ContainsKey(TKey key)
    {
        return dictionary.ContainsKey(key);
    }

    public bool Remove(TKey key)
    {
        return dictionary.Remove(key);
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        foreach (TKey key in dictionary.Keys)
        {
            info.AddValue(key.ToString(), dictionary[key]);
        }
    }
}

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WcfService.CarService">
        <endpoint 
          behaviorConfiguration="restfulBehaviour" 
          binding="webHttpBinding" 
          contract="WcfService.ICarService">
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/carservice"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="restfulBehaviour">
          <webHttp defaultOutgoingResponseFormat="Json"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData="d:\WebTrace.svclog"  />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>
RvdK
  • 19,580
  • 4
  • 64
  • 107
  • Can you not just handle this on the receiving end? Process the keys from their ASCII hex equivalent back into the original character? – Dutts Sep 24 '13 at 08:55
  • Imho thats a working around the situation. The Server should output proper data. – RvdK Sep 24 '13 at 08:57
  • You want to replace the serializer: http://stackoverflow.com/questions/6792785/replace-wcf-default-json-serialization There is no way with the default serializer as it only supports a subset of JSON, namely the one that would result in valid XML. – Daniel Hilgarth Sep 24 '13 at 09:11
  • @RvdK Agreed, but as is pointed out in the MSDN article you linked to, WCF represents the JSON as XML under the hood and the numbers you have chosen as key names are not valid XML names. – Dutts Sep 24 '13 at 09:11
  • @RvdK - Do you have any updates on this? Facing the same issue here. – warbi Apr 02 '15 at 14:45
  • @warbi, sorry, i don't – RvdK Apr 03 '15 at 06:56

0 Answers0