예제 #1
0
        /// <summary>
        /// Extract the audit history for the record and a specific Field
        /// </summary>
        /// <param name="entityID">ID of the Account</param>
        /// <param name="identificatorField">Identificator of the Row</param>
        /// <param name="attributeName">Name of the attribute to retrieve for Audit History</param>
        /// <param name="fileName">File to write</param>
        public List <AuditHistory> GetAuditHistoryForRecordAndField(Guid entityID, string entityLogicalName, string attributeName, string recordKeyValue)
        {
            List <AuditHistory> auditHistoryForRecord = new List <AuditHistory>();
            var attributeChangeHistoryRequest         = new RetrieveAttributeChangeHistoryRequest
            {
                Target = new EntityReference(entityLogicalName, entityID),
                AttributeLogicalName = attributeName,
            };

            RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();

            changeRequest.Target = new EntityReference(entityLogicalName, entityID);

            RetrieveRecordChangeHistoryResponse changeResponse = (RetrieveRecordChangeHistoryResponse)_service.Execute(changeRequest);
            AuditDetailCollection details = changeResponse.AuditDetailCollection;

            var attributeChangeHistoryResponse = (RetrieveAttributeChangeHistoryResponse)_service.Execute(attributeChangeHistoryRequest);

            details = attributeChangeHistoryResponse.AuditDetailCollection;

            foreach (var detail in details.AuditDetails)
            {
                //AuditHistory change = GetRecordChanges(detail);

                auditHistoryForRecord.AddRange(GetRecordChanges(detail, recordKeyValue));
                //if (change != null)
                //{
                //    change.RecordKeyValue = recordKeyValue;
                //    auditHistoryForRecord.Add(change);
                //}
            }
            return(auditHistoryForRecord);
        }
예제 #2
0
        /// <summary>
        /// Retrieve attribute audit
        /// </summary>
        /// <param name="entityLogicalName"></param>
        /// <param name="attributeLogicalName"></param>
        /// <param name="recordId"></param>
        /// <returns></returns>
        public List <AuditDetailModel> RetrieveAuditHistory(string entityLogicalName, string attributeLogicalName, Guid recordId)
        {
            //Return
            List <AuditDetailModel> audits = new List <AuditDetailModel>();

            //Make a request to retrieve the audit history
            RetrieveAttributeChangeHistoryRequest request = new RetrieveAttributeChangeHistoryRequest()
            {
                Target = new EntityReference(entityLogicalName, recordId),
                AttributeLogicalName = attributeLogicalName
            };
            //Execute the request
            RetrieveAttributeChangeHistoryResponse response = (RetrieveAttributeChangeHistoryResponse)Service.Execute(request);

            //If the audit return histories
            if (response.AuditDetailCollection != null && response.AuditDetailCollection.AuditDetails != null)
            {
                //Filter by changes
                foreach (AuditDetail auditDetail in response.AuditDetailCollection.AuditDetails.Where(w => w.GetType() == typeof(AttributeAuditDetail)))
                {
                    AttributeAuditDetail attributeDetail = (AttributeAuditDetail)auditDetail;
                    audits.Add(attributeDetail.ToEasyHistoryComponent(attributeLogicalName));
                }
            }

            return(audits);
        }
예제 #3
0
        private void RetrieveAttributeHistory()
        {
            var req = new RetrieveAttributeChangeHistoryRequest
            {
                Target = new EntityReference(EntityName, new Guid(EntityId)),
                AttributeLogicalName = AttributeName
            };

            if (!(CdsClient.Execute(req) is RetrieveAttributeChangeHistoryResponse resp))
            {
                return;
            }

            var details = resp.AuditDetailCollection;

            foreach (var detail in details.AuditDetails)
            {
                //Important: the AuditDetailCollection.AuditDetails doesn’t always contain the type of AttributeAuditDetail, so make sure it is of correct type before casting

                if (!(detail is AttributeAuditDetail attributeDetail))
                {
                    continue;
                }
                string oldValue = " ", newValue = " ";

                if (attributeDetail.OldValue.Contains(AttributeName))
                {
                    oldValue = attributeDetail.OldValue[AttributeName].ToString();
                }
                Console.WriteLine($"Old Value : {oldValue ?? ""}");

                if (attributeDetail.NewValue.Contains(AttributeName))
                {
                    newValue = attributeDetail.NewValue[AttributeName].ToString();
                }
                Console.WriteLine($"New Value : {newValue ?? ""}");
            }
        }
