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?