/// <summary> /// Convert the Microsoft.Crm.Sdk.Messages.AttributeAuditDetail to custom VinnyB.EasyHistory.Models.AuditDetailModel /// </summary> /// <param name="_this">AttributeAuditDetail</param> /// <returns>AuditDetailModel</returns> public static AuditDetailModel ToEasyHistoryComponent(this AttributeAuditDetail _this, string _attributeLogicalName) { EntityReference user = _this.AuditRecord.GetAttributeValue <EntityReference>("userid"); if (user == null || String.IsNullOrEmpty(user.Name)) { user = new EntityReference(); user.Name = "N/A"; } DateTime date = _this.AuditRecord.GetAttributeValue <DateTime>("createdon"); string value = string.Empty; Type attributeType = null; if (_this.OldValue.Contains(_attributeLogicalName) && _this.OldValue.Attributes[_attributeLogicalName] != null) { attributeType = _this.OldValue.Attributes[_attributeLogicalName].GetType(); value = RetrieveAttributeValue(attributeType, _this.OldValue, _attributeLogicalName); } else { value = string.Empty; } AuditDetailModel auditDetailModel = new AuditDetailModel(user.Name, date.ToString("MM-dd-yyyy hh:mm tt"), value, attributeType != null ? attributeType.Name : string.Empty); return(auditDetailModel); }
private void FindContacts(Guid guid) { Guid selectedUser = (Guid)ddlUsers.SelectedValue; List <AuditItem> data = new List <Model.AuditItem>(); FetchExpression query = null; Tuple <int, string, string> selectedEntity = (Tuple <int, string, string>)ddlEntities.SelectedItem; string auditFetchXml; if (selectedUser == Guid.Empty) { auditFetchXml = string.Format(ConnectionDetail.OrganizationMajorVersion < 8 ? FetchXml.DeletedAuditLogs.Replace("regardingobject", "object") : FetchXml.DeletedAuditLogs, dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.AddDays(1).ToString("yyyy-MM-dd"), 2); } else { auditFetchXml = string.Format(ConnectionDetail.OrganizationMajorVersion < 8 ? FetchXml.DeleteAuditLogsByUser.Replace("regardingobject", "object") : FetchXml.DeleteAuditLogsByUser, dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.AddDays(1).ToString("yyyy-MM-dd"), 2, selectedUser); } query = new FetchExpression(auditFetchXml); var queryResult = Service.RetrieveMultiple(query); foreach (Entity item in queryResult.Entities) { RetrieveAuditDetailsRequest auditDetailRequest = new RetrieveAuditDetailsRequest(); auditDetailRequest.AuditId = item.Id; RetrieveAuditDetailsResponse response = (RetrieveAuditDetailsResponse)Service.Execute(auditDetailRequest); AttributeAuditDetail attributeDetail = (AttributeAuditDetail)response.AuditDetail; EntityMetadata metadata = entityMetadataList.FirstOrDefault(x => (x.ObjectTypeCode == 2)); AuditItem auditItem = new Model.AuditItem() { AuditId = item.Id, DeletedBy = ((EntityReference)item["userid"]).Name, DeletionDate = (DateTime)item["createdon"], Entity = ((EntityReference)item["objectid"]).LogicalName, RecordId = ((EntityReference)item["objectid"]).Id, AuditDetail = attributeDetail, Metadata = metadata }; if (selectedEntity.Item3 != null && attributeDetail.OldValue.Contains(selectedEntity.Item3)) { auditItem.Name = attributeDetail.OldValue[selectedEntity.Item3].ToString(); } data.Add(auditItem); } var contact = data.First(x => x.AuditDetail.OldValue.Id == guid); Service.Create(contact.AuditDetail.OldValue); }
/// <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); }
public void GetAuditDetails(IOrganizationService service, EntityCollection entColl) { #region Execute Multiple with Results // Create an ExecuteMultipleRequest object. ExecuteMultipleRequest requestWithResults = new ExecuteMultipleRequest() { // Assign settings that define execution behavior: continue on error, return responses. Settings = new ExecuteMultipleSettings() { ContinueOnError = false, ReturnResponses = true }, // Create an empty organization request collection. Requests = new OrganizationRequestCollection() }; // Add a CreateRequest for each entity to the request collection. foreach (Entity ent in entColl.Entities) { var auditDetailsRequest = new RetrieveAuditDetailsRequest() { AuditId = ent.Id }; requestWithResults.Requests.Add(auditDetailsRequest); } // Execute all the requests in the request collection using a single web method call. ExecuteMultipleResponse AuditDetailResponses = (ExecuteMultipleResponse)service.Execute(requestWithResults); foreach (var AuditDetailResponse in AuditDetailResponses.Responses) { if (AuditDetailResponse.Response != null) { if (((RetrieveAuditDetailsResponse)(AuditDetailResponse.Response)).Results != null) { if (((RetrieveAuditDetailsResponse)(AuditDetailResponse.Response)).AuditDetail != null) { AttributeAuditDetail AuditDetail_ = (AttributeAuditDetail)((RetrieveAuditDetailsResponse)(AuditDetailResponse.Response)).AuditDetail; AuditDetailsColl.Add(AuditDetail_); } } } else if (AuditDetailResponse.Fault != null) { MessageBox.Show("Exception: There was a problem in extacting the Audit History. " + AuditDetailResponse.Fault.ToString()); } } #endregion }
public void It_Should_Retrieve_Old_Values_From_Audit() { var context = new XrmFakedContext(); var service = context.GetFakedOrganizationService(); var tracing = context.GetFakeTracingService(); var contact = new Entity { LogicalName = "contact", Id = Guid.NewGuid(), Attributes = new AttributeCollection { { "name", "newName" } } }; context.AddExecutionMock <RetrieveRecordChangeHistoryRequest>((OrganizationRequest req) => { var auditDetail = new AttributeAuditDetail { OldValue = new Entity { LogicalName = "contact", Id = Guid.NewGuid(), ["name"] = "oldName" } }; var collection = new AuditDetailCollection(); collection.AuditDetails.Add(auditDetail); return(new RetrieveRecordChangeHistoryResponse { Results = new ParameterCollection { { "AuditDetailCollection", collection } } }); }); var formula = "RetrieveAudit (PrimaryRecord(), \"name\")"; var result = new XTLInterpreter(formula, contact, null, service, tracing).Produce(); Assert.That(result, Is.EqualTo("oldName")); }
/// <summary> /// Shows the data. /// </summary> /// <param name="auditDetail">The audit detail.</param> /// <param name="metadata">The metadata.</param> private void ShowData(AttributeAuditDetail auditDetail, EntityMetadata metadata) { List <DeletedField> result = new List <Model.DeletedField>(); foreach (var item in auditDetail.OldValue.Attributes) { var metadataAttrib = metadata.Attributes.Where(x => (x.SchemaName.ToLower() == item.Key.ToLower())).ToList(); if (metadataAttrib.Count > 0) { result.Add(new DeletedField() { FieldName = metadataAttrib[0].DisplayName.UserLocalizedLabel.Label, Value = GetFormattedValue(item.Value) }); } } GridDetails.DataSource = result; }
private List <AuditRecord> ConvertToAttributeAuditRecord(AttributeAuditDetail auditDetails) { var auditRecords = new List <AuditRecord>(); if (auditDetails != null && auditDetails.OldValue != null) { Entity audit = auditDetails.AuditRecord; var action = audit.GetAttributeValueAsString("action"); var actionText = audit.GetAttributeText("action"); var attributesToDisplay = audit.GetAttributeValue <OptionSetValue>("action").Value == 3 //delete ? auditDetails.OldValue.Attributes : auditDetails.NewValue.Attributes; foreach (var attribute in attributesToDisplay) { var entityLogicalName = audit.GetAttributeValue <EntityReference>("objectid")?.LogicalName; auditRecords.Add(new AuditRecord { EntityLogicalName = entityLogicalName, EntityDisplayName = this.auditableEntities[entityLogicalName].DisplayName?.UserLocalizedLabel?.Label, RecordName = audit.GetAttributeValue <EntityReference>("objectid")?.Name, AuthorName = audit.GetAttributeValue <EntityReference>("userid")?.Name, CreatedOn = audit.GetAttributeValue <DateTime>("createdon"), ObjectLogicalName = attribute.Key, ObjectDisplayName = this.auditableEntities[entityLogicalName].Attributes.First(a => a.LogicalName == attribute.Key).DisplayName?.UserLocalizedLabel?.Label, NewValue = auditDetails.NewValue?.GetAttributeValueAsString(attribute.Key), NewValueFormated = auditDetails.NewValue?.GetAttributeText(attribute.Key), OldValue = auditDetails.OldValue?.GetAttributeValueAsString(attribute.Key), OldValueFormated = auditDetails.OldValue?.GetAttributeText(attribute.Key), OperationFormated = audit.GetAttributeText("operation"), OperationValue = audit.GetAttributeValueAsString("operation"), ActionValue = audit.GetAttributeValueAsString("action"), ActionFormated = audit.GetAttributeText("action"), }); } } return(auditRecords); }
/// <summary> /// Handles the Click event of the btnShowRecords control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void btnShowRecords_Click(object sender, EventArgs e) { if (IsValid()) { WorkAsync(new WorkAsyncInfo { Message = "Loading deleted records...", Work = (w, ev) => { Guid selectedUser = (Guid)ddlUsers.SelectedValue; List <AuditItem> data = new List <Model.AuditItem>(); FetchExpression query = null; Tuple <int, string, string> selectedEntity = (Tuple <int, string, string>)ddlEntities.SelectedItem; string auditFetchXml; if (selectedUser == Guid.Empty) { auditFetchXml = string.Format(ConnectionDetail.OrganizationMajorVersion < 8 ? FetchXml.DeletedAuditLogs.Replace("regardingobject", "object") : FetchXml.DeletedAuditLogs, dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.AddDays(1).ToString("yyyy-MM-dd"), ddlEntities.SelectedValue); } else { auditFetchXml = string.Format(ConnectionDetail.OrganizationMajorVersion < 8 ? FetchXml.DeleteAuditLogsByUser.Replace("regardingobject", "object") : FetchXml.DeleteAuditLogsByUser, dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.AddDays(1).ToString("yyyy-MM-dd"), ddlEntities.SelectedValue, selectedUser); } query = new FetchExpression(auditFetchXml); var queryResult = Service.RetrieveMultiple(query); foreach (Entity item in queryResult.Entities) { RetrieveAuditDetailsRequest auditDetailRequest = new RetrieveAuditDetailsRequest(); auditDetailRequest.AuditId = item.Id; RetrieveAuditDetailsResponse response = (RetrieveAuditDetailsResponse)Service.Execute(auditDetailRequest); AttributeAuditDetail attributeDetail = (AttributeAuditDetail)response.AuditDetail; EntityMetadata metadata = entityMetadataList.FirstOrDefault(x => (x.ObjectTypeCode == selectedEntity.Item1)); AuditItem auditItem = new Model.AuditItem() { AuditId = item.Id, DeletedBy = ((EntityReference)item["userid"]).Name, DeletionDate = (DateTime)item["createdon"], Entity = ((EntityReference)item["objectid"]).LogicalName, RecordId = ((EntityReference)item["objectid"]).Id, AuditDetail = attributeDetail, Metadata = metadata }; if (selectedEntity.Item3 != null && attributeDetail.OldValue.Contains(selectedEntity.Item3)) { auditItem.Name = attributeDetail.OldValue[selectedEntity.Item3].ToString(); } data.Add(auditItem); } ev.Result = data.OrderByDescending(x => x.DeletionDate).ToList(); }, ProgressChanged = ev => { // If progress has to be notified to user, use the following method: SetWorkingMessage("Loading entities with auditing enabled..."); }, PostWorkCallBack = ev => { GridDeletedRecords.DataSource = ev.Result; }, AsyncArgument = null, IsCancelable = true, MessageWidth = 340, MessageHeight = 150 }); } }
private void PullDataFromAttributeAuditDetail(AttributeAuditDetail attributeDetail, Microsoft.Office.Interop.Excel._Worksheet workSheet, string title) { var AttributeColl = attributeDetail.OldValue.Attributes; if (ColumnCount != AttributeColl.Count) { // Add Columns foreach (var ColumnName in AttributeColl.Keys) { if (!ColumnSet.ContainsKey(ColumnName)) { ColumnCount++; string attributeType = AttributeColl[ColumnName].GetType().ToString(); if (attributeType == "Microsoft.Xrm.Sdk.EntityReference") { ColumnSet.Add(ColumnName, new List <ColumnDetail>() { new ColumnDetail() { AttributeName = ColumnName, Column = ColumnName + "_GUID", position = ColumnCount }, new ColumnDetail() { AttributeName = ColumnName, Column = ColumnName + "_Name", position = (ColumnCount + 1) } }); workSheet.Cells[1, ExcelColumns[ColumnCount + 1]] = ColumnName + "_GUID"; workSheet.Cells[1, ExcelColumns[ColumnCount + 2]] = ColumnName + "_Name"; ColumnCount++; } else { ColumnSet.Add(ColumnName, new List <ColumnDetail>() { new ColumnDetail() { AttributeName = ColumnName, Column = ColumnName, position = ColumnCount } }); workSheet.Cells[1, ExcelColumns[ColumnCount + 1]] = ColumnName; } } } } workSheet.Cells[rowCount, "A"] = title; foreach (KeyValuePair <string, List <ColumnDetail> > item in ColumnSet) { string cellValue = ""; if (AttributeColl.ContainsKey(item.Key)) { var attribute = AttributeColl[item.Key]; switch (attribute.GetType().ToString()) { case "Microsoft.Xrm.Sdk.OptionSetValue": cellValue = ((OptionSetValue)attribute).Value.ToString(); break; case "Microsoft.Xrm.Sdk.EntityReference": var ref_ = (EntityReference)attribute; workSheet.Cells[rowCount, ExcelColumns[item.Value[1].position + 1]] = ref_.Name; cellValue = ref_.Id.ToString(); break; default: cellValue = attribute.ToString(); break; } workSheet.Cells[rowCount, ExcelColumns[item.Value[0].position + 1]] = cellValue; } } rowCount++; }
protected DataTable BuildDataTable(CodeActivityContext context, IWorkflowContext workflowContext, IOrganizationService service) { DataTable table = new DataTable() { TableName = workflowContext.PrimaryEntityName }; table.Columns.AddRange(new DataColumn[] { new DataColumn("Attribute"), new DataColumn("Old Value"), new DataColumn("New Value") }); RetrieveRecordChangeHistoryRequest request = new RetrieveRecordChangeHistoryRequest() { Target = new EntityReference(workflowContext.PrimaryEntityName, workflowContext.PrimaryEntityId), PagingInfo = new PagingInfo() { Count = 100, PageNumber = 1 } }; RetrieveRecordChangeHistoryResponse response = service.Execute(request) as RetrieveRecordChangeHistoryResponse; if (response != null && response.AuditDetailCollection.Count > 0) { string onlyIfField = LastUpdateWithThisField.Get(context); AttributeAuditDetail detail = null; for (int i = 0; i < response.AuditDetailCollection.Count; i++) { AttributeAuditDetail thisDetail = response.AuditDetailCollection[i] as AttributeAuditDetail; if (thisDetail != null && (String.IsNullOrEmpty(onlyIfField) || (thisDetail.OldValue.Attributes.Keys.Contains(onlyIfField) || thisDetail.NewValue.Attributes.Keys.Contains(onlyIfField)))) { detail = thisDetail; break; } } if (detail != null && detail.NewValue != null && detail.OldValue != null) { Microsoft.Xrm.Sdk.Messages.RetrieveEntityRequest retrieveEntityRequest = new Microsoft.Xrm.Sdk.Messages.RetrieveEntityRequest() { EntityFilters = EntityFilters.Attributes, LogicalName = workflowContext.PrimaryEntityName }; Microsoft.Xrm.Sdk.Messages.RetrieveEntityResponse retrieveEntityResponse = service.Execute(retrieveEntityRequest) as Microsoft.Xrm.Sdk.Messages.RetrieveEntityResponse; EntityMetadata metadata = retrieveEntityResponse.EntityMetadata; var details = detail.NewValue.Attributes.Keys.Union(detail.OldValue.Attributes.Keys) .Distinct() .Select(a => new { AttributeName = a, DisplayName = this.GetDisplayLabel(metadata, a), OldValue = String.Empty, NewValue = String.Empty }) .OrderBy(a => a.DisplayName); foreach (var item in details) { DataRow newRow = table.NewRow(); newRow["Attribute"] = item.DisplayName; newRow["Old Value"] = GetDisplayValue(detail.OldValue, item.AttributeName); newRow["New Value"] = GetDisplayValue(detail.NewValue, item.AttributeName); table.Rows.Add(newRow); } } } return(table); }