예제 #4
0
        [STAThread] // Added to support UX
        static void Main(string[] args)
        {
            CrmServiceClient service = null;

            try
            {
                service = SampleHelpers.Connect("Connect");
                if (service.IsReady)
                {
                    #region Sample Code
                    #region Set up
                    SetUpSample(service);
                    #endregion Set up
                    #region Demonstrate

                    Console.WriteLine("Enabling auditing on the organization and account entities.");

                    // Enable auditing on the organization.
                    // First, get the organization's ID from the system user record.
                    Guid orgId = ((WhoAmIResponse)service.Execute(new WhoAmIRequest())).OrganizationId;

                    // Next, retrieve the organization's record.
                    var org = service.Retrieve(Organization.EntityLogicalName, orgId,
                                               new ColumnSet(new string[] { "organizationid", "isauditenabled" })) as Organization;

                    // Finally, enable auditing on the organization.
                    bool organizationAuditingFlag = org.IsAuditEnabled.Value;
                    org.IsAuditEnabled = true;
                    service.Update(org);

                    // Enable auditing on account entities.
                    bool accountAuditingFlag = EnableEntityAuditing(service, Account.EntityLogicalName, true);
                    #endregion Enable Auditing for an Account
                    #region Retrieve the Record Change History
                    Console.WriteLine("Retrieving the account change history.\n");

                    // Retrieve the audit history for the account and display it.
                    var changeRequest = new RetrieveRecordChangeHistoryRequest();
                    changeRequest.Target = new EntityReference(Account.EntityLogicalName, _newAccountId);

                    var changeResponse =
                        (RetrieveRecordChangeHistoryResponse)service.Execute(changeRequest);

                    AuditDetailCollection details = changeResponse.AuditDetailCollection;

                    foreach (AttributeAuditDetail detail in details.AuditDetails)
                    {
                        // Display some of the detail information in each audit record.
                        DisplayAuditDetails(service, detail);
                    }
                    #endregion Retrieve the Record Change History

                    #region Retrieve the Attribute Change History

                    // Update the Telephone1 attribute in the Account entity record.
                    var accountToUpdate = new Account();
                    accountToUpdate.AccountId  = _newAccountId;
                    accountToUpdate.Telephone1 = "123-555-5555";
                    service.Update(accountToUpdate);
                    Console.WriteLine("Updated the Telephone1 field in the Account entity.");

                    // Retrieve the attribute change history.
                    Console.WriteLine("Retrieving the attribute change history for Telephone1.");
                    var attributeChangeHistoryRequest = new RetrieveAttributeChangeHistoryRequest
                    {
                        Target = new EntityReference(
                            Account.EntityLogicalName, _newAccountId),
                        AttributeLogicalName = "telephone1"
                    };

                    var attributeChangeHistoryResponse =
                        (RetrieveAttributeChangeHistoryResponse)service.Execute(attributeChangeHistoryRequest);

                    // Display the attribute change history.
                    details = attributeChangeHistoryResponse.AuditDetailCollection;

                    foreach (var detail in details.AuditDetails)
                    {
                        DisplayAuditDetails(service, detail);
                    }

                    // Save an Audit record ID for later use.
                    Guid auditSampleId = details.AuditDetails.First().AuditRecord.Id;
                    #endregion Retrieve the Attribute Change History

                    #region Retrieve the Audit Details
                    Console.WriteLine("Retrieving audit details for an audit record.");

                    // Retrieve the audit details and display them.
                    var auditDetailsRequest = new RetrieveAuditDetailsRequest
                    {
                        AuditId = auditSampleId
                    };

                    var auditDetailsResponse =
                        (RetrieveAuditDetailsResponse)service.Execute(auditDetailsRequest);
                    DisplayAuditDetails(service, auditDetailsResponse.AuditDetail);

                    #endregion Retrieve the Audit Details

                    #region Revert Auditing
                    // Set the organization and account auditing flags back to the old values
                    org.IsAuditEnabled = organizationAuditingFlag;
                    service.Update(org);

                    EnableEntityAuditing(service, Account.EntityLogicalName, accountAuditingFlag);

                    #endregion Revert Auditing

                    #region Clean up
                    CleanUpSample(service);
                    #endregion Clean up
                }
                #endregion Demonstrate

                else
                {
                    const string UNABLE_TO_LOGIN_ERROR = "Unable to Login to Dynamics CRM";
                    if (service.LastCrmError.Equals(UNABLE_TO_LOGIN_ERROR))
                    {
                        Console.WriteLine("Check the connection string values in cds/App.config.");
                        throw new Exception(service.LastCrmError);
                    }
                    else
                    {
                        throw service.LastCrmException;
                    }
                }
            }
            catch (Exception ex)
            {
                SampleHelpers.HandleException(ex);
            }

            finally
            {
                if (service != null)
                {
                    service.Dispose();
                }

                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }
        }
