3
votes

I want to write a Dynamics CRM 2011 (online) plugin that takes an address of a contact entity and creates a customeraddress entity from it. It should basically take the customeraddress with address number 1 and create a new identical customeraddress with address number 3 from it. the parent of the newly created customeraddress should be the contact.

I wrote the following plugin to achieve that:

namespace Plugins
{
    using System;
    using System.Linq;
    using System.ServiceModel;
    using Microsoft.Xrm.Sdk;
    using Plugins.Entities;
    using Microsoft.Xrm.Sdk.Query;
    using System.Collections.Generic;

    /// <summary>
    /// AddressMover Plugin.
    /// </summary>    
    public class AddressMoverPlugin : Plugin
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AddressMoverPlugin"/> class.
        /// </summary>
        public AddressMoverPlugin()
            : base(typeof(AddressMoverPlugin))
        {
            base.RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(20, "Update", "contact", new Action<LocalPluginContext>(ExecuteAddressMoverPlugin)));
        }

        /// <summary>
        /// Executes the plug-in.
        /// </summary>
        /// <param name="localContext">The <see cref="LocalPluginContext"/> which contains the
        /// <see cref="IPluginExecutionContext"/>,
        /// <see cref="IOrganizationService"/>
        /// and <see cref="ITracingService"/>
        /// </param>
        protected void ExecuteAddressMoverPlugin(LocalPluginContext localContext)
        {
            if (localContext == null)
            {
                throw new ArgumentNullException("localContext");
            }

            //Extract the tracing service for use in debugging sandboxed plug-ins.
            ITracingService tracingService = localContext.TracingService;

            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = localContext.PluginExecutionContext;
            IOrganizationService service = localContext.OrganizationService;

            Entity entity = context.InputParameters["Target"] as Entity;
            if(entity.Contains("address1_line1"))
            {
                var newAddress = new Entity("customeraddress");
                newAddress.Attributes["name"] = "business";

                // details about type codes can be found here: http://msdn.microsoft.com/en-us/library/aa682922.aspx
                newAddress.Attributes["objecttypecode"] = 2;
                //newAddress.Attributes["addresstypecode"] = "Other";

                newAddress.Attributes["parentid"] = entity.Id;
                tracingService.Trace("parent id is: " + newAddress["parentid"]);

                newAddress.Attributes["addressnumber"] = 3;
                if (entity.Contains("address1_line1")) newAddress["line1"] = entity["address1_line1"];
                if (entity.Contains("address1_line2")) newAddress["line2"] = entity["address1_line2"];
                if (entity.Contains("address1_line3")) newAddress["line3"] = entity["address1_line3"];
                if (entity.Contains("address1_city")) newAddress["city"] = entity["address1_city"];
                if (entity.Contains("address1_stateorprovince")) newAddress["stateorprovince"] = entity["address1_stateorprovince"];
                if (entity.Contains("address1_postalcode")) newAddress["postalcode"] = entity["address1_postalcode"];
                if (entity.Contains("address1_country")) newAddress["country"] = entity["address1_country"];

                service.Create(newAddress);
                //throw new Exception("Start tracing");
            }
        }
    }
}

Please note the line:

                tracingService.Trace("parent id is: " + newAddress["parentid"]);

When I execute this, I get an error message saying that the parentid is not set:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Attribute: parentid cannot be set to NULLDetail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ErrorCode>-2147220989</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <Message>Attribute: parentid cannot be set to NULL</Message>
  <Timestamp>2013-09-05T10:42:46.0285782Z</Timestamp>
  <InnerFault i:nil="true" />
  <TraceText>
[Plugins: Plugins.AddressMoverPlugin]
[2d6c4656-6815-e311-a90e-ac162dbe3ffe: AddressMoverPlugin]
Entered Plugins.AddressMoverPlugin.Execute(), Correlation Id: 65dc4a08-1075-4340-83a5-d35464375348, Initiating User: 1d55dd88-f2f8-e211-a305-ac162db64ac6
Plugins.AddressMoverPlugin is firing for Entity: contact, Message: Update, Correlation Id: 65dc4a08-1075-4340-83a5-d35464375348, Initiating User: 1d55dd88-f2f8-e211-a305-ac162db64ac6
parent id is: b6eb3f86-1716-e311-aa0d-ac162dbe3218
Exception: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Attribute: parentid cannot be set to NULL (Fault Detail is equal to Microsoft.Xrm.Sdk.OrganizationServiceFault)., Correlation Id: 65dc4a08-1075-4340-83a5-d35464375348, Initiating User: 1d55dd88-f2f8-e211-a305-ac162db64ac6
Exiting Plugins.AddressMoverPlugin.Execute(), Correlation Id: 65dc4a08-1075-4340-83a5-d35464375348, Initiating User: 1d55dd88-f2f8-e211-a305-ac162db64ac6

</TraceText>
</OrganizationServiceFault>

The trace obviously contains the output from the code that says that the parentid field is set:

parent id is: b6eb3f86-1716-e311-aa0d-ac162dbe3218

Why do I get this error message saying that the parent id is null when it is not? And how can I avoid it? Is this due to the special behaviour of cutomeraddress entities in the Dynamics CRM?

1

1 Answers

3
votes

Is parentid is an EntityReference?

If yes, then try as below:

EntityReference parentRef = new EntityReference();
parentRef.Id = entity.Id;
parentRef.EntityLogicalName = "contact";

newAddress.Attributes["parentid"] = parentRef;

I hope it will work.