3
votes

this is a working example of a plugin that I have written for CRM 2011. I have created a 'Create' step in the plugin registration tool for this plugin. This executes fine. I also have an 'Update' step registered for the plugin. This fails to execute because the primary contact returned is null. These steps are both registered as asynchronous.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using System.ServiceModel;
using System.IO;
using System.Net;

namespace CRMNewsletterPlugin
{
    public class NewsletterSignup : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)
            serviceProvider.GetService(typeof(IPluginExecutionContext));

            tracingService.Trace("Begin load");
            // The InputParameters collection contains all the data passed in the message request.
            if (context.InputParameters.Contains("Target") &&
            context.InputParameters["Target"] is Entity)
            {
                tracingService.Trace("We have a target.");
                // Obtain the target entity from the input parmameters.
                Entity entity = (Entity)context.InputParameters["Target"];
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                if (!entity.GetAttributeValue<bool>("new_receivesnewsletter"))
                {
                    try
                    {
                        //check if the account number exist
                        string emailAddress = entity.GetAttributeValue<string>("emailaddress1");
                        EntityReference primaryContact = entity.GetAttributeValue<EntityReference>("primarycontactid");

                        // UPDATE STEP FAILS HERE
                        if (primaryContact == null)
                        {
                            tracingService.Trace("Primary Contact is null");
                        }
                        Entity contact = service.Retrieve("contact", primaryContact.Id, new Microsoft.Xrm.Sdk.Query.ColumnSet(new string[] { "fullname" }));
                        string fullname = contact.GetAttributeValue<string>("fullname");
                        string name = entity.GetAttributeValue<string>("name");
                        WebRequest req = WebRequest.Create("http://localhost");
                        string postData = "cm-name=" + fullname + "&cm-ddurhy-ddurhy=" + emailAddress + "&cm-f-jddkju=" + name;
                        tracingService.Trace(postData);
                        byte[] send = Encoding.Default.GetBytes(postData);
                        req.Method = "POST";
                        req.ContentType = "application/x-www-form-urlencoded";
                        req.ContentLength = send.Length;
                        tracingService.Trace("Sending info");

                        Stream sout = req.GetRequestStream();
                        sout.Write(send, 0, send.Length);
                        sout.Flush();
                        sout.Close();
                        tracingService.Trace("Info sent");
                        WebResponse res = req.GetResponse();
                        StreamReader sr = new StreamReader(res.GetResponseStream());
                        string returnvalue = sr.ReadToEnd();
                        tracingService.Trace(returnvalue);

                        entity.Attributes["new_receivesnewsletter"] = true;
                        service.Update(entity);
                        tracingService.Trace("Newsletter field set");

                    }
                    catch (FaultException ex)
                    {
                        throw new InvalidPluginExecutionException("An error occurred in the plug-in.", ex);
                    }

                }
            }

        }
    }//end class
}
1

1 Answers

10
votes

The entity contained in the InputParameters["Target"] only includes the changed fields that were submitted in the update, not all fields. Your plugin works for Create because InputParameters["Target"] always contains all fields during a Create obviously.

To fix this, you need to add a PreImage to your step in PluginRegistrationTool that includes the primarycontactid field. A PreImage will always include the values for the fields you specify as they were before the update.

The trick is to check for primarycontactid on InputParameters["Target"] first, because that would contain the latest value (if the user updated both new_receivesnewsletter and primarycontactid during the same save, for example). If InputParameters["Target"] doesn't contain primarycontactid, then fall back on your PreImage, accessed something like this (assuming you set your PreImage's alias to "preimage"):

context.PreEntityImages["preimage"].GetAttributeValue<EntityReference>("primarycontactid")

Hope that helps!