예제 #5
0
        /// <summary>
        /// This method first connects to the organization service. Next, auditing
        /// is enabled on the organization and an account entity. The account record
        /// is updated and the audit history printed out.
        /// </summary>
        /// <param name="serverConfig">Contains server connection information.</param>
        /// <param name="promptforDelete">When True, the user will be prompted to delete all
        /// created entities.</param>
        public void Run(ServerConnection.Configuration serverConfig, bool promptforDelete)
        {
            using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
            {
                // Enable early-bound type support.
                _serviceProxy.EnableProxyTypes();

                // You can access the service through the proxy, but this sample uses the interface instead.
                _service = _serviceProxy;

                #region Enable Auditing for an Account
                //<snippetAuditing1>
                Console.WriteLine("Enabling auditing on the organization and account entities.");

                // Enable auditing on the organization.
                // First, get the organization's ID from the system user record.
                Guid orgId = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).OrganizationId;

                // Next, retrieve the organization's record.
                Organization org = _service.Retrieve(Organization.EntityLogicalName, orgId,
                                                     new ColumnSet(new string[] { "organizationid", "isauditenabled" })) as Organization;

                // Finally, enable auditing on the organization.
                bool organizationAuditingFlag = org.IsAuditEnabled.Value;
                org.IsAuditEnabled = true;
                _service.Update(org);

                // Enable auditing on account entities.
                bool accountAuditingFlag = EnableEntityAuditing(Account.EntityLogicalName, true);
                //</snippetAuditing1>
                #endregion Enable Auditing for an Account

                CreateRequiredRecords();

                #region Retrieve the Record Change History
                Console.WriteLine("Retrieving the account change history.\n");
                //<snippetAuditing5>
                // Retrieve the audit history for the account and display it.
                RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();
                changeRequest.Target = new EntityReference(Account.EntityLogicalName, _newAccountId);

                RetrieveRecordChangeHistoryResponse changeResponse =
                    (RetrieveRecordChangeHistoryResponse)_service.Execute(changeRequest);

                AuditDetailCollection details = changeResponse.AuditDetailCollection;
                //</snippetAuditing5>

                foreach (AttributeAuditDetail detail in details.AuditDetails)
                {
                    // Display some of the detail information in each audit record.
                    DisplayAuditDetails(detail);
                }
                #endregion Retrieve the Record Change History

                #region Retrieve the Attribute Change History

                //<snippetAuditing7>
                // Update the Telephone1 attribute in the Account entity record.
                Account accountToUpdate = new Account();
                accountToUpdate.AccountId  = _newAccountId;
                accountToUpdate.Telephone1 = "123-555-5555";
                _serviceProxy.Update(accountToUpdate);
                Console.WriteLine("Updated the Telephone1 field in the Account entity.");

                // Retrieve the attribute change history.
                Console.WriteLine("Retrieving the attribute change history for Telephone1.");

                var attributeChangeHistoryRequest = new RetrieveAttributeChangeHistoryRequest
                {
                    Target = new EntityReference(
                        Account.EntityLogicalName, _newAccountId),
                    AttributeLogicalName = "telephone1"
                };

                var attributeChangeHistoryResponse =
                    (RetrieveAttributeChangeHistoryResponse)_service.Execute(attributeChangeHistoryRequest);

                // Display the attribute change history.
                details = attributeChangeHistoryResponse.AuditDetailCollection;
                //</snippetAuditing7>

                foreach (var detail in details.AuditDetails)
                {
                    DisplayAuditDetails(detail);
                }

                // Save an Audit record ID for later use.
                Guid auditSampleId = details.AuditDetails.First().AuditRecord.Id;
                #endregion Retrieve the Attribute Change History

                #region Retrieve the Audit Details
                //<snippetAuditing8>
                Console.WriteLine("Retrieving audit details for an audit record.");

                // Retrieve the audit details and display them.
                var auditDetailsRequest = new RetrieveAuditDetailsRequest
                {
                    AuditId = auditSampleId
                };

                var auditDetailsResponse =
                    (RetrieveAuditDetailsResponse)_service.Execute(auditDetailsRequest);
                //</snippetAuditing8>
                DisplayAuditDetails(auditDetailsResponse.AuditDetail);

                #endregion Retrieve the Audit Details

                #region Revert Auditing
                // Set the organization and account auditing flags back to the old values
                org.IsAuditEnabled = organizationAuditingFlag;
                _service.Update(org);

                EnableEntityAuditing(Account.EntityLogicalName, accountAuditingFlag);

                #endregion Revert Auditing

                DeleteRequiredRecords(promptforDelete);
            }
        }
예제 #6
0
파일: Program.cs 프로젝트: cesugden/Scripts
        /// <summary>
        /// This method first connects to the organization service. Next, auditing 
        /// is enabled on the organization and an account entity. The account record
        /// is updated and the audit history printed out.
        /// </summary>
        /// <param name="serverConfig">Contains server connection information.</param>
        /// <param name="promptforDelete">When True, the user will be prompted to delete all
        /// created entities.</param>
        public void Run(ServerConnection.Configuration serverConfig, bool promptforDelete)
        {
            using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri, serverConfig.Credentials, serverConfig.DeviceCredentials))
            {
                // Enable early-bound type support.
                _serviceProxy.EnableProxyTypes();

                // You can access the service through the proxy, but this sample uses the interface instead.
                _service = _serviceProxy;

                #region Enable Auditing for an Account
                //<snippetAuditing1>
                Console.WriteLine("Enabling auditing on the organization and account entities.");

                // Enable auditing on the organization.
                // First, get the organization's ID from the system user record.
                Guid orgId = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).OrganizationId;

                // Next, retrieve the organization's record.
                Organization org = _service.Retrieve(Organization.EntityLogicalName, orgId,
                    new ColumnSet(new string[] { "organizationid", "isauditenabled" })) as Organization;

                // Finally, enable auditing on the organization.
                bool organizationAuditingFlag = org.IsAuditEnabled.Value;
                org.IsAuditEnabled = true;
                _service.Update(org);

                // Enable auditing on account entities.
                bool accountAuditingFlag = EnableEntityAuditing(Account.EntityLogicalName, true);
                //</snippetAuditing1>
                #endregion Enable Auditing for an Account

                CreateRequiredRecords();

                #region Retrieve the Record Change History
                Console.WriteLine("Retrieving the account change history.\n");
                //<snippetAuditing5>
                // Retrieve the audit history for the account and display it.
                RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();
                changeRequest.Target = new EntityReference(Account.EntityLogicalName, _newAccountId);

                RetrieveRecordChangeHistoryResponse changeResponse =
                    (RetrieveRecordChangeHistoryResponse)_service.Execute(changeRequest);

                AuditDetailCollection details = changeResponse.AuditDetailCollection;
                //</snippetAuditing5>

                foreach (AttributeAuditDetail detail in details.AuditDetails)
                {
                    // Display some of the detail information in each audit record. 
                    DisplayAuditDetails(detail);
                }
                #endregion Retrieve the Record Change History

                #region Retrieve the Attribute Change History

                //<snippetAuditing7>
                // Update the Telephone1 attribute in the Account entity record.
                Account accountToUpdate = new Account();
                accountToUpdate.AccountId = _newAccountId;
                accountToUpdate.Telephone1 = "123-555-5555";
                _serviceProxy.Update(accountToUpdate);
                Console.WriteLine("Updated the Telephone1 field in the Account entity.");

                // Retrieve the attribute change history.
                Console.WriteLine("Retrieving the attribute change history for Telephone1.");

                var attributeChangeHistoryRequest = new RetrieveAttributeChangeHistoryRequest
                {
                    Target = new EntityReference(
                        Account.EntityLogicalName, _newAccountId),
                    AttributeLogicalName = "telephone1"
                };

                var attributeChangeHistoryResponse =
                    (RetrieveAttributeChangeHistoryResponse)_service.Execute(attributeChangeHistoryRequest);

                // Display the attribute change history.
                details = attributeChangeHistoryResponse.AuditDetailCollection;
                //</snippetAuditing7>

                foreach (var detail in details.AuditDetails)
                {
                    DisplayAuditDetails(detail);
                }

                // Save an Audit record ID for later use.
                Guid auditSampleId = details.AuditDetails.First().AuditRecord.Id;
                #endregion Retrieve the Attribute Change History

                #region Retrieve the Audit Details
                //<snippetAuditing8>
                Console.WriteLine("Retrieving audit details for an audit record.");

                // Retrieve the audit details and display them.
                var auditDetailsRequest = new RetrieveAuditDetailsRequest
                {
                    AuditId = auditSampleId
                };

                var auditDetailsResponse =
                    (RetrieveAuditDetailsResponse)_service.Execute(auditDetailsRequest);
                //</snippetAuditing8>
                DisplayAuditDetails(auditDetailsResponse.AuditDetail);

                #endregion Retrieve the Audit Details

                #region Revert Auditing
                // Set the organization and account auditing flags back to the old values
                org.IsAuditEnabled = organizationAuditingFlag;
                _service.Update(org);

                EnableEntityAuditing(Account.EntityLogicalName, accountAuditingFlag);

                #endregion Revert Auditing

                DeleteRequiredRecords(promptforDelete);
            }
        }
        /// <summary>
        /// This method first connects to the organization service. Afterwards,
        /// auditing is enabled on the organization, account entity, and a couple
        /// of attributes. Finally, display that information in Console, and creates
        /// an XML file.
        /// </summary>
        /// <param name="serverConfig">Contains server connection information.</param>
        /// <param name="promptforDelete">When True, the user will be prompted to delete all
        /// created entities.</param>
        public void Run(ServerConnection.Configuration serverConfig, bool promptforDelete)
        {
            _sampleStartTime = DateTime.Now;
            using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
            {
                // This statement is required to enable early-bound type support.
                _serviceProxy.EnableProxyTypes();

                // You can access the service through the proxy, but this sample uses the interface instead.
                _service = _serviceProxy;

                #region Enable Auditing for an Account

                Console.WriteLine("Enabling auditing on the organization and account entities.");

                // Enable auditing on the organization.
                // First, get the organization's ID from the system user record.
                Guid orgId = ((WhoAmIResponse)_service.Execute(new WhoAmIRequest())).OrganizationId;

                // Next, retrieve the organization's record.
                Organization org = _service.Retrieve(Organization.EntityLogicalName, orgId,
                                                     new ColumnSet(new string[] { "organizationid", "isauditenabled" })) as Organization;

                // Finally, enable auditing on the organization.
                bool organizationAuditingFlag = org.IsAuditEnabled.Value;
                bool usersAccessAuditingFlag  = org.IsUserAccessAuditEnabled.HasValue ?
                                                org.IsUserAccessAuditEnabled.Value : false;

                org.IsAuditEnabled           = true;
                org.IsUserAccessAuditEnabled = true;
                _service.Update(org);

                // Enable auditing on account entities.
                bool accountAuditingFlag = EnableEntityAuditing(Account.EntityLogicalName, true);

                #endregion Enable Auditing for an Account

                CreateRequiredRecords();

                #region Create and start XML file

                // Create the XML file
                String fileName = "auditReport.xml";
                textWriter = new XmlTextWriter(fileName, null);
                textWriter.WriteStartDocument();

                // Start Audit Node
                textWriter.WriteStartElement("auditReport", "");

                #endregion

                #region Retrive user access audit records

                var query = new QueryExpression(Audit.EntityLogicalName)
                {
                    ColumnSet = new ColumnSet("createdon", "action", "operation", "objectid"),
                    Criteria  = new FilterExpression(LogicalOperator.And)
                };

                // Only retrieve audit records that track user access.
                query.Criteria.AddCondition("action", ConditionOperator.In,
                                            (int)AuditAction.UserAccessAuditStarted,
                                            (int)AuditAction.UserAccessAuditStopped,
                                            (int)AuditAction.UserAccessviaWebServices,
                                            (int)AuditAction.UserAccessviaWeb);

                // Change this to false in order to retrieve audit records for all users
                // when running the sample.
                var filterAuditsRetrievedByUser = true;
                if (filterAuditsRetrievedByUser)
                {
                    // Only retrieve audit records for the current user.
                    var userFilter = new FilterExpression(LogicalOperator.Or);
                    userFilter.AddCondition(
                        "userid", ConditionOperator.Equal, _serviceProxy.CallerId);
                }
                // Only retrieve records for this sample run, so that we don't get too
                // many results if auditing was enabled previously.
                query.Criteria.AddCondition(
                    "createdon", ConditionOperator.GreaterEqual, _sampleStartTime);

                var results = _serviceProxy.RetrieveMultiple(query);
                foreach (Audit audit in results.Entities)
                {
                    // Display results
                    DisplayAndAddToXMLFileUserAccessDetails(audit);
                }

                #endregion

                #region Retrieve the Audit History
                Console.WriteLine("Retrieving the account change history.\n");

                DateTime startTime = DateTime.Now;

                // Retrieve the audit records for accounts.
                RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();
                changeRequest.Target = new EntityReference(Account.EntityLogicalName, _newAccountId);

                RetrieveRecordChangeHistoryResponse changeResponse =
                    (RetrieveRecordChangeHistoryResponse)_service.Execute(changeRequest);

                AuditDetailCollection details = changeResponse.AuditDetailCollection;

                foreach (AttributeAuditDetail detail in details.AuditDetails)
                {
                    // Write out some of the information in each audit record.
                    DisplayAndAddToXMLFileAuditDetails(detail);
                }
                #endregion Retrieve the Audit History

                #region RetrieveAttributeChangeHistoryRequest
                // How to use message: RetrieveAttributeChangeHistoryRequest

                // Update Telephone1 in account entity
                Account accountToUpdate = new Account();
                accountToUpdate.AccountId  = _newAccountId;
                accountToUpdate.Telephone1 = "123-555-5555";
                _serviceProxy.Update(accountToUpdate);
                Console.WriteLine("Updated Telephone1 field in Account entity.");

                Console.WriteLine("Retrieving attribute change history for Telephone1.");
                // Create RetrieveAttributeChangeHistoryRequest
                var attributeChangeHistoryRequest = new RetrieveAttributeChangeHistoryRequest
                {
                    Target = new EntityReference(
                        Account.EntityLogicalName, _newAccountId),
                    AttributeLogicalName = "telephone1"
                };

                // Execute RetrieveAttributeChangeHistoryRequest
                var attributeChangeHistoryResponse =
                    (RetrieveAttributeChangeHistoryResponse)_service.Execute(attributeChangeHistoryRequest);

                // Set AuditDetailCollection and output to console
                details = attributeChangeHistoryResponse.AuditDetailCollection;

                foreach (var detail in details.AuditDetails)
                {
                    DisplayAndAddToXMLFileAuditDetails(detail);
                }

                // Create an Audit record
                // to store a sample for use with RetrieveAuditDetailsRequest
                Guid auditSampleId = details.AuditDetails.First().AuditRecord.Id;
                #endregion RetrieveAttributeChangeHistoryRequest

                #region RetrieveAuditDetailsRequest
                // How to use message: RetrieveAuditDetailsRequest

                Console.WriteLine("Retrieving audit details for an audit record.");
                // Create RetrieveAuditDetailsRequest
                var auditDetailsRequest = new RetrieveAuditDetailsRequest
                {
                    AuditId = auditSampleId
                };

                // Execute RetrieveAuditDetailsRequest
                var auditDetailsResponse =
                    (RetrieveAuditDetailsResponse)_service.Execute(auditDetailsRequest);

                // Display results
                DisplayAndAddToXMLFileAuditDetails(auditDetailsResponse.AuditDetail);

                #endregion RetrieveAuditDetailsRequest

                #region Retrieve AuditExtension details

                Console.WriteLine("Simulating a user reading records");
                _service.Retrieve(Account.EntityLogicalName, _newAccountId, new ColumnSet("accountid"));

                // creating read records is an async process - wait until the records have been created
                // wait a max of 30 seconds
                Console.WriteLine("Fetching read audit records for accounts");
                for (int i = 0; i < 30; i++)
                {
                    query = new QueryExpression
                    {
                        EntityName = "sample_auditextension",
                        ColumnSet  = new ColumnSet("createdon", "sample_objectlogicalname",
                                                   "sample_objectid", "sample_userid", "sample_action", "sample_operation"),
                        Criteria = new FilterExpression
                        {
                            Conditions =
                            {
                                new ConditionExpression("sample_objectlogicalname", ConditionOperator.Equal, Account.EntityLogicalName),
                                new ConditionExpression("sample_objectid",          ConditionOperator.Equal,
                                                        _newAccountId.ToString().TrimStart('{').TrimEnd('}'))
                            }
                        }
                    };
                    results = _service.RetrieveMultiple(query);
                    if (results.Entities.Count > 0)
                    {
                        break;
                    }
                    else if (i == 29)
                    {
                        throw new Exception("Exceeded maximum wait time");
                    }
                    System.Threading.Thread.Sleep(1000);
                }

                foreach (var record in results.Entities)
                {
                    _auditExtensionRecordIds.Add(record.Id);
                    DisplayAndAddToXmlFileAuditExtension(record);
                }

                #endregion

                #region Finish and close XML file

                // End auditReport Xml Node
                textWriter.WriteEndElement();
                textWriter.WriteEndDocument();

                // Close xml writer.
                textWriter.Close();

                Console.WriteLine("File name: " + fileName);

                #endregion

                #region Revert auditing
                // Set the organization and account auditing flags back to the old values
                org.IsAuditEnabled           = organizationAuditingFlag;
                org.IsUserAccessAuditEnabled = usersAccessAuditingFlag;
                _service.Update(org);

                EnableEntityAuditing(Account.EntityLogicalName, accountAuditingFlag);

                #endregion Revert auditing

                DeleteRequiredRecords(promptforDelete);
            }
        }
        /// <summary>
        /// Exports the entity.
        /// </summary>
        /// <param name="profile">The profile.</param>
        /// <param name="fetchXml">The fetch XML query.</param>
        /// <param name="PrimaryNameAttribute">The primary name attribute.</param>
        /// <param name="columns">The columns.</param>
        /// <param name="DisplayedColumns">The displayed columns.</param>
        /// <param name="sae">The sae.</param>
        /// <returns>The number of exported records</returns>
        public int ExportEntity(MSCRMAuditExportProfile profile, string fetchXml, string PrimaryNameAttribute, List<string> columns, List<string> DisplayedColumns, SelectedAuditEntity sae)
        {
            //Set the number of records per page to retrieve.
            //This value should not be bigger than 5000 as this is the limit of records provided by the CRM
            int fetchCount = 5000;
            // Initialize the file number.
            int fileNumber = 1;
            // Initialize the number of records.
            int recordCount = 0;
            // Specify the current paging cookie. For retrieving the first page, pagingCookie should be null.
            string pagingCookie = null;
            string entityName = "";

            while (true)
            {
                // Build fetchXml string with the placeholders.
                string xml = CreateXml(fetchXml, pagingCookie, fileNumber, fetchCount);

                RetrieveMultipleRequest fetchRequest = new RetrieveMultipleRequest
                {
                    Query = new FetchExpression(xml)
                };

                EntityCollection returnCollection = ((RetrieveMultipleResponse)_serviceProxy.Execute(fetchRequest)).EntityCollection;
                recordCount += returnCollection.Entities.Count;
                if (recordCount > 0)
                {
                    if (profile.AuditType == "User Acces Audit" || profile.AuditType == "Audit Summary View")
                    {
                        if (profile.ExportFormat.ToLower() == "csv")
                            WriteCSV(returnCollection, fileName, columns, DisplayedColumns);
                        else if (profile.ExportFormat.ToLower() == "xml")
                            WriteXML(returnCollection, fileName, columns, DisplayedColumns);
                        else if (profile.ExportFormat.ToLower() == "xml spreadsheet 2003")
                            WriteXMLSpreadsheet2003(returnCollection, fileName, columns, DisplayedColumns);
                    }
                    else
                    {
                        foreach (Entity e in returnCollection.Entities)
                        {
                            AuditDetailCollection details = new AuditDetailCollection();
                            if (profile.AuditType == "Record Change History")
                            {
                                RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();
                                changeRequest.Target = new EntityReference(returnCollection.EntityName, e.Id);
                                RetrieveRecordChangeHistoryResponse changeResponse = (RetrieveRecordChangeHistoryResponse)_serviceProxy.Execute(changeRequest);
                                details = changeResponse.AuditDetailCollection;
                            }
                            else
                            {
                                //Attribute change history
                                var attributeChangeHistoryRequest = new RetrieveAttributeChangeHistoryRequest
                                {
                                    Target = new EntityReference(e.LogicalName, e.Id),
                                    AttributeLogicalName = sae.SelectedAttributes[0]
                                };

                                var attributeChangeHistoryResponse = (RetrieveAttributeChangeHistoryResponse)_serviceProxy.Execute(attributeChangeHistoryRequest);
                                details = attributeChangeHistoryResponse.AuditDetailCollection;
                            }

                            foreach (AuditDetail detail in details.AuditDetails)
                            {
                                DisplayAuditDetails(detail, profile, (string)e[PrimaryNameAttribute], fileName, columns, DisplayedColumns);
                            }
                        }
                    }
                }
                // Check for more records, if it returns 1.
                if (returnCollection.MoreRecords)
                {
                    // Increment the page number to retrieve the next page.
                    fileNumber++;
                    pagingCookie = returnCollection.PagingCookie;
                }
                else
                {
                    // If no more records in the result nodes, exit the loop.
                    break;
                }
            }

            if (profile.ExportFormat.ToLower() == "xml" && File.Exists(fileName))
            {
                using (var writer = new StreamWriter(fileName, true, encoding))
                {
                    writer.WriteLine("</Records>");
                    writer.Flush();
                }
            }
            else if (profile.ExportFormat.ToLower() == "xml spreadsheet 2003" && File.Exists(fileName))
            {
                using (var writer = new StreamWriter(fileName, true, encoding))
                {
                    writer.WriteLine("</Table></Worksheet></Workbook>\n");
                    writer.Flush();
                }
            }

            LogManager.WriteLog("Exported " + recordCount + " " + entityName + " records.");

            return recordCount;
        }