Exemplo n.º 1
0
        public IEnumerable <DataModel.AuditLogModel> ToDwItems(IOrganizationService service, AuditDetail source, int langCode, IJobTime job)
        {
            List <DataModel.AuditLogModel> items = new List <DataModel.AuditLogModel>();
            var audtLog = source;

            if (source.GetType() != typeof(AttributeAuditDetail))
            {
                return(items);
            }

            var               attr       = (AttributeAuditDetail)source;
            Entity            record     = (Entity)source.AuditRecord;
            AuditLogModelBase baseEntity = new AuditLogModelBase();
            var               modified   = attr.AuditRecord.GetAttributeValue <EntityReference>("userid");

            baseEntity.EntityType     = record.GetAttributeValue <EntityReference>("objectid").LogicalName;
            baseEntity.EntityTypeDesc = record.FormattedValues["objecttypecode"];
            baseEntity.ChangeDateTime = attr.AuditRecord.GetAttributeValue <DateTime>("createdon");
            baseEntity.ChangeType     = record.FormattedValues["operation"];
            baseEntity.CrmAuditId     = audtLog.AuditRecord.Id;
            baseEntity.ModifiedByName = modified.Name;
            baseEntity.ModifiedByID   = modified.Id;
            baseEntity.JobId          = job.JobId;
            baseEntity.ModifiedOn     = DateTime.UtcNow;
            AddToListItems(service, baseEntity.EntityType, langCode, source, items, baseEntity);
            return(items);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Displays audit change history details on the console.
        /// </summary>
        /// <param name="detail"></param>
        //<snippetAuditing2>
        private static void DisplayAuditDetails(AuditDetail detail)
        {
            // Write out some of the change history information in the audit record.
            Audit record = (Audit)detail.AuditRecord;

            Console.WriteLine("\nAudit record created on: {0}", record.CreatedOn.Value.ToLocalTime());
            Console.WriteLine("Entity: {0}, Action: {1}, Operation: {2}",
                              record.ObjectId.LogicalName, record.FormattedValues["action"],
                              record.FormattedValues["operation"]);

            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail))
            {
                var attributeDetail = (AttributeAuditDetail)detail;

                // Display the old and new attribute values.
                foreach (KeyValuePair <String, object> attribute in attributeDetail.NewValue.Attributes)
                {
                    String oldValue = "(no value)", newValue = "(no value)";

                    //TODO Display the lookup values of those attributes that do not contain strings.
                    if (attributeDetail.OldValue.Contains(attribute.Key))
                    {
                        oldValue = attributeDetail.OldValue[attribute.Key].ToString();
                    }

                    newValue = attributeDetail.NewValue[attribute.Key].ToString();

                    Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                                      attribute.Key, oldValue, newValue);
                }

                foreach (KeyValuePair <String, object> attribute in attributeDetail.OldValue.Attributes)
                {
                    if (!attributeDetail.NewValue.Contains(attribute.Key))
                    {
                        String newValue = "(no value)";

                        //TODO Display the lookup values of those attributes that do not contain strings.
                        String oldValue = attributeDetail.OldValue[attribute.Key].ToString();

                        Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                                          attribute.Key, oldValue, newValue);
                    }
                }
            }
            Console.WriteLine();
        }
        /// <summary>
        /// Displays audit change history details on the console.
        /// </summary>
        /// <param name="detail"></param>
        private static void DisplayAuditDetails(CrmServiceClient service, AuditDetail detail)
        {
            // Write out some of the change history information in the audit record.
            var record = (Audit)detail.AuditRecord;

            Console.WriteLine($"\nAudit record created on: {record.CreatedOn.Value.ToLocalTime()}");
            Console.WriteLine($"Entity: {record.ObjectId.LogicalName}, Action: {record.FormattedValues["action"]}, Operation: {record.FormattedValues["operation"]}");
            Console.WriteLine($"Operation performed by {record.UserId.Name}");

            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail))
            {
                var    attributeDetail = (AttributeAuditDetail)detail;
                string oldValue = "(no value)", newValue = "(no value)";

                // Display the old and new attribute values.
                foreach (KeyValuePair <string, object> attribute in attributeDetail.NewValue.Attributes)
                {
                    if (attributeDetail.OldValue.Contains(attribute.Key))
                    {
                        oldValue = GetTypedValueAsString(attributeDetail.OldValue[attribute.Key]);
                    }

                    newValue = GetTypedValueAsString(attributeDetail.NewValue[attribute.Key]);

                    Console.WriteLine($"Attribute: {attribute.Key}, old value: {oldValue}, new value: {newValue}");
                }

                foreach (KeyValuePair <String, object> attribute in attributeDetail.OldValue.Attributes)
                {
                    if (!attributeDetail.NewValue.Contains(attribute.Key))
                    {
                        newValue = "(no value)";

                        oldValue = GetTypedValueAsString(attributeDetail.OldValue[attribute.Key]);

                        Console.WriteLine($"Attribute: {attribute.Key}, old value: {oldValue}, new value: {newValue}");
                    }
                }
            }
            Console.WriteLine();
        }
