While working with Dynamics CRM plugin, we encountered a scenario where we were calling a Web API, which returns data in JSON format.
Normally .NET framework provides many methods to use JSON in C# code, many third party solutions such as Newtonsoft.Json library are available. Mostly we use JavaScriptSerializer to read JSON data.
However, when we register Plugin inside Sandbox, and if we try to use javascriptSerializer method in plugin, it will throw security exception error as show below:
The error message we get:
Unhandled Exception: Microsoft.Crm.CrmException: Unexpected exception from plug-in (Execute): XXXXXXXX.CRM2015.WorkflowActivities.XXXXXXXX: System.MethodAccessException: Attempt by security transparent method ‘XXXXXXXX.CRM2015.WorkflowActivities.XXXXXXXX.SetLocationInfo(Microsoft.Xrm.Sdk.IOrganizationService, Microsoft.Xrm.Sdk.ITracingService, System.String)’ to access security critical method ‘System.Web.Script.Serialization.JavaScriptSerializer..ctor()’ failed.
Assembly ‘XXXXXXXX.CRM2015.WorkflowActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3f9fc15734725b08’ is partially trusted, which causes the CLR to make it entirely security transparent regardless of any transparency annotations in the assembly itself. In order to access security critical code, this assembly must be fully trusted.
Assembly ‘System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ is a conditionally APTCA assembly which is not enabled in the current AppDomain. To enable this assembly to be used by partial trust or security transparent code, please add assembly name ‘System.Web.Extensions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9’ to the the PartialTrustVisibleAssemblies list when creating the AppDomain.
at Microsoft.Crm.Sandbox.SandboxCodeUnit.Execute(IExecutionContext context)
at Microsoft.Crm.Workflow.Services.ProxyCustomActivity.Execute(CodeActivityContext executionContext)
This error occurs since we cannot access third party dll’s in CRM context.
To resolve this, we can use either ILMerge(utility for merging multiple .NET assemblies into a single one).
However there is an alternate way to get it done without using third party solution, by using DataContractJsonSerializer in CRM plugin.
Below code will demonstrate you how to use DataContractJsonSerializer in CRM plugin.
To use JSON in CRM plugin
- Create a DataContract class that will define datamodel for JSON data that we receive from Web API.
[DataContract] public class Student { [DataMember] public string FullName { get; set; } [DataMember] public string JobTitle { get; set; } [DataMember] public string Contact { get; set; } [DataMember] public string Country { get; set; } [DataMember] public string ZIPCode { get; set; } }
- Deserialize Data obtained in JSON string to an object
using (MemoryStream DeSerializememoryStream = new MemoryStream()) { //Json String that we get from web api string ResponseString = "{\"FullName\":\"" + "Sam" + "\",\"JobTitle\":\"" + "Developer" + "\",\"Contact\":\"" + "808-124567" + "\",\"Country\":\"" + "India" + "\",\"ZIPCode\":\"" + "400005" + "\"}"; //initialize DataContractJsonSerializer object and pass Student class type to it DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Student)); //user stream writer to write JSON string data to memory stream StreamWriter writer = new StreamWriter(DeSerializememoryStream); writer.Write(ResponseString); writer.Flush(); DeSerializememoryStream.Position = 0; //get the Desrialized data in object of type Student Student SerializedObject = (Student)serializer.ReadObject(DeSerializememoryStream); }
- Serialize Data in JSON string
using (MemoryStream SerializememoryStream = new MemoryStream()) { //create a sample data of type Student Class add details Student NewStudent = new Student(); NewStudent.FullName = "Sam"; NewStudent.JobTitle = "Developer"; NewStudent.Contact = "808-2125454"; NewStudent.Country = "India"; NewStudent.ZIPCode = "400005"; //initialize DataContractJsonSerializer object and pass Student class type to it DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Student)); //write newly created object(NewStudent) into memory stream serializer.WriteObject(SerializememoryStream, NewStudent); //use stream reader to read serialized data from memory stream StreamReader sr = new StreamReader(SerializememoryStream); //get JSON data serialized in string format in string variable string Serializedresult = sr.ReadToEnd(); }
Hope this will help you in using JSON data in Dynamics CRM plugin!
70% of global 2000 companies apply gamification to improve productivity and returns!
Gamifics365 – Spin the magic of games within Microsoft Dynamics 365 CRM to improve user adoption, enhance productivity, and achieve company goals!
Hi,
I have also created a similiar plugin where i am getting json data.
but my requirement is i want use this json data my ms crm account form.
What should i do?
My flow is:
on click of a button a js will be fired which will have this json data and will call a action and action will again trigger my plugin.
I need to display this json data on the account form.
To convert the object to JSON please add below two updated lines in your code to achieve the result.
using (MemoryStream SerializememoryStream = new MemoryStream())
{
//create a sample data of type CaseDetails Class add details
CaseDetails caseD = new CaseDetails();
caseD.CaseNumber = “123”;
caseD.Title = “abc”;
//initialize DataContractJsonSerializer object and pass Student class type to it
var serializer = new DataContractJsonSerializer(caseD.GetType(), new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
});
//write newly created object(NewStudent) into memory stream
serializer.WriteObject(SerializememoryStream, caseD);
SerializememoryStream.Position = 0;
//use stream reader to read serialized data from memory stream
StreamReader sr = new StreamReader(SerializememoryStream);
//get JSON data serialized in string format in string variable
string Serializedresult = sr.ReadToEnd();
}
Hope this helps.
Thanks!
Hello, AM not able to convert object to json with above code, please help.
using (MemoryStream SerializememoryStream = new MemoryStream())
{
//create a sample data of type Student Class add details
CaseDetails caseD = new CaseDetails();
caseD.CaseNumber = “123”;
caseD.Title = “abc”;
//initialize DataContractJsonSerializer object and pass Student class type to it
System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CaseDetails));
//write newly created object(NewStudent) into memory stream
serializer.WriteObject(SerializememoryStream, caseD);
//use stream reader to read serialized data from memory stream
StreamReader sr = new StreamReader(SerializememoryStream);
//get JSON data serialized in string format in string variable
string Serializedresult = sr.ReadToEnd();
}
sr.BaseStream.ReadTimeout ‘sr.BaseStream.ReadTimeout’ threw an exception of type ‘System.InvalidOperationException’
Hi,
To convert the object to JSON please add below two updated lines in your code to achieve the result.
using (MemoryStream SerializememoryStream = new MemoryStream())
{
//create a sample data of type CaseDetails Class add details
CaseDetails caseD = new CaseDetails();
caseD.CaseNumber = “123”;
caseD.Title = “abc”;
//initialize DataContractJsonSerializer object and pass Student class type to it
var serializer = new DataContractJsonSerializer(caseD.GetType(), new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
});
//write newly created object(NewStudent) into memory stream
serializer.WriteObject(SerializememoryStream, caseD);
SerializememoryStream.Position = 0;
//use stream reader to read serialized data from memory stream
StreamReader sr = new StreamReader(SerializememoryStream);
//get JSON data serialized in string format in string variable
string Serializedresult = sr.ReadToEnd();
}
Hope this helps.
Thanks!
has anyone measure the overhead of this convversion? Advisable in using a syncronous call or best for async? Best for limited number of fields or ok for large numbers? impact on memory use?
If you have a very large object then it can slow down or even halt the execution. You should optimize the memory usage. You can refer this article to avoid this situation and to improve the performance.
Hope this helps!