Monday, August 22, 2011

Jsonify an ExpandoObject in MVC3

I’ve recently stumbled across a scenario where it would make sense to use an ExpandoObject to populate an object which then would be serialized to JSON. But this cannot be done in MVC 3. The reason being that an ExpandoObject implements IDictionary<TKey, TValue>, and the JavaScriptSerializer interprets it as such, and results in the following output:

[{"Key":"data","Value":"Title"}]

How to fix this? Well there is no easy way, and the the only way I could come up with are described in this StackOverflow post, How to flatten an ExpandoObject returned via JsonResult in MVC?. The post supplies us with to possibilities, an extension method to convert the ExpandoObject to a string, and a custom JsonConverter used only for ExpandoObjects.

All of these methods require that we client-side parses the JSON returned, using either eval(jsonString) or JSON.parse(jsonString) (preferred because of security issues). Not a nice way to do it, but of course the JavaScriptSerializer serializes a string as a JSON string, so this is currently the only way to do so.

You could implement a custom ActionResult, which removes the the start and end “, but then this method can only be used of non-string objects which would introduce a whole new set of problems.

Monday, August 8, 2011

Deep clone an XDocument

I’ve recently needed to clone an XDocument, and started looking in how to do this easy. The standard way to clone objects in .NET is by using the Clone method on a object implementing ICloneable, but XDocument doesn’t implement ICloneable. Now what to do?
I started my trusted browser, and the only way I found was to do this manually, and so I did. But I couldn’t let the thought go away, there had to be an easier way as cloning could be used a lot in LINQ.
I looked through the MSDN documentation, I sure enough I’ve found it, one of the constructors can do this, XDocument(XDocument). There is simply no reason to manual clone the document, and a constructor just like this exists for an XElement.
Many people may know this constructor exists, but I sure didn’t as it doesn’t following the “standard” .NET cloning methods. But the constructor way is much better, as we now are explicitly told whether or not the clone will be a shallow or deep clone.

Update: Added example as requested.

XmlDocument originalXml = new XmlDocument();
XmlDocument xmlCopy = new XmlDocument(originalXml);