February 9, 2015

JSON and CRM Sandbox Plugins

Today I was working on a plugin and one of the requirements was a call to a web service passing some POST parameters, nothing complicated but I want to share part of the process.

Normally I register my plugins always inside Sandbox, the main reason is that I don't need to care where the plugin is executed (in this specific case the development is OnPremise but the production is Online), the second reason is that my user is often forgotten to be added as Deployment Administrator :)

One of the parameter was a JSON Object passed as string, practically I needed to do the C# equivalent of a JSON.stringify in order to pass a complex structure. An example can be the following Course object (JavaScript):
var Course = new Object();
Course.Name = "CRM Development 1";
Course.Teacher = "Prof. John Smith";

Course.Students = new Array();
Course.Students[0] = new Object();
Course.Students[0].ID = "001";
Course.Students[0].Name = "Walter Davis";

Course.Students[1] = new Object();
Course.Students[1].ID = "002";
Course.Students[1].Name = "Mark Harris";

var parameter1 = JSON.stringify(Course);
Because I was inside a Sandbox plugin I couldn't use the Newtonsoft.Json library and I didn't want to waste time trying to merge it inside my plugin.

The .NET framework provides different methods to create a JSON output, in particular JavaScriptSerializer (from System.Web.Script.Serialization namespace) and DataContractJsonSerializer (from System.Runtime.Serialization.Json namespace).

JavaScriptSerializer is very easy to use (it has a Serialize method returning a string) but doesn't work inside Sandbox, so I used DataContractJsonSerializer:
Course course = new Course();
// ...

string parameter1 = "";
using (MemoryStream memoryStream = new MemoryStream())
{
   DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Course));
   serializer.WriteObject(memoryStream, course);
   parameter1 = Encoding.Default.GetString(memoryStream.ToArray());
}
A bit longer code but compatible with Sandbox and CRM Online.

5 comments:

  1. This approach sometimes also fails. I'm trying to identify pattern, but it is not that reliable too.

    ReplyDelete
  2. It finally worked for me, but I had to mark my class definition with [DataContract] attribute. And all public fields was marked as [DataMember].

    This is not mentioned in the article, and without it this steps code raises security exceptions. Since it tries to reflect members of the class. And this is forbidden in sandboxed environment.

    ReplyDelete
  3. By the way, Newtonsoft.Json, at least newest version I have tried 7.0.1 WORKs inside sandbox mode.

    ReplyDelete
    Replies
    1. thanks for the Newtonsoft.Json update, I will test it as soon as possible. Regarding the decorators of your previous comment, when I created a plugin using DataContractJsonSerializer I didn't add decorators

      Delete
  4. Thanks Guido, That saved my time. One thing that caused me problem is my object and all its fields should be public. Then only it is able to convert..

    ReplyDelete