Question

I have a working WCF - WPF application working, however I'm looking for some optimization. Below is my code where a WCF restful service is exposing a JSON array, and a WPF UI is receiving it without any problem.

WCF:

public clsStatus[] GetAllStatus()
{

    DataTable dt = new DataTable();
    List<clsStatus> lstGetAllStatus = new List<clsStatus>();
    try
    {
        dt = // My Data Table

        foreach (DataRow dr in dt.Rows)
        {
            dcStatus objGetAllStatus = new clsStatus();
            objGetAllStatus.Id = Convert.ToInt32(dr["Id"]);
            objGetAllStatus.Status = dr["Status"].ToString();                   
            lstGetAllStatus.Add(objGetAllStatus);
        }

    }
    return lstGetAllStatus.ToArray();
}

In WPF UI:

public ObservableCollection<T> InvokeGet<T>(string sUrl)
{

    System.Net.WebRequest request = System.Net.HttpWebRequest.Create(sUrl);

    request.Method = "GET";

    request.UseDefaultCredentials = true;

    request.ContentLength = 0;

    System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse;

    Stream objResponseStream = response.GetResponseStream();

    StreamReader reader = new StreamReader(objResponseStream);

    string objResponseString = reader.ReadToEnd();

    response.Close();

    JavaScriptSerializer objJsonserialiser = new JavaScriptSerializer();

    objJsonserialiser.MaxJsonLength = 999999999;

    T[] arrResult = objJsonserialiser.Deserialize<T[]>(objResponseString);

    return new ObservableCollection<T>(arrResult);  

}

This way serialization/deserialization is working fine, whereas when I make the changes shown below the deserialization no longer works:

In WCF:

public string[] GetAllStatus()
{
    DataTable dt = new DataTable();

    try
    {
        dt = // My Data Table

        string jsonresp = JsonConvert.SerializeObject(dt, Formatting.None);
    }

    return jsonresp;
}

In WPF:

public ObservableCollection<T> InvokeGet<T>(string sUrl )
{

    System.Net.WebRequest request = System.Net.HttpWebRequest.Create(sUrl);

    request.Method = "GET";

    request.UseDefaultCredentials = true;

    request.ContentLength = 0;

    System.Net.HttpWebResponse response = request.GetResponse() as System.Net.HttpWebResponse;

    Stream objResponseStream = response.GetResponseStream();

    StreamReader reader = new StreamReader(objResponseStream);

    string objResponseString = reader.ReadToEnd();

    response.Close();

    dsReportRequests dsrepreq = new dsReportRequests();

    //This conversion is failing with error
    dsrepreq = JsonConvert.DeserializeObject<dsReportRequests>(objResponseString);
}

Error: "Error converting value \"[{\"Id\":11280,\"statName}]\" to type 'clsStat[]'. Path '', line 1, position 759."

I found out that the JSON format in the changed code contains escape chars (\), which seems to be causing the error while deserializing.

Was it helpful?

Solution

Your JSON is getting double-serialized. (The extra backslashes in the JSON are symptomatic of this.)

Notice in the first version, you do not make a call to serialize the return object inside GetAllStatus(), but in InvokeGet() you do make a call to deserialize it. And that works. So, somehow the return object from GetAllStatus must be getting serialized automatically. It should be clear that WCF must be handling the serialization of your return object for you.

In the second version, you manually serialize the return object inside GetAllStatus() using JsonConvert.SerializeObject(). Since we just established that WCF is also doing serialization, you end up with double-serialized JSON.

To make it work, you need to ensure that the output is only serialized once. Presumably you had a reason to start using Json.Net in your service, so I would look for a way to replace the WCF serializer with JSON.Net. You don't have to look far-- there are quite a few questions and answers on StackOverflow that deal with this very topic. Here are few ideas:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top