AuditDetail Class
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
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 |
ExtensionData |
Gets or sets the structure that contains extra data. Optional. |