Tagged: JSON

JSON Serialization and Circular Reference Error !

I have a table that references a child table with reference to parent (!), I am using LINQ to SQL, for a paricular scenario, when I want to serialize my result using Json(obj) in my controller code, I got an error saying.. “A circular reference was detected while serializing an object of type..”

This issue is very well explained by Rick Strahl in his blog (link here)

If we are using WCF services, setting SerializationMode of the data context to “Unidirectional” would do the trick. In my case I was using MVC and it was a controller action invoke from javascript!! Also I did not want to try setting the Access Level to internal because I was not sure whether I get deep serialization if I do that! (did not try, because I was half convinced that It may not work for me)

Issue was Json() call in my controller to convert my object to Json and send back as JsonResult… So I ended up serializing it in my biz layer, biz layer method now returned a Json String, changed my controller to return ActionResult/ContentResult and used Content(jsonString) to send back a ContentResult.

It worked because Javascript library expected a Json Literal and it got that. All is good for now!

Gettting ClientIDs of asp.net controls in an external javascript file

When maintaining external javascript files for our webpages the biggest hurdle we face is the getting clientID of our server side controls in the javascript file. Let me demonstrate a workwround for this that I usually adopt.
Step 1:
In the page load event create an array of json objects representing the clIentIDs of all the controls that we would be requiring to use in javascript functions. Store this in a javascript global variable using window::onload function.

private void SaveControlClientIDs()
{
       
    System.Text.StringBuilder ctlObj = new System.Text.StringBuilder();
    ctlObj.Append("[");
    ctlObj.Append("{""Id"":'" + ddlEmployee.ClientID & "',""Type"":'" + ddlEmployee.GetType().ToString() + "',""DefaultValue"":'0'},");
    ctlObj.Append("{""Id"":'" + txtName.ClientID & "',""Type"":'" + txtName.GetType().ToString() + "',""DefaultValue"":''},");
    ctlObj.Append("{""Id"":'" + txtEndDt.ClientID & "',""Type"":'" + txtEndDt.GetType().ToString() + "',""DefaultValue"":''}");
    ctlObj.Append("]");
    string bodyOnloadScript = "<script type='text/javascript'>function body_onload() { ctlIds=" + ctlObj.ToString() + ";}</script>";
    Page.ClientScript.RegisterStartupScript(this.GetType(), "onload", bodyOnloadScript);
  
}

Step 2:

In your javascript file use the following function to retrieve the clientID using the actual id of your control

var ctlIds; //this is the global variable which will store the json objects
function GetCtlClientId(id) {
    var arr = ctlIds;
    var res = ”;
    var i = 0;
    for (i = 0; i < arr.length; i++) {         if (arr[i].Id.indexOf(id) != -1) {             res = arr[i].Id;             break;         }     }     return res; } [/sourcecode] In .NET 4.0 the issue of ClientIDs has been addressed to an extent. Till you move to 4.0 hope this helps:-)

Which JSON Serializer to use?

This is an easy one, but just want to make a note for easy reference. JSON is more ubiquitous than ever these days in ASP.Net web development. From AJAX enables web sites to MVC AJAX, JSON is “the” data-interchange format we want to use.

There are 2 possible class libraries that you can use in ASP.net to serialize objects to JSON and back. If you are using WCF and your custom objects are marked as [Data Contratcs], then DataContractJsonSerializer (System.Runtime.Serialization.Json) is the class you want to use. But if you are using an object that you cannot mark as a DataContract (may be part of a third-party component), then you want to use JavaScriptSerializer (System.Web.Script.Serialization).

Here is some code snippets that shows both approaches:

/* Using JavaScriptSerializer */
//Serialize		
String s;
JavaScriptSerializer ser = new JavaScriptSerializer();
ser.MaxJsonLength = Int32.MaxValue;
s = ser.Serialize(obj);

//De-Serialize
JavaScriptSerializer ser = new JavaScriptSerializer();
ser.MaxJsonLength = Int32.MaxValue;
obj = ser.Deserialize(json);
return (obj);



/* Using DataContractJsonSerializer */

//Serialize
DataContractJsonSerializer ser = new DataContractJsonSerializer(obj.GetType());
MemoryStream ms = new MemoryStream();
ser.WriteObject(ms, obj);
string retVal = Encoding.Default.GetString(ms.ToArray());

//De-Serialize
T obj = Activator.CreateInstance();
MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
DataContractJsonSerializer ser = new DataContractJsonSerializer(obj.GetType());
obj = (T)ser.ReadObject(ms);
ms.Close();

Happy programming!

Tip: C# Automatic Properties, k_BackingField and JSON

If you are using automatic properties to define your data objects and you are trying to serialize these objects to a JSON string using DataContractSerializer (WCF/3.5), make sure you mark your data classes with [DataContract] and [DataMember] attributes (even if you are not really using WCF), a simple [Serializable] attribute will not do. If you just use [Serializable], the emitted JSON string will have a prefix tag “k_backingField” and the string is all mumbo-jumbo!

So if you use automatic properties, your class should look like this 🙂

 
    [DataContract] 
    public class Employee
    {
        [DataMember(Name = "FirstName", Order = 1)]
        public string FirstName { get; set; }
        [DataMember(Name = "LastName", Order = 2)]
        public string LastName { get; set; }
    }	

Cheers!

Using JSON – Some observations

When using JSON with Web Services (classic web service or WCF service), you might get an error “JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.” when your json string is too big. If you are using JavaScriptSerializer class to serilaize your object, then there is a property ser.MaxJsonLength that you can set to allow for more size. But somehow, I still got the error, and I had to make that setting in web.config file. If you are using DataContractJsonSerializer class (using System.Runtime.Serialization.Json namespace), then you don’t have MaxJsonLength property for that class, but adding configuration settings in web.config works like a charm.

Here is how you change MaxJsonLength using web.config:

  <system.web.extensions>
    <scripting>
      <webServices>
        <jsonSerialization maxJsonLength=”2147483647″></jsonSerialization>
      </webServices>
    </scripting>
  </system.web.extensions>

 
Cheers!