Collection of fixes to version 13689

Feb 10, 2011 at 11:20 PM

Issue #1:

The CustomTargetImage.cs GetValue function has two problems related to null values.  It tries to check whether a given collection contains the specified target with a != null check, but statebag throws an exception key not found so this doesn't work.  Additionally, it expects that any value it is being told to check for always exists.  This isn't necessarily the case - in particular, it's possible to audit a change to a record that has a null primary attribute.

Rewrite it:  Make it a two step process where step 1 is correctly selecting which dynamic entity we will pull the value from, then step 2 is checking if the property exists and if so returning it.

        public string GetValue(IPluginExecutionContext context, string attributeName)
        {
            try
            {
                DynamicEntity de = null;
                switch (context.MessageName.ToLowerInvariant())
                {
                    case "create":
                    case "update":
                        de = (DynamicEntity)context.PostEntityImages["Target"];
                        break;
                    case "delete":
                        if (context.PreEntityImages.Contains("AsynchronousStepPrimaryName")
                            && context.PreEntityImages["AsynchronousStepPrimaryName"] != null)
                            de = ((DynamicEntity)context.PreEntityImages["AsynchronousStepPrimaryName"]);
                        else
                            de = ((DynamicEntity)context.PreEntityImages["Target"]);
                        break;
                    default:
                        if (context.PostEntityImages.Contains("Target")
                            && context.PostEntityImages["Target"] != null)
                            de = ((DynamicEntity)context.PostEntityImages["Target"]);
                        if (context.PreEntityImages.Contains("Target")
                            && context.PreEntityImages["Target"] != null)
                            de = ((DynamicEntity)context.PreEntityImages["Target"]);
                        break;
                }
                if (de != null && de.Properties.Contains(attributeName)) {
                        return CustomDynamicEntity.GetAttributeValue(de.Properties[attributeName], false);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return null;
            }

            return null;
        }

 

Issue #2:

If we try to save an audit on a record whose primary attribute was null, it will blow up. Replace the line that sets auditRecord custom_primary_attribute with:

                var val = this.GetValue(context, res.EntityMetadata.PrimaryField);
                auditRecord.Properties["custom_primary_attribute"] = val ?? "(blank)";

Issue #3: If an attribute has no label, kaboom.  I'm told this can crop up with a timezone rule field.  I think this will fix it, replace the custom display name setting code:

                                    // Set the detail for the attribute detail change.
                                    try {
                                        auditDetail.Properties["custom_display_name"] = metaAttribute.DisplayName.UserLocLabel.Label;
                                    } catch (Exception e) {
                                        auditDetail.Properties["custom_display_name"] = metaAttribute.LogicalName;
                                    }

Issue #4:

Auditing deletes doesn't store the pre-deleted values.

Replace the beginning of the 'process the modified records' loop with a new test and code to dummy up a post dynamicentity:

                // Process the modified records
                if (context.PostEntityImages.Contains("Target")
                    || (context.MessageName.ToLower().Equals("delete")
                        && context.PreEntityImages.Contains("Target")))
                {
                    // Get a reference to the images.
                    DynamicEntity pre = null;
                    DynamicEntity post = null;
                    if (context.PostEntityImages.Contains("Target"))
                    {
                        post = (DynamicEntity)context.PostEntityImages["Target"];
                    }
                    else
                    {
                        post = new DynamicEntity();
                    }

Anybody else have any other bug fixes than these 4?