Exemplo n.º 4
0
        private List <AuditHistory> GetRecordChanges(AuditDetail detail, string recordKeyValue = "")
        {
            AuditHistory        auditHistory = new AuditHistory();
            Entity              record       = (Entity)detail.AuditRecord;
            List <AuditHistory> lsChanges    = new List <AuditHistory>();

            // Write out some of the change history information in the audit record.


            Console.WriteLine("\nAudit record created on: {0}", record.GetAttributeValue <DateTime>("createdon").ToLocalTime());
            Console.WriteLine("Entity: {0}, Action: {1}, Operation: {2}, Transaction Id {3}", record.GetAttributeValue <EntityReference>("objectid").LogicalName, record.FormattedValues["action"], record.FormattedValues["operation"], record.GetAttributeValue <Guid>("auditid").ToString());


            Console.WriteLine("USER : {0}", record.GetAttributeValue <EntityReference>("userid").Name);
            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail) && ((AttributeAuditDetail)detail).NewValue != null)
            {
                var attributeDetail = (AttributeAuditDetail)detail;

                // Display the old and new attribute values.
                foreach (KeyValuePair <String, object> attribute in attributeDetail.NewValue.Attributes)
                {
                    auditHistory = new AuditHistory();
                    FillAuditRecordWithBaseInfo(auditHistory, record);
                    auditHistory.RecordKeyValue = recordKeyValue;
                    String oldValue = "(no value)", newValue = "(no value)";

                    //TODO Display the lookup values of those attributes that do not contain strings.
                    if (attributeDetail.OldValue.Contains(attribute.Key))
                    {
                        oldValue = GetValue(attributeDetail.OldValue, attribute.Key);
                    }

                    newValue = GetValue(attributeDetail.NewValue, attribute.Key);

                    Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}", attribute.Key, oldValue, newValue);


                    auditHistory.OldValue      = oldValue;
                    auditHistory.NewValue      = newValue;
                    auditHistory.AttributeName = attribute.Key;



                    lsChanges.Add(auditHistory);
                }

                foreach (KeyValuePair <String, object> attribute in attributeDetail.OldValue.Attributes)
                {
                    if (!attributeDetail.NewValue.Contains(attribute.Key))
                    {
                        auditHistory = new AuditHistory();
                        FillAuditRecordWithBaseInfo(auditHistory, record);
                        String newValue = "(no value)";

                        //TODO Display the lookup values of those attributes that do not contain strings.
                        String oldValue = GetValue(attributeDetail.OldValue, attribute.Key);// attributeDetail.OldValue[attribute.Key].ToString();
                        Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}", attribute.Key, oldValue, newValue);

                        auditHistory.OldValue      = oldValue;
                        auditHistory.NewValue      = newValue;
                        auditHistory.AttributeName = attribute.Key;

                        lsChanges.Add(auditHistory);
                    }
                }
            }
            else
            {
                auditHistory = null;
            }
            return(lsChanges);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Displays audit change history details on the console.
        /// </summary>
        /// <param name="detail"></param>
        //<snippetAuditing2>
        private static void DisplayAuditDetails(AuditDetail detail)
        {
            // Write out some of the change history information in the audit record. 
            Audit record = (Audit)detail.AuditRecord;

            Console.WriteLine("\nAudit record created on: {0}", record.CreatedOn.Value.ToLocalTime());
            Console.WriteLine("Entity: {0}, Action: {1}, Operation: {2}",
                record.ObjectId.LogicalName, record.FormattedValues["action"],
                record.FormattedValues["operation"]);

            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();
            if (detailType == typeof(AttributeAuditDetail))
            {
                var attributeDetail = (AttributeAuditDetail)detail;

                // Display the old and new attribute values.
                foreach (KeyValuePair<String, object> attribute in attributeDetail.NewValue.Attributes)
                {
                    String oldValue = "(no value)", newValue = "(no value)";

                    //TODO Display the lookup values of those attributes that do not contain strings.
                    if (attributeDetail.OldValue.Contains(attribute.Key))
                        oldValue = attributeDetail.OldValue[attribute.Key].ToString();

                    newValue = attributeDetail.NewValue[attribute.Key].ToString();

                    Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                        attribute.Key, oldValue, newValue);
                }

                foreach (KeyValuePair<String, object> attribute in attributeDetail.OldValue.Attributes)
                {
                    if (!attributeDetail.NewValue.Contains(attribute.Key))
                    {
                        String newValue = "(no value)";

                        //TODO Display the lookup values of those attributes that do not contain strings.
                        String oldValue = attributeDetail.OldValue[attribute.Key].ToString();

                        Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                            attribute.Key, oldValue, newValue);
                    }
                }
            }
            Console.WriteLine();
        }
        private void DisplayAndAddToXMLFileAuditDetails(AuditDetail detail)
        {
            // Write out some of the information in each audit record.
            // and add this information to the XML file
            Audit record = (Audit)detail.AuditRecord;

            DisplayAndAddToXMLFileAudit(record, false);

            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail))
            {
                var attributeDetail = (AttributeAuditDetail)detail;

                // Start attributes XML Node
                textWriter.WriteStartElement("attributes", "");

                // Display the old and new attribute values.
                foreach (KeyValuePair <String, object> attribute in attributeDetail.NewValue.Attributes)
                {
                    String oldValue = "(no value)", newValue = "(no value)", userName = "******";

                    if (attributeDetail.OldValue.Contains(attribute.Key))
                    {
                        oldValue = attributeDetail.OldValue[attribute.Key].ToString();
                    }

                    if (attributeDetail.AuditRecord.Attributes.Contains("userid"))
                    {
                        userName = ((EntityReference)attributeDetail.AuditRecord.Attributes["userid"]).Name;
                    }

                    newValue = attributeDetail.NewValue.FormattedValues.Contains(attribute.Key) ?
                               attributeDetail.NewValue.FormattedValues[attribute.Key].ToString() :
                               attributeDetail.NewValue[attribute.Key].ToString();

                    if (oldValue == "Microsoft.Xrm.Sdk.EntityReference")
                    {
                        EntityReference temp = (EntityReference)attributeDetail.NewValue[attribute.Key];
                        oldValue = temp.Name;
                    }

                    if (newValue == "Microsoft.Xrm.Sdk.EntityReference")
                    {
                        EntityReference temp = (EntityReference)attributeDetail.NewValue[attribute.Key];
                        newValue = temp.Name;
                    }

                    Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                                      attribute.Key, oldValue, newValue);

                    #region Add Audit details for New Values to XML file

                    // Start attribute XML Node
                    textWriter.WriteStartElement("attribute", "");

                    // Add name XML Node
                    textWriter.WriteStartElement("name", "");
                    textWriter.WriteString(attribute.Key);
                    textWriter.WriteEndElement();

                    // Add oldValue XML Node
                    textWriter.WriteStartElement("oldValue", "");
                    textWriter.WriteString(oldValue);
                    textWriter.WriteEndElement();

                    // Add newValue XML Node
                    textWriter.WriteStartElement("newValue", "");
                    textWriter.WriteString(newValue);
                    textWriter.WriteEndElement();

                    // Add userName XML Node
                    textWriter.WriteStartElement("userName", "");
                    textWriter.WriteString(userName);
                    textWriter.WriteEndElement();

                    // End attribute XML Node
                    textWriter.WriteEndElement();

                    #endregion
                }

                foreach (KeyValuePair <String, object> attribute in attributeDetail.OldValue.Attributes)
                {
                    if (!attributeDetail.NewValue.Contains(attribute.Key))
                    {
                        String newValue = "(no value)", userName = "******";

                        String oldValue = attributeDetail.OldValue.FormattedValues.Contains(attribute.Key) ?
                                          attributeDetail.OldValue.FormattedValues[attribute.Key].ToString() :
                                          attributeDetail.OldValue[attribute.Key].ToString();

                        if (oldValue == "Microsoft.Xrm.Sdk.EntityReference")
                        {
                            EntityReference temp = (EntityReference)attributeDetail.OldValue[attribute.Key];
                            oldValue = temp.Name;
                        }

                        if (attributeDetail.AuditRecord.Attributes.Contains("userid"))
                        {
                            userName = ((EntityReference)attributeDetail.AuditRecord.Attributes["userid"]).Name;
                        }

                        Console.WriteLine("Attribute: {0}, old value: {1}, new value: {2}",
                                          attribute.Key, oldValue, newValue);

                        #region Add Audit details for Old Values to XML file

                        // Start attribute XML Node
                        textWriter.WriteStartElement("attribute", "");

                        // Add name XML Node
                        textWriter.WriteStartElement("name", "");
                        textWriter.WriteString(attribute.Key);
                        textWriter.WriteEndElement();

                        // Add oldValue XML Node
                        textWriter.WriteStartElement("oldValue", "");
                        textWriter.WriteString(oldValue);
                        textWriter.WriteEndElement();

                        // Add newValue XML Node
                        textWriter.WriteStartElement("newValue", "");
                        textWriter.WriteString(newValue);
                        textWriter.WriteEndElement();

                        // Add userName XML Node
                        textWriter.WriteStartElement("userName", "");
                        textWriter.WriteString(userName);
                        textWriter.WriteEndElement();

                        // End attribute XML Node
                        textWriter.WriteEndElement();

                        #endregion
                    }
                }

                // End attributes XML Node
                textWriter.WriteEndElement();
            }
            Console.WriteLine();

            // End audit XML Node
            textWriter.WriteEndElement();
        }
Exemplo n.º 7
0
        private void AddToListItems(IOrganizationService service, string entityName, int langCode, AuditDetail detail, List <DataModel.AuditLogModel> items, AuditLogModelBase auditLogModelBase)
        {
            var              crmAttrbites = _schema.GetEntityFields(service, _log, entityName, langCode);
            AuditLogModel    auditLogModel;
            IFieldDesc       fieldDesc        = null;
            CrmAttrbite      attr             = null;
            CrmValueAttrbite crmValueAttrbite = null;
            Entity           record           = (Entity)detail.AuditRecord;
            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail))
            {
                var attributeDetail = (AttributeAuditDetail)detail;
                if (attributeDetail.NewValue != null && attributeDetail.NewValue.Attributes.Any())
                {
                    // Display the old and new attribute values.
                    foreach (KeyValuePair <String, object> attribute in attributeDetail.NewValue.Attributes)
                    {
                        fieldDesc        = null;
                        crmValueAttrbite = null;
                        attr             = crmAttrbites.Where(a => a.FieldName == attribute.Key).FirstOrDefault();
                        if (attr == null)
                        {
                            continue;
                        }
                        auditLogModel            = new AuditLogModel();
                        auditLogModel.AuditLogId = Guid.NewGuid();
                        auditLogModelBase.CopyTo(auditLogModel);
                        auditLogModel.FieldDesc       = attr.DisplayName;
                        auditLogModel.FieldSchemaName = attr.FieldName;
                        if (attributeDetail.OldValue.Contains(attribute.Key))
                        {
                            fieldDesc = _factoryFieldsValue.GetFieldDesc(attribute.Key, attr, attributeDetail.OldValue);
                            if (fieldDesc != null)
                            {
                                crmValueAttrbite       = fieldDesc.GetValue(attribute.Key.ToString(), attributeDetail.OldValue);
                                auditLogModel.OldValue = crmValueAttrbite.FieldValue;
                            }
                        }
                        fieldDesc = _factoryFieldsValue.GetFieldDesc(attribute.Key, attr, attributeDetail.NewValue);
                        if (fieldDesc != null)
                        {
                            crmValueAttrbite       = fieldDesc.GetValue(attribute.Key.ToString(), attributeDetail.NewValue);
                            auditLogModel.NewValue = crmValueAttrbite.FieldValue;
                        }
                        items.Add(auditLogModel);
                    }
                }
                // for data who clear (the old value was data and new value was empty)
                if (attributeDetail.OldValue != null && attributeDetail.OldValue.Attributes.Any())
                {
                    foreach (KeyValuePair <String, object> attribute in attributeDetail.OldValue.Attributes)
                    {
                        if (attributeDetail.NewValue != null && !attributeDetail.NewValue.Contains(attribute.Key))
                        {
                            fieldDesc                = null;
                            crmValueAttrbite         = null;
                            attr                     = crmAttrbites.Where(a => a.FieldName == attribute.Key).FirstOrDefault();
                            auditLogModel            = new AuditLogModel();
                            auditLogModel.AuditLogId = Guid.NewGuid();
                            auditLogModelBase.CopyTo(auditLogModel);
                            auditLogModel.FieldDesc       = attr.DisplayName;
                            auditLogModel.FieldSchemaName = attr.FieldName;

                            fieldDesc = _factoryFieldsValue.GetFieldDesc(attribute.Key, attr, attributeDetail.OldValue);
                            if (fieldDesc != null)
                            {
                                crmValueAttrbite       = fieldDesc.GetValue(attribute.Key.ToString(), attributeDetail.OldValue);
                                auditLogModel.OldValue = crmValueAttrbite.FieldValue;
                                auditLogModel.NewValue = "";
                            }
                            items.Add(auditLogModel);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// This is to Fetch the Audit details
        /// </summary>
        /// <param name="detail">The Audit Detail</param>
        private void FetchAuditDetails(AuditDetail detail)
        {
            int counter = 0;
            List <AuditDetails> lstDetails = new List <AuditDetails>();
            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail))
            {
                var    attributeDetail      = (AttributeAuditDetail)detail;
                string AttributeDisplayName = "";
                if (attributeDetail.NewValue != null)
                {
                    foreach (KeyValuePair <string, object> attribute in attributeDetail.NewValue.Attributes)
                    {
                        counter = counter + 1;
                        string oldValue = string.Empty, newValue = string.Empty;
                        //*********************GET AttributeDisplayName
                        string AttrFullLogicalName = EntityLogicalName + ":" + attribute.Key;
                        if (!AttrFullNameDispNameMap.ContainsKey(AttrFullLogicalName))
                        {
                            for (int iCnt = 0; iCnt < EntityMetaResponse.EntityMetadata.Attributes.ToList().Count; iCnt++)
                            {
                                if (EntityMetaResponse.EntityMetadata.Attributes.ToList()[iCnt].DisplayName.LocalizedLabels.Count > 0)
                                {
                                    if (EntityMetaResponse.EntityMetadata.Attributes.ToList()[iCnt].LogicalName == attribute.Key)
                                    {
                                        AttributeDisplayName = EntityMetaResponse.EntityMetadata.Attributes.ToList()[iCnt].DisplayName.LocalizedLabels[0].Label;
                                        if (AttributeDisplayName == "" || AttributeDisplayName == null)
                                        {
                                            Console.WriteLine("################ Attribute Display name is empty ");
                                        }
                                        AttrFullNameDispNameMap.Add(AttrFullLogicalName, AttributeDisplayName);
                                        string logicalName = EntityMetaResponse.EntityMetadata.Attributes.ToList()[iCnt].LogicalName;
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            AttrFullNameDispNameMap.TryGetValue(AttrFullLogicalName, out AttributeDisplayName);
                        }
                        //************************************
                        if (attributeDetail.OldValue.Contains(attribute.Key))
                        {
                            oldValue = attributeDetail.OldValue[attribute.Key].ToString();
                            if (oldValue == "Microsoft.Xrm.Sdk.OptionSetValue" || oldValue == "Microsoft.Xrm.Sdk.EntityReference" || oldValue == "Microsoft.Xrm.Sdk.Money")
                            {
                                if (attributeDetail.OldValue.FormattedValues.Keys.Contains(attribute.Key))
                                {
                                    oldValue = attributeDetail.OldValue.FormattedValues[attribute.Key];
                                }
                                else
                                {
                                    oldValue = "Record Unavailable";
                                }
                            }
                        }
                        if (attributeDetail.NewValue.Contains(attribute.Key))
                        {
                            newValue = attributeDetail.NewValue[attribute.Key].ToString();
                            if (newValue == "Microsoft.Xrm.Sdk.OptionSetValue" || newValue == "Microsoft.Xrm.Sdk.EntityReference" || newValue == "Microsoft.Xrm.Sdk.Money")
                            {
                                if (attributeDetail.NewValue.FormattedValues.Keys.Contains(attribute.Key))
                                {
                                    newValue = attributeDetail.NewValue.FormattedValues[attribute.Key];
                                }
                                else
                                {
                                    newValue = "Record Unavailable";
                                }
                            }
                        }
                        DataRow dr = this.dtcombined.NewRow();
                        dr["AuditId"]      = detail.AuditRecord.Id;
                        dr["ChangedDate"]  = Convert.ToString(detail.AuditRecord.GetAttributeValue <DateTime>("createdon"));
                        dr["Event"]        = detail.AuditRecord.FormattedValues["operation"];
                        dr["ChangedBy"]    = detail.AuditRecord.GetAttributeValue <EntityReference>("userid").Name;
                        dr["ChangedField"] = AttributeDisplayName;// attribute.Key;
                        dr["OldValue"]     = oldValue;
                        dr["NewValue"]     = newValue;
                        this.dtcombined.Rows.Add(dr);
                    }
                }
                else
                {
                    if (attributeDetail.OldValue != null)
                    {
                        foreach (KeyValuePair <string, object> attribute in attributeDetail.OldValue.Attributes)
                        {
                            string oldValue = string.Empty;
                            if (attributeDetail.OldValue.Contains(attribute.Key))
                            {
                                if (attributeDetail.OldValue.FormattedValues.Keys.Contains(attribute.Key))
                                {
                                    oldValue = attributeDetail.OldValue.FormattedValues[attribute.Key];
                                }
                                else
                                {
                                    oldValue = "Record Unavailable";
                                }
                            }
                            DataRow dr = this.dtcombined.NewRow();
                            dr["AuditId"]      = detail.AuditRecord.Id;
                            dr["ChangedDate"]  = Convert.ToString(detail.AuditRecord.GetAttributeValue <DateTime>("createdon"));
                            dr["Event"]        = detail.AuditRecord.FormattedValues["action"];
                            dr["ChangedBy"]    = detail.AuditRecord.GetAttributeValue <EntityReference>("userid").Name;
                            dr["ChangedField"] = AttributeDisplayName;// attribute.Key;
                            dr["OldValue"]     = oldValue;
                            dr["NewValue"]     = string.Empty;
                            this.dtcombined.Rows.Add(dr);
                        }
                    }
                }
            }
        }
        private void DisplayAuditDetails(AuditDetail detail, IList <AuditRecords> auditRecCollection)
        {
            // Write out some of the change history information in the audit record.
            Audit record = (Audit)detail.AuditRecord;

            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();

            if (detailType == typeof(AttributeAuditDetail) && record.Action.Value != 3)
            {
                Collection <ModifiedAttributes> modifiedAttributes = new Collection <ModifiedAttributes>();

                var attributeDetail = (AttributeAuditDetail)detail;

                if (attributeDetail.NewValue != null)
                {
                    // Display the old and new attribute values.
                    foreach (KeyValuePair <String, object> attribute in attributeDetail.NewValue.Attributes)
                    {
                        //TODO Display the lookup values of those attributes that do not contain strings.
                        modifiedAttributes.Add(new ModifiedAttributes()
                        {
                            ChangedDate   = record.CreatedOn.Value.ToLocalTime(),
                            Attribute     = attribute.Key,
                            AttributeName = attribute.Key,
                            OldValue      = this.getAttributeValue(attributeDetail.OldValue, attribute.Key),
                            NewValue      = this.getAttributeValue(attributeDetail.NewValue, attribute.Key)
                        });
                    }
                }

                if (attributeDetail.OldValue != null)
                {
                    foreach (KeyValuePair <String, object> attribute in attributeDetail.OldValue.Attributes)
                    {
                        if (!(attributeDetail.NewValue != null && attributeDetail.NewValue.Contains(attribute.Key)))
                        {
                            modifiedAttributes.Add(new ModifiedAttributes()
                            {
                                ChangedDate   = record.CreatedOn.Value.ToLocalTime(),
                                Attribute     = attribute.Key,
                                AttributeName = attribute.Key,
                                OldValue      = this.getAttributeValue(attributeDetail.OldValue, attribute.Key),
                                NewValue      = this.getAttributeValue(attributeDetail.NewValue, attribute.Key, attributeDetail.InvalidNewValueAttributes)
                            });
                        }
                    }
                }

                if (attributeDetail.InvalidNewValueAttributes != null)
                {
                    foreach (string invalidAttributeName in attributeDetail.InvalidNewValueAttributes)
                    {
                        if (!(attributeDetail.NewValue != null && attributeDetail.NewValue.Contains(invalidAttributeName)) &&
                            !(attributeDetail.OldValue != null && attributeDetail.OldValue.Contains(invalidAttributeName)))
                        {
                            modifiedAttributes.Add(new ModifiedAttributes()
                            {
                                ChangedDate   = record.CreatedOn.Value.ToLocalTime(),
                                Attribute     = invalidAttributeName,
                                AttributeName = invalidAttributeName,
                                OldValue      = this.getAttributeValue(attributeDetail.OldValue, invalidAttributeName),
                                NewValue      = this.getAttributeValue(attributeDetail.NewValue, invalidAttributeName, attributeDetail.InvalidNewValueAttributes)
                            });
                        }
                    }
                }

                if (modifiedAttributes.Count > 0)
                {
                    auditRecCollection.Add(new AuditRecords()
                    {
                        ChangedDate        = record.CreatedOn.Value.ToLocalTime(),
                        ChangedBy          = record.UserId.Name,
                        Action             = record.Action.Value == 1 ? "Create" : "Update",
                        ModifiedAttributes = modifiedAttributes
                    });
                }
            }
        }
        /// <summary>
        /// Displays the audit details.
        /// </summary>
        /// <param name="detail">The detail.</param>
        /// <param name="profile">The profile.</param>
        /// <param name="ObjectName">Name of the object.</param>
        /// <param name="path">The path.</param>
        /// <param name="columns">The columns.</param>
        /// <param name="DisplayedColumns">The displayed columns.</param>
        private void DisplayAuditDetails(AuditDetail detail, MSCRMAuditExportProfile profile, string ObjectName, string path, List<string> columns, List<string> DisplayedColumns)
        {
            Audit record = (Audit)detail.AuditRecord;

            if (profile.AuditRecordCreatedOnFilter == "Last X Days")
            {
                DateTime CreatedOnBottomLimit = DateTime.Today.AddDays(-(double)profile.AuditRecordCreatedOnFilterLastX);
                if (CreatedOnBottomLimit > record.CreatedOn)
                    return;
            }
            else if (profile.AuditRecordCreatedOnFilter == "Last X Months")
            {
                DateTime CreatedOnBottomLimit = DateTime.Today.AddMonths(-(int)profile.AuditRecordCreatedOnFilterLastX);
                if (CreatedOnBottomLimit > record.CreatedOn)
                    return;
            }
            else if (profile.AuditRecordCreatedOnFilter == "Last X Years")
            {
                DateTime CreatedOnBottomLimit = DateTime.Today.AddYears(-(int)profile.AuditRecordCreatedOnFilterLastX);
                if (CreatedOnBottomLimit > record.CreatedOn)
                    return;
            }
            else if (profile.AuditRecordCreatedOnFilter == "Between Dates")
            {
                if (profile.AuditRecordCreatedOnFilterFrom > record.CreatedOn || profile.AuditRecordCreatedOnFilterTo < record.CreatedOn)
                    return;
            }

            List<AuditDetailLine> AuditDetailLines = new List<AuditDetailLine>();
            // Show additional details for certain AuditDetail sub-types.
            var detailType = detail.GetType();
            if (detailType == typeof(AttributeAuditDetail))
            {
                var attributeDetail = (AttributeAuditDetail)detail;
                AuditDetailLine adl = new AuditDetailLine();

                if (attributeDetail.NewValue != null)
                {
                    // Display the old and new attribute values.
                    foreach (KeyValuePair<String, object> attribute in attributeDetail.NewValue.Attributes)
                    {
                        String oldValue = "(no value)", newValue = "(no value)";

                        //format values
                        oldValue = getFormattedValue(attributeDetail.OldValue, attribute.Key);
                        newValue = getFormattedValue(attributeDetail.NewValue, attribute.Key);

                        adl = new AuditDetailLine();
                        adl.TransactionId = record.Id;
                        adl.createdon = record.CreatedOn.Value.ToLocalTime();
                        adl.UserName = record.UserId.Name;
                        adl.RecordLogicalName = record.ObjectId.LogicalName;
                        adl.RecordName = ObjectName;
                        adl.action = record.FormattedValues["action"];
                        adl.operation = record.FormattedValues["operation"];
                        adl.key = attribute.Key;
                        adl.oldValue = oldValue;
                        adl.newValue = newValue;

                        AuditDetailLines.Add(adl);
                    }
                }

                if (attributeDetail.OldValue != null)
                {
                    foreach (KeyValuePair<String, object> attribute in attributeDetail.OldValue.Attributes)
                    {
                        if (!attributeDetail.NewValue.Contains(attribute.Key))
                        {
                            String newValue = "(no value)";

                            //format values
                            String oldValue = getFormattedValue(attributeDetail.OldValue, attribute.Key);

                            adl = new AuditDetailLine();
                            adl.TransactionId = record.Id;
                            adl.createdon = record.CreatedOn.Value.ToLocalTime();
                            adl.UserName = record.UserId.Name;
                            adl.RecordLogicalName = record.ObjectId.LogicalName;
                            adl.RecordName = ObjectName;
                            adl.action = record.FormattedValues["action"];
                            adl.operation = record.FormattedValues["operation"];
                            adl.key = attribute.Key;
                            adl.oldValue = oldValue;
                            adl.newValue = newValue;

                            AuditDetailLines.Add(adl);
                        }
                    }
                }
            }
            else
            {
                AuditDetailLine adl = new AuditDetailLine();
                adl.TransactionId = record.Id;
                adl.createdon = record.CreatedOn.Value.ToLocalTime();
                adl.UserName = record.UserId.Name;
                adl.RecordLogicalName = record.ObjectId.LogicalName;
                adl.RecordName = ObjectName;
                adl.action = record.FormattedValues["action"];
                adl.operation = record.FormattedValues["operation"];

                AuditDetailLines.Add(adl);
            }

            if (profile.ExportFormat.ToLower() == "csv")
                WriteCSVAuditDetail(AuditDetailLines, fileName, columns, DisplayedColumns);
            else if (profile.ExportFormat.ToLower() == "xml")
                WriteXMLAuditDetail(AuditDetailLines, fileName, columns, DisplayedColumns);
            else if (profile.ExportFormat.ToLower() == "xml spreadsheet 2003")
                WriteXMLSpreadsheet2003AuditDetail(AuditDetailLines, fileName, columns, DisplayedColumns);
        }