locked
CRM 2011: plugin in sandbox mode works incorrectly with EntityCollection RRS feed

  • Question

  • Hi guys,

    i have strange bug with plugin (only in sandbox mode):

    1. load current entity from DB

    2. mix attributes loaded entity and current entity in current entity

     

                foreach (KeyValuePair<string, object> attr in secondaryEntity.Attributes)
                {
                    string key = attr.Key;
    
                    if (!mainEntity.Attributes.ContainsKey(key))
                    {
                        object value = attr.Value;
    
                        //if (value is EntityCollection)
                            mainEntity.Attributes[key] = value;
                    }
                }
    

     


    after work of plugin the system generations an exception:

     

    Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: System.Runtime.Serialization.SerializationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #31550DA4Detail: 
    <OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
      <ErrorCode>-2147220970</ErrorCode>
      <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
      <Message>System.Runtime.Serialization.SerializationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #31550DA4</Message>
      <Timestamp>2011-10-10T09:25:54.6595704Z</Timestamp>
      <InnerFault i:nil="true" />
      <TraceText>
    
    [CDMBase.Plugins: CDMCRM11.Appointment_Update_Pre_SetPromotionStatus]
    [32caaa30-e5e9-e011-9fb1-000c29b30c2d: Appointment_Update_Pre_SetPromotionStatus]
    
    
    </TraceText>
    </OrganizationServiceFault>
    


    it only happens when there are fields of type 'EntityCollection' ( in 'appointment' case they are requiredattendees, optionalattendees, organizer)

     

    What do you think about this?

    Thanks in advance

     

     

     

    Monday, October 10, 2011 9:27 AM

