private static ICrmSubscriptionMessage Create(string messageBody, BrokeredMessage message) { Dictionary <string, string> jsonDictionary = JsonConvert.DeserializeObject <Dictionary <string, string> >(messageBody); if (!jsonDictionary.ContainsKey("MessageName")) { ADXTrace.Instance.TraceWarning(TraceCategory.Application, string.Format("Unexpected message format. MessageId: {0} ", message.MessageId)); return(null); } switch (jsonDictionary["MessageName"]) { case "MetadataChange": NotificationUpdateManager.Instance.MetadataDirty = true; return(MetadataMessage.DeserializeMessage(messageBody, message)); case "Create": case "Update": case "Delete": return(EntityRecordMessage.DeserializeMessage(messageBody, message)); case "AssociateEntities": case "DisassociateEntities": return(AssociateDisassociateMessage.DeserializeMessage(messageBody, message)); default: ADXTrace.Instance.TraceWarning(TraceCategory.Application, string.Format("Unexpected message type: {0} ", jsonDictionary["MessageName"])); return(null); } }
/// <summary> /// Pushes CrmSubscriptionMessages into the cache /// </summary> /// <param name="crmSubscriptionMessage">Message to push into the cache</param> /// <param name="isSearchIndexInvalidationMessage">Whther to update message from search subscription</param> // TODO perf might require us to keep a table in memory for lookup and access cache only to insert internal void UpdateNotificationMessageTable(ICrmSubscriptionMessage crmSubscriptionMessage, bool isSearchIndexInvalidationMessage = false) { if (crmSubscriptionMessage is MetadataMessage) { //When New Views are added which is a metadata change we Refresh Search Index Enabled entity List WebAppConfigurationProvider.GetPortalEntityList(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Found a MetaData Change {0} in messageId: {1}.", crmSubscriptionMessage.MessageName, crmSubscriptionMessage.MessageId)); lock (metadataFlagLock) { this.MetadataDirtyEntry = true; } return; } EntityRecordMessage message = crmSubscriptionMessage as EntityRecordMessage; portalUsedEntities = WebAppConfigurationProvider.PortalUsedEntities; //Filter's out Entities Not Used in Portal if (message != null && portalUsedEntities.ContainsKey(message.EntityName)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Pushing MessageId: {0} CRMSubscriptionMessage with entity: {1} and message name: {2} into the Cache.", message.MessageId, message.EntityName, message.MessageName)); var entityKey = string.Format(EntityKey, message.EntityName, isSearchIndexInvalidationMessage ? FromSearchSubscription : FromCacheSubscription); if (!this.DirtyTable.TryAdd(entityKey, new EntityInvalidationMessageAndType(message, isSearchIndexInvalidationMessage))) { EntityInvalidationMessageAndType val = null; var success = this.DirtyTable.TryGetValue(message.EntityName, out val); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Dirty Table already contains entity: {0} and message name: {1} in the Cache with MessageId: {2}. Dropping MessageId: {3} ", message.EntityName, message.MessageName, success ? val.Message.MessageId : Guid.Empty, message.MessageId)); } } }
/// <summary> /// Deserialize the BrokeredMessage message body into a EntityRecordMessage /// </summary> /// <param name="message">BrokeredMessage message body</param> /// <param name="brokeredMessage">BrokeredMessage message</param> /// <returns>ICrmSubscriptionMessage</returns> internal static ICrmSubscriptionMessage DeserializeMessage(string message, BrokeredMessage brokeredMessage) { EntityRecordMessage entityRecordMessage = (EntityRecordMessage)CrmSubscriptionMessage.DeserializeMessage(message, typeof(EntityRecordMessage)); if (entityRecordMessage != null && entityRecordMessage.ValidMessage) { entityRecordMessage.AppendProperties(brokeredMessage); return(entityRecordMessage); } return(null); }
/// <summary> /// Converts a ChangedItem to a protal cache message /// </summary> /// <param name="changedItem">ChangedItem to convert</param> /// <param name="entityRecordMessage">EntityRecordMessage with the corresponding entityName</param> /// <returns>Portal cache message converted from ChangedItem</returns> private PluginMessage CreateMessageForRemovedOrDeletedItem(RemovedOrDeletedItem changedItem, EntityRecordMessage entityRecordMessage) { if (changedItem == null) { return(null); } PluginMessage message; AssociateDisassociateMessage associateDisassociateMessage = entityRecordMessage as AssociateDisassociateMessage; ADXTrace.Instance.TraceWarning(TraceCategory.Application, string.Format("Converting ChangedItem/Deleted with EntityName: {0} and Type:{1} to Portal Cache Message", changedItem.RemovedItem.LogicalName, changedItem.Type.ToString())); if (associateDisassociateMessage == null || changedItem.RemovedItem.LogicalName == "adx_webpageaccesscontrolrule_webrole") { message = new PluginMessage { MessageName = Constants.RemovedOrDeleted, Target = new PluginMessageEntityReference { Name = null, Id = changedItem.RemovedItem.Id, LogicalName = changedItem.RemovedItem.LogicalName, }, }; } else { message = new PluginMessage { MessageName = Constants.Disassociate, Target = new PluginMessageEntityReference { // Special Handling : We want this information to pass to adx code for dissociate and message schema is fixed / nothing can be added, this name/guid would have been null/empty else . Name = associateDisassociateMessage.EntityName, Id = changedItem.RemovedItem.Id, LogicalName = associateDisassociateMessage.RelatedEntity1Name, }, RelatedEntities = new List <PluginMessageEntityReference> { new PluginMessageEntityReference { Name = null, Id = Guid.Empty, LogicalName = associateDisassociateMessage.RelatedEntity2Name, } }, Relationship = new PluginMessageRelationship { PrimaryEntityRole = null, SchemaName = associateDisassociateMessage.RelationshipName, }, }; } return(message); }
/// <summary> /// Converts a ChangedItem to a protal cache message /// </summary> /// <param name="changedItem">ChangedItem to convert</param> /// <param name="entityRecordMessage">EntityRecordMessage with the corresponding entityName</param> /// <returns>Portal cache message converted from ChangedItem</returns> private PluginMessage CreateMessageForNewOrUpdatedItem(NewOrUpdatedItem changedItem, EntityRecordMessage entityRecordMessage) { if (changedItem == null || entityRecordMessage == null) { return(null); } PluginMessage message; AssociateDisassociateMessage associateDisassociateMessage = entityRecordMessage as AssociateDisassociateMessage; string name = this.TryGetTargetName(changedItem.NewOrUpdatedEntity); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Converting ChangedItem with EntityName: {0} and Type:{1} to Portal Cache Message ", changedItem.NewOrUpdatedEntity.LogicalName, changedItem.Type.ToString())); if (associateDisassociateMessage == null || changedItem.NewOrUpdatedEntity.LogicalName == "adx_webpageaccesscontrolrule_webrole") { message = new PluginMessage { MessageName = Constants.CreatedOrUpdated, Target = new PluginMessageEntityReference { Name = name, Id = changedItem.NewOrUpdatedEntity.Id, LogicalName = changedItem.NewOrUpdatedEntity.LogicalName, }, RelatedEntities = null, Relationship = null, }; } else { message = new PluginMessage { MessageName = Constants.Associate, Target = new PluginMessageEntityReference { Name = name, Id = (Guid)changedItem.NewOrUpdatedEntity.Attributes [ CrmChangeTrackingManager.Instance.TryGetPrimaryKey(associateDisassociateMessage.RelatedEntity1Name) ], LogicalName = associateDisassociateMessage.RelatedEntity1Name, }, RelatedEntities = new List <PluginMessageEntityReference> { new PluginMessageEntityReference { Name = null, Id = (Guid)changedItem.NewOrUpdatedEntity.Attributes [ CrmChangeTrackingManager.Instance.TryGetPrimaryKey(associateDisassociateMessage.RelatedEntity2Name) ], LogicalName = associateDisassociateMessage.RelatedEntity2Name, } }, Relationship = new PluginMessageRelationship { PrimaryEntityRole = null, SchemaName = associateDisassociateMessage.RelationshipName, }, }; } return(message); }