shytikov
shytikov

Reputation: 9538

Serialization of MS CRM 2011 plugin execution context to JSON

I'm trying to serialize MS CRM 2011 plugin execution context to JSON to analyze it later (I need to find issue of the error, and I would prefer to have more human-readable form of context dump).

But all my tries leads to a serialization errors, like following:

Newtonsoft.Json.JsonSerializationException: Error getting value from 'ServiceProvider' on 'Plugin+LocalPluginContext

Plugin was generated by Visual Studio add-on. Code was placed inside base class Plugin, like this:

internal void Trace(string message)
{
    if (string.IsNullOrWhiteSpace(message) || this.TracingService == null)
    {
        return;
    }

    if (this.PluginExecutionContext == null)
    {
        this.TracingService.Trace(message);
    }
    else
    {
        this.TracingService.Trace(
            "{0}, Correlation Id: {1}, Initiating User: {2}",
            message,
            this.PluginExecutionContext.CorrelationId,
            this.PluginExecutionContext.InitiatingUserId);

        var jss = new JsonSerializerSettings();
        var dcr = new DefaultContractResolver();

        dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
        jss.ContractResolver = dcr;

        this.TracingService.Trace("Local Context Dump: {0}", JsonConvert.SerializeObject(this, jss));
    }
}

I believe the issue is the general approach. LocalContext is very complex object. JSON.NET is unable to serialize some kind of types. But I cannot nail down this restriction.

Could you please help me to correct the approach?

Upvotes: 2

Views: 2635

Answers (3)

Adel
Adel

Reputation: 91

This works better for me http://www.crmanswers.net/2015/02/json-and-crm-sandbox-plugins.html

string parameter1 = "";
using (MemoryStream memoryStream = new MemoryStream())
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Course));
    serializer.WriteObject(memoryStream, course);
    parameter1 = Encoding.Default.GetString(memoryStream.ToArray());
}

Upvotes: 1

Daryl
Daryl

Reputation: 18895

I wanted to get do something similar, but rather than JSON'ing it, I created by own C# method to covert it to a string, and I just add it to a log: Here it the C# function if it helps.

protected String GetPluginExecutionInfo(IPluginExecutionContext context)
{
    var lines = new List<String>();
    var target = GetTarget<Entity>(context);

    lines.Add("MessageName: " + context.MessageName);
    lines.Add("PrimaryEntityName: " + context.PrimaryEntityName);
    lines.Add("PrimaryEntityId: " + context.PrimaryEntityId);
    lines.Add("BusinessUnitId: " + context.BusinessUnitId);
    lines.Add("CorrelationId: " + context.CorrelationId);
    lines.Add("Depth: " + context.Depth);
    lines.Add("Has Parent Context: " + (context.ParentContext != null));
    lines.Add("InitiatingUserId: " + context.InitiatingUserId);
    AddParameters(lines, context.InputParameters, "Input Parameters");
    lines.Add("IsInTransaction: " + context.IsInTransaction);
    lines.Add("IsolationMode: " + context.IsolationMode);
    lines.Add("Mode: " + context.Mode);
    lines.Add("OperationCreatedOn: " + context.OperationCreatedOn);
    lines.Add("OperationId: " + context.OperationId);
    lines.Add("Organization: " + context.OrganizationName + "(" + context.OrganizationId + ")");
    AddParameters(lines, context.OutputParameters, "Output Parameters");
    AddEntityReference(lines, context.OwningExtension, "OwningExtension");
    AddEntityImages(lines, context.PostEntityImages, "Post Entity Images");
    AddEntityImages(lines, context.PreEntityImages, "Pre Entity Images");
    lines.Add("SecondaryEntityName: " + context.SecondaryEntityName);
    AddParameters(lines, context.SharedVariables, "Shared Variables");
    lines.Add("Stage: " + context.Stage);
    lines.Add("UserId: " + context.UserId);

    if (target == null || target.Attributes.Count == 0)
    {
        lines.Add("Target: Empty ");
    }
    else
    {
        lines.Add("* Target " + target.ToEntityReference().GetNameId() + " *");
        lines.Add(target.ToStringAttributes("    Target[{0}]: {1}"));
    }

    lines.Add("* App Config Values *");
    foreach (var key in ConfigurationManager.AppSettings.AllKeys)
    {
        lines.Add("    [" + key + "]: " + ConfigurationManager.AppSettings[key]);
    }

    return String.Join(Environment.NewLine, lines);
}

private static void AddEntityReference(List<string> nameValuePairs, EntityReference entity, string name)
{
    if (entity != null)
    {
        nameValuePairs.Add(name + ": " + entity.GetNameId());
    }
}

private static void AddEntityImages(List<string> nameValuePairs, EntityImageCollection images, string name)
{
    if (images != null && images.Count > 0)
    {
        nameValuePairs.Add("** " + name + " **");
        foreach (var image in images)
        {
            if (image.Value == null || image.Value.Attributes.Count == 0)
            {
                nameValuePairs.Add("    Image[" + image.Key + "] " + image.Value + ": Empty");
            }
            else
            {
                nameValuePairs.Add("*   Image[" + image.Key + "] " + image.Value.ToEntityReference().GetNameId() + "   *
                nameValuePairs.Add(image.Value.ToStringAttributes("        Entity[{0}]: {1}"));
            }
        }
    }
    else
    {
        nameValuePairs.Add(name + ": Empty");
    }
}

private static void AddParameters(List<string> nameValuePairs, ParameterCollection parameters, string name)
{
    if (parameters != null && parameters.Count > 0)
    {
        nameValuePairs.Add("* " + name + " *");
        foreach (var param in parameters)
        {
            nameValuePairs.Add("    Param[" + param.Key + "]: " + param.Value);
        }
    }
    else
    {
        nameValuePairs.Add(name + ": Empty");
    }
}

public static String ToStringAttributes(this Entity entity, string attributeFormat = "[{0}]: {1}")
{
    return String.Join(Environment.NewLine, entity.Attributes.Select(att => 
        String.Format(attributeFormat, att.Key, GetAttributeValue(att.Value))));
}

private static string GetAttributeValue(object value)
{
    if (value == null)
    {
        return "Null";
    }

    var osv = value as OptionSetValue;
    if (osv != null)
    {
        return osv.Value.ToString();
    }

    var entity = value as EntityReference;
    if (entity != null)
    {
        return entity.GetNameId();
    }

    return value.ToString();
}

Upvotes: 4

Andrew Butenko
Andrew Butenko

Reputation: 5446

Are you aware of Plugin Debugger approach? Recheck this article that describes how to debug plugins that are located even in CRM Online.

Upvotes: 2

Related Questions