All replies

  • There should be an inner exception that you can see and if might give yiou better details on the error. Have you debugged into the plugin and inspected the variables?
    MS CRM Bing'd - http://bingsoft.wordpress.com
    Useful Tools  CRM 4 to CRM 2011 JavaScript Converter Tool
    CRM 2011 OData Query Designer
    CRM Forum Guidance on how to Help Us Help You
    Monday, October 10, 2011 12:04 PM
    Moderator
  • Thanks for the answer. Of course, I debugged it, but the plugin does not generate exception (exception occurs after plugin finished its work)
    Monday, October 10, 2011 12:39 PM
  • I am relatively new to 2011. so discard my reply if it doenst make sense.

    I would give ur issue a try by using the tracing service for the plugin.

    Just to make sure that the plugin is not generating an exception.

     

    Wednesday, October 12, 2011 9:41 AM
  • Hi,

    Did you ever get a resolution to this issue, I think I've seen something similar?

    Thanks

     

    Thursday, January 19, 2012 9:56 AM
  • Hi Alexander,

    Have you find a solution to this error? I'm working on a plugin for Appointment entity that adds Regarding Account's Primary Contact to Required Attendees list and vice versa, i.e. adds the Account of Regarding Contact to Required Attendees. After plugin execution I'm getting the same error.

    Thanks

    Lilit

    Wednesday, June 6, 2012 2:07 PM
  • Hello Alexander A. Sharygin:

    Could you just paste your block of code that is creating problem, like retrieve method.


    Saurabh Gupta, MS CRM 2011 Software Development Engineer

    Wednesday, June 6, 2012 3:48 PM
  • If any of you folks who are experiencing this issue can share the code, we will be able to track down the issue.

    Thursday, June 7, 2012 10:23 PM
  • I too was receiving a serialization error when early binding in the sandbox.  Fine when not in the sandbox.  The error was occurring on a RetrieveMultiple that queried the statecode of a custom entity and using the enum generated by the crmsvcutil tool.  To work around it, I changed this line...

    query.AddAttributeValue("statecode", qgan_counterState.Active);

    to

    query.AddAttributeValue("statecode", 0);

    I'm sure there are more elegant solutions but this worked for me.  Instinct tells me that something is not quite right with the output from crmsvcutil tool but that's above me.

    FYI... My error is below


    EXIT
     Tracking ID: 999D9079/394DF390/1
     Source: w3wp.exe (4940)
     Function: ISandboxSdkListener.Execute\RetrieveMultiple [0.001]
     Origin: DCCRM2011; Microsoft.Crm.Sandbox.WorkerProcess.exe (5912)
     Additional Data: Exception: System.Runtime.Serialization.SerializationException: Element 'http://schemas.microsoft.com/2003/10/Serialization/Arrays:anyType' contains data from a type that maps to the name 'QGate.Dynamics.Autonumber:qgan_counterState'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'qgan_counterState' and namespace 'QGate.Dynamics.Autonumber'.

    

    Thursday, June 14, 2012 10:29 AM
  • Hi all, I am also experiencing the same issue with organizers/requiredattendees on appointments.

    I found an article about it that suggested removing all references to the activityparty svcutil generated class: http://nicolagrillo.blogspot.ca/2012/01/crm-2011-activityparty.html

    That did not work, but I have not tried completely removing all reference to the class in my assembly as that is an unrealistic solution in my situation.

    My error from the server trace: important part extracted for visibility: (Rhett, this is that inner exception you asked for originally)

    System.Runtime.Serialization.SerializationException: Element 'http://schemas.microsoft.com/xrm/2011/Contracts:Entity' contains data from a type that maps to the name 'MyNamespace:ActivityParty'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'ActivityParty' and namespace 'MyNamespace'.

    >System.Runtime.Serialization.SerializationException: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #5BCA670D: System.Runtime.Serialization.SerializationException: Element 'http://schemas.microsoft.com/xrm/2011/Contracts:Entity' contains data from a type that maps to the name 'MyNamespace:ActivityParty'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'ActivityParty' and namespace 'MyNamespace'.
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
    >   at ReadArrayOfEntityFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
    >   at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
    >   at ReadKeyValuePairOfstringanyTypeFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
    >   at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
    >   at ReadAttributeCollectionFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
    >   at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
    >   at ReadEntityFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
    >   at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
    >   at ReadKeyValuePairOfstringanyTypeFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
    >   at System.Runtime.Serialization.ClassDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Int32 id, RuntimeTypeHandle declaredTypeHandle, String name, String ns)
    >   at ReadParameterCollectionFromXml(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString , XmlDictionaryString , CollectionDataContract )
    >   at System.Runtime.Serialization.CollectionDataContract.ReadXmlValue(XmlReaderDelegator xmlReader, XmlObjectSerializerReadContext context)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
    >   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
    >   at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
    >   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
    >   at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader reader)
    >   at Microsoft.Crm.Sandbox.SandboxUtility.DeserializeDataContract[T](Byte[] serializedDataContract, Assembly proxyTypesAssembly)
    >   at Microsoft.Crm.Sandbox.SandboxPluginExecutionContext.get_InputParameters()
    >   at Microsoft.Crm.Sandbox.SandboxPluginExecutionContext.Merge(IPluginExecutionContext originalContext)
    >   at Microsoft.Crm.Sandbox.SandboxPlugin.Execute(IServiceProvider serviceProvider)

    Anyone end up resolving this or finding a work around?

    I'm working on isolating a reproducible sample and will post it when I can.

    I am very curious why it fails in isolation mode and works in non isolation. I hope the stack trace triggers a thought from someone.

    Thursday, June 14, 2012 4:08 PM
  • Without seeing code, I can't provide a specific reason why your code doesn't work. However, there are several reasons why your code may not work:

    1. The assembly-level attribute, [assembly: ProxyTypesAssemblyAttribute], is missing; without this attribute the plug-in infrastructure doesn't know that you want to use early bound classes.
    2. An early bound class is assigned to one of the collections exposed by IPluginExecutionContext. The plug-in infrastructure currently doesn't run any conversion logic on the IPluginExecutionContext, which means that the Sandbox infrastructure will encounter a serialization exception when there it references an early bound class. The reason that this works in non-isolated cases is because the IPluginExecutionContext is never serialized. Since the generated classes inherit from Entity, any code that is meant to work with late bound classes will also work with early bound classes. Consider the following code snippets (from a plug-in registered on Create of Email):

      Succeeds
      Late bound classes exposed by the IPluginExecutionContext are converted to early bound classes, which doesn't affect the instances found in the IPluginExecutionContext collections.
      {
      IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); Email email = ((Entity)context.InputParameters["Target"]).ToEntity<Email>(); ActivityParty recipient = email.To.FirstOrDefault(); // Execute code ... }

      Won't work
      The "To" property will internally create an EntityCollection with the early bound class. Since the "email" entity is using the same instance of the Attributes collection as context.InputParameters["Target"], an early bound class is now being referenced by IPluginExecutionContext.

      {
      IPluginExecutionContext context =
      (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
      Email email = ((Entity)context.InputParameters["Target"]).ToEntity<Email>();
      email.To = new ActivityParty[] { new ActivityParty() };
      }

    John, your code failed for a completely different reason. The query model only supports the underlying primitive data types. You'll see this same behavior if you execute code against the web service (instead of using a plug-in). In your example, the StateCode is a Picklist attribute, which is returned from the server as OptionSetValue (even though the early bound class exposes it as an enum). The underlying value for an OptionSetValue is int, which is why querying with "0" worked.

    Michael

    Thursday, June 14, 2012 5:02 PM
  • Thank you Michael, that was the insight I needed! 

    For any others interested I created a new late bound activityparty:

    Entity lateBoundOrganizer = new Entity("activityparty");
    lateBoundOrganizer.Attributes = crmOrganizer.Attributes;
    lateBoundOrganizer.Id = crmOrganizer.Id;
    lateBoundOrganizer.LogicalName = crmOrganizer.LogicalName;
    
    // now use lateBoundOrganizer to assign where you were assigning crmOrganizer before.

    http://benpatterson1.blogspot.ca/2012/06/crm-2011-activity-party-and.html


    • Edited by BenPatterson1 Tuesday, June 26, 2012 5:22 PM link to my blog post on it
    Thursday, June 14, 2012 6:06 PM
  • Thanks Michael. I'll stop being lazy and avoid early binding in my plugins from now on :)
    Friday, June 15, 2012 9:22 AM
  • You should continue to use early binding in your plug-ins (the benefits outweigh the costs by far). You just need to be aware of some of the caveats so that you convert when necessary.

    In your example, if you use code like this it will work: query.AddAttributeValue("statecode", (int)qgan_counterState.Active);

    In my example, you can do something like this: email["to"] = new EntityCollection(new Entity[] { party.ToEntity<Entity>() });

    • Proposed as answer by leSasch Wednesday, April 23, 2014 8:12 AM
    Friday, June 15, 2012 4:26 PM
  • Hi,

    Another reason for this to happen is if your code is throwing a custom exception. Let's say that you have something like "MyCustomCRMException", which inherits from Exception. Because MyCustomCRMException is an unknown type within your plugin, you will get that error with very few information and traces.

    Regards

    • Proposed as answer by NathanBenelli Thursday, October 10, 2013 6:00 PM
    Wednesday, September 18, 2013 2:26 PM
  • Thank you so much Michael! You saved my day.

    I encountered this same error while trying to use Jonas Rapp's code to execute server side code in a plugin: http://jonasrapp.cinteros.se/2012/07/execute-server-side-code-from-javascript.html

    The part where the result entity (i.e. serverfunction) is returned (see code snippet below) fails in the Sandboxed plugin:

    EntityCollection resultCollection = (EntityCollection)context.OutputParameters["BusinessEntityCollection"];
    resultCollection.Entities.Clear();
    resultCollection.Entities.Add(serverfunction);
    context.OutputParameters["BusinessEntityCollection"] = resultCollection;

    Converting the early bound entity back to the generic Entity type by using the '.ToEntity<Entity>()' trick worked for me. Like so:

    EntityCollection resultCollection = (EntityCollection)context.OutputParameters["BusinessEntityCollection"];
    resultCollection.Entities.Clear();
    resultCollection.Entities.Add(serverfunction.ToEntity<Entity>());
    context.OutputParameters["BusinessEntityCollection"] = resultCollection;



    Monday, February 10, 2014 9:22 AM