/// <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); }
/// <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); }
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 ?? ""}"); } }
[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(); } }
/// <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); } }
/// <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; }