Jaa


AuditDetail Class

Definition

Provides a base class for storing the details of data changes.

public ref class AuditDetail : System::Runtime::Serialization::IExtensibleDataObject
[System.Runtime.Serialization.DataContract(Namespace="http://schemas.microsoft.com/crm/2011/Contracts")]
[System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.ApplicationBasedAccessControlAuditDetail))]
[System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.AttributeAuditDetail))]
[System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.IPFirewallAccessAuditDetail))]
[System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.RelationshipAuditDetail))]
[System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.ShareAuditDetail))]
public class AuditDetail : System.Runtime.Serialization.IExtensibleDataObject
[<System.Runtime.Serialization.DataContract(Namespace="http://schemas.microsoft.com/crm/2011/Contracts")>]
[<System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.ApplicationBasedAccessControlAuditDetail))>]
[<System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.AttributeAuditDetail))>]
[<System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.IPFirewallAccessAuditDetail))>]
[<System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.RelationshipAuditDetail))>]
[<System.Runtime.Serialization.KnownType(typeof(Microsoft.Crm.Sdk.Messages.ShareAuditDetail))>]
type AuditDetail = class
    interface IExtensibleDataObject
Public Class AuditDetail
Implements IExtensibleDataObject
Inheritance
AuditDetail
Derived
Attributes
Implements

Examples

The DisplayAuditDetail static method outputs different details to the console depending on the type of audit detail.

/// <summary>
/// Displays properties of the different classes derived from AuditDetail
/// </summary>
/// <param name="auditDetail">The instance of a type derived from AuditDetail</param>
static void DisplayAuditDetail(AuditDetail auditDetail)
{
      switch (auditDetail)
      {
         case AttributeAuditDetail aad:

            Entity oldRecord = aad.OldValue;
            Entity newRecord = aad.NewValue;
            List<string> oldKeys = new List<string>();

            //Look for changed or deleted values that are included in the OldValue collection
            oldRecord.Attributes.Keys.ToList().ForEach(k =>
            {
                  if (oldRecord.FormattedValues.Keys.Contains(k))
                  {
                     if (newRecord.FormattedValues.Contains(k))
                     {
                        Console.WriteLine(
                              $"\tChange:{k}:{oldRecord.FormattedValues[k]} => " +
                              $"{newRecord.FormattedValues[k]}");
                     }
                     else
                     {

                        Console.WriteLine($"\tDeleted:{k}:" +
                              $"{oldRecord.FormattedValues[k]}");
                     }
                  }
                  else
                  {
                     if (newRecord.Attributes.Keys.Contains(k))
                     {

                        Console.WriteLine($"\tChange:{k}:{oldRecord[k]} => " +
                              $"{newRecord[k]}");
                     }
                     else
                     {
                        Console.WriteLine($"\tDeleted:{k}:{oldRecord[k]}");
                     }
                  }

                  oldKeys.Add(k); //Add to list so we don't check again
            });

            //Look for New values that are only in the NewValues collection
            newRecord.Attributes.Keys.ToList().ForEach(k =>
            {
                  if (!oldKeys.Contains(k))//Exclude any keys for changed or deleted values
                  {
                     if (newRecord.FormattedValues.Keys.Contains(k))
                     {
                        Console.WriteLine($"\tNew Value:{k} => " +
                              $"{newRecord.FormattedValues[k]}");
                     }
                     else
                     {
                        Console.WriteLine($"\tNew Value:{k}:{newRecord[k]}");
                     }
                  }
            });
            break;

         case ShareAuditDetail sad:
            Console.WriteLine($"\tUser: {sad.Principal.Name}");
            Console.WriteLine($"\tOld Privileges: {sad.OldPrivileges}");
            Console.WriteLine($"\tNew Privileges: {sad.NewPrivileges}");
            break;

         //Applies to operations on N:N relationships
         case RelationshipAuditDetail rad:
            Console.WriteLine($"\tRelationship Name :{rad.RelationshipName }");
            Console.WriteLine($"\tRecords:");
            rad.TargetRecords.ToList().ForEach(y =>
            {
                  Console.WriteLine($"\tTarget Record :{y.Name}");
            });
            break;

         //Only applies to role record
         case RolePrivilegeAuditDetail rpad:

            List<string> newRolePrivileges = new List<string>();
            rpad.NewRolePrivileges.ToList().ForEach(y =>
            {
                  if (y != null)
                  {
                     newRolePrivileges.Add(
                     $"\t\tPrivilege Id:{y.PrivilegeId} Depth:{y.Depth}\n");
                  }
            });

            List<string> oldRolePrivileges = new List<string>();
            rpad.OldRolePrivileges.ToList().ForEach(y =>
            {
                  if (y != null)
                  {
                     oldRolePrivileges.Add(
                     $"\t\tPrivilege Id:{(y.PrivilegeId)} Depth:{y.Depth}\n");
                  }
            });

            List<string> invalidNewPrivileges = new List<string>();
            rpad.InvalidNewPrivileges.ToList().ForEach(y =>
            {
                  if (y != null)
                  {
                     invalidNewPrivileges.Add(
                     $"\t\tGuid:{y}\n");
                  }
            });

            Console.WriteLine($"\tNew Role Privileges:\n{string.Join(string.Empty, newRolePrivileges.ToArray())}");
            Console.WriteLine($"\tOld Role Privileges:\n{string.Join(string.Empty, oldRolePrivileges.ToArray())}");
            Console.WriteLine($"\tInvalid New Privileges:\n{string.Join(string.Empty, invalidNewPrivileges.ToArray())}"); ;
            break;

         //Only applies for systemuser record
         case UserAccessAuditDetail uaad:
            Console.WriteLine($"\tAccess Time:{uaad.AccessTime}");
            Console.WriteLine($"\tInterval:{uaad.Interval}");
            break;
      }
}

Remarks

When you cast an object of this type, use one of its specialized (derived) types: AttributeAuditDetail, RelationshipAuditDetail, RolePrivilegeAuditDetail, ShareAuditDetail, or UserAccessAuditDetail.

Learn to retrieve audit change history

Constructors

AuditDetail()

Initializes a new instance of the AuditDetail class.

Properties

AuditRecord

Gets or sets the related Audit record that contains the change details.

ExtensionData

Gets or sets the structure that contains extra data. Optional.

Applies to

See also