public void LogFeatureUsage(FeatureTraceCategory category, HttpContextBase context, string action, string message, int itemCount, string entity, string cRED) { try { var userId = HashPii.GetHashedUserId(context); var sessionId = context != null && context.Session != null ? context.Session.SessionID : string.Empty; bool isPortalEntityAllowed = EntityNamePrivacy.IsPortalEntityAllowed(entity); cRED = string.IsNullOrEmpty(cRED) ? "UnknownPortalAction" : cRED; entity = EntityNamePrivacy.GetEntityName(entity); action = cRED + (!isPortalEntityAllowed ? "__CustomEntityHashedName:" : "__") + entity; // message = EntityGUID this.LogFeatureUsage( category, userId, sessionId, action, message, itemCount, entity, this.Lcid, this.CrmLcid, this.PortalUrl, this.PortalVersion, this.ProductionOrTrial, cRED, this.ElapsedTime()); } catch (Exception ex) { ADXTrace.Instance.TraceError(TraceCategory.Exception, "LogFeatureUsage: received unexpected exception. Message: " + ex.Message); } }
public override bool TryAssert(OrganizationServiceContext context, Entity entity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies) { if (entity != null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format( "right={0}, logicalName={1}, id={2}", right, EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); } else { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("right={0}", right)); } var timer = Stopwatch.StartNew(); var result = InnerTryAssert(context, entity, right, dependencies); timer.Stop(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("result={0}, duration={1} ms", result, timer.ElapsedMilliseconds)); return(result); }
public EntityNode Replace(Entity entity) { entity.ThrowOnNull("entity"); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); var reference = entity.ToEntityReference(); // remove the existing node var removed = Unmerge(reference, ToEntityIdentifier); if (removed != null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Removed: Id={0}", removed.Id)); } // add the new node var added = AddOrGetExisting(entity); if (added != null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Added: Id={0}", added.Id)); } return(added); }
public IEnumerable <CrmEntityIndexDocument> GetDocuments() { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Start"); var dataContext = _index.DataContext; var documentFactory = new FetchXmlIndexDocumentFactory(_index, _fetchXml, _titleAttributeLogicalName, _localeConfig); var currentPageFetchXml = _fetchXml; var knowledgeArticleFilter = new FetchXmlResultsFilter(); while (true) { var request = new OrganizationRequest("ExecuteFetch"); request.Parameters["FetchXml"] = currentPageFetchXml.ToString(); var response = dataContext.Execute(request); if (response == null) { throw new InvalidOperationException("Did not receive valid response from ExecuteFetchRequest."); } var fetchXmlResponse = response.Results["FetchXmlResult"] as string; if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (this._fetchXml.LogicalName == "knowledgearticle") { fetchXmlResponse = knowledgeArticleFilter.Aggregate(fetchXmlResponse, "knowledgearticleid", "record2id.productid", "adx_contentaccesslevelid.adx_contentaccesslevelid", "record2id.connectionid", "annotation.filename", "annotation.notetext", "annotation.annotationid"); } if (this._fetchXml.LogicalName == "annotation") { fetchXmlResponse = knowledgeArticleFilter.Aggregate(fetchXmlResponse, "annotationid", "product.productid"); } } var resultSet = new FetchXmlResultSet(fetchXmlResponse); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("FetchXmlResult:LogicalName={0}, Count={1}", EntityNamePrivacy.GetEntityName(this._fetchXml.LogicalName), resultSet.Count())); foreach (var document in resultSet.Select(documentFactory.GetDocument)) { yield return(document); } if (resultSet.MoreRecords) { currentPageFetchXml = currentPageFetchXml.ForNextPage(resultSet.PagingCookie); } else { break; } } ADXTrace.Instance.TraceInfo(TraceCategory.Application, "End"); }
private static void Associate(CrmDbContext context, ContentMap map, EntityReference target, Relationship relationship, EntityReferenceCollection relatedEntities) { target.ThrowOnNull("target"); relationship.ThrowOnNull("relationship"); relatedEntities.ThrowOnNull("relatedEntities"); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Target: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(target.LogicalName), target.Id)); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Relationship: SchemaName={0}, PrimaryEntityRole={1}", relationship.SchemaName, relationship.PrimaryEntityRole)); foreach (var entity in relatedEntities) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Related: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); } // validate that the relationships do in fact exist by querying for the intersects var entities = map.Using(ContentMapLockType.Read, () => RetrieveIntersectEntities(context, map, target, relationship, relatedEntities)); if (entities != null) { // add intersect entities to the content map map.Using(ContentMapLockType.Write, () => map.AddRange(entities)); foreach (var added in entities) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Added: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(added.LogicalName), added.Id)); } } }
private static void Refresh(CrmDbContext context, ContentMap map, List <EntityReference> references) { if (references.Count > 0) { references[0].ThrowOnNull("reference"); EntityDefinition ed; Dictionary <Guid, Entity> mapEntities = new Dictionary <Guid, Entity>(); bool getEntityDefinition = map.Solution.Entities.TryGetValue(references[0].LogicalName, out ed); if (getEntityDefinition) { List <Guid> guids = new List <Guid>(); foreach (var reference in references) { reference.ThrowOnNull("reference"); guids.Add(reference.Id); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(reference.LogicalName), reference.Id)); } try { string primaryEntityAttribute = EventHubBasedInvalidation.CrmChangeTrackingManager.Instance.TryGetPrimaryKey(references[0].LogicalName); var entities = RetrieveCRMRecords(context, primaryEntityAttribute, references[0], ed, guids); foreach (var entity in entities) { mapEntities.Add(entity.Id, entity); } ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Retrieve Multiple Response for Entity {0} has Record Count {1} , Refrence Count {2} ", references[0].LogicalName, entities.Count, references.Count)); // check if the entity is inactive according to the definition foreach (var reference in references) { var entity = mapEntities.ContainsKey(reference.Id) ? (Entity)mapEntities[reference.Id] : null; // Check if the entity matches on the defined relationships. if (!ed.ShouldIncludeInContentMap(entity)) { continue; } var option = entity != null?entity.GetAttributeValue <OptionSetValue>("statecode") : null; var isActive = ed.ActiveStateCode == null || (option != null && ed.ActiveStateCode.Value == option.Value); var node = map.Using(ContentMapLockType.Write, () => entity != null ? isActive ? map.Replace(entity) : map.Deactivate(reference) : map.Remove(reference)); } } catch (FaultException <OrganizationServiceFault> ) { // an exception occurs when trying to retrieve a non-existing entity ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("An exception occurs when trying to retrieve a non-existing entity")); } } else { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Unknown: logicalName={0}", EntityNamePrivacy.GetEntityName(references[0].LogicalName))); } } }
public static IEnumerable <FilterOptionGroupDrop> Metafilters(EntityListDrop entityList, string query = null, EntityViewDrop entityView = null) { if (entityList == null || String.IsNullOrWhiteSpace(entityList.FilterDefinition)) { return(Enumerable.Empty <FilterOptionGroupDrop>()); } Fetch fetch; try { fetch = Fetch.FromJson(entityList.FilterDefinition); } catch (Exception e) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Error parsing entity list filter definition: {0}", e.ToString())); return(Enumerable.Empty <FilterOptionGroupDrop>()); } if (fetch == null) { return(Enumerable.Empty <FilterOptionGroupDrop>()); } var serviceContext = entityList.PortalViewContext.CreateServiceContext(); var portalContext = entityList.PortalViewContext.CreatePortalContext(); EntityMetadata entityMetadata; try { entityMetadata = serviceContext.GetEntityMetadata(entityList.EntityLogicalName, EntityFilters.Attributes); } catch (FaultException <OrganizationServiceFault> e) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format(@"Error retrieving metadata for entity ""{0}"": {1}", EntityNamePrivacy.GetEntityName(entityList.EntityLogicalName), e.ToString())); return(Enumerable.Empty <FilterOptionGroupDrop>()); } if (entityMetadata == null) { return(Enumerable.Empty <FilterOptionGroupDrop>()); } var currentFilters = String.IsNullOrWhiteSpace(query) ? new NameValueCollection() : HttpUtility.ParseQueryString(query); return(FilterOptionGroup.FromFetch( serviceContext, portalContext, entityMetadata, fetch, currentFilters, entityList.LanguageCode, entityView == null ? null : entityView.Columns.ToDictionary(e => e.LogicalName, e => e.Name)) .Select(@group => new FilterOptionGroupDrop(@group))); }
protected override bool Validate(OrganizationServiceContext context, CrmEntitySearchResult result) { // With permissions now indexed, invalid results should have been filtered out index time. // Monitor whether this is true or whether the permission indexing is missing corner cases. if (!base.Validate(context, result)) { return(false); } if (result.Url == null) { ADXTrace.Instance.TraceWarning(TraceCategory.Application, string.Format("Search result had invalid URL. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); return(false); } if (!ValidateCmsSecurityProvider(context, result)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search result failed CMS security check. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); if (!ValidateEntityPermission(context, result)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search result failed entity permissions security check. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); return(false); } } // Checking products and CALs for a full page of results can be costly // Only check if explicitly enabled (e.g. because a customer is having issues with CAL/product indexing) if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CALProductSearchPostFiltering)) { var contentAccessLevelProvider = new ContentAccessLevelProvider(); var productAccessProvider = new ProductAccessProvider(); if (!ValidateContentAccessLevelAndProducts(context, result, contentAccessLevelProvider, productAccessProvider)) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Search result failed CAL or product filtering. Logical name: {0}, ID: {1}", EntityNamePrivacy.GetEntityName(result.EntityLogicalName), result.EntityID)); return(false); } } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="SavedQueryNotFoundException" /> class. /// </summary> /// <param name="entityLogicalName">Logical Name of the entity the savedquery is associated to.</param> public SavedQueryNotFoundException(string entityLogicalName) : base($"A saved query for the entity {EntityNamePrivacy.GetEntityName(entityLogicalName)} couldn't be found.") { }
/// <summary> /// SavedQueryView constructor /// </summary> /// <param name="serviceContext">OrganizationServiceContext</param> /// <param name="savedQuery">savedquery entity</param> /// <param name="fetchXmlString">Existing known FetchXML for this view</param> /// <param name="layoutXmlString">Existing known LayoutXML for this view</param> /// <param name="languageCode">Language code used to retrieve the localized attribute label</param> /// <param name="aliasColumnNameStringFormat">A format string used to compose an alias column label. Index 0 is the alias attribute display name, index 1 is the aliased entity's display name. Default is "{0} ({1})".</param> public SavedQueryView(OrganizationServiceContext serviceContext, Entity savedQuery, string fetchXmlString, string layoutXmlString, int?languageCode = 0, string aliasColumnNameStringFormat = DefaultAliasColumnNameStringFormat) { if (serviceContext == null) { throw new ArgumentNullException("serviceContext"); } if (savedQuery == null) { throw new ArgumentNullException("savedQuery"); } ServiceContext = serviceContext; SavedQuery = savedQuery; LanguageCode = languageCode ?? 0; AliasColumnNameStringFormat = aliasColumnNameStringFormat; if (string.IsNullOrEmpty(fetchXmlString)) { fetchXmlString = savedQuery.GetAttributeValue <string>("fetchxml"); } if (!string.IsNullOrEmpty(fetchXmlString)) { FetchXml = XElement.Parse(fetchXmlString); SortExpression = SetSortExpression(FetchXml); var entityElement = FetchXml.Element("entity"); if (entityElement != null) { var entityName = entityElement.Attribute("name").Value; EntityLogicalName = entityName; } var response = (RetrieveEntityResponse)ServiceContext.Execute(new RetrieveEntityRequest { LogicalName = EntityLogicalName, EntityFilters = EntityFilters.Attributes }); if (response == null || response.EntityMetadata == null) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Failed to get EntityMetadata for entity of type '{0}'.", EntityNamePrivacy.GetEntityName(EntityLogicalName))); return; } EntityMetadata = response.EntityMetadata; PrimaryKeyLogicalName = EntityMetadata.PrimaryIdAttribute; } if (string.IsNullOrEmpty(layoutXmlString)) { layoutXmlString = savedQuery.GetAttributeValue <string>("layoutxml"); } LayoutXml = XElement.Parse(layoutXmlString); var rowElement = LayoutXml.Element("row"); if (rowElement != null) { var cellNames = rowElement.Elements("cell") .Where(cell => cell.Attribute("ishidden") == null || cell.Attribute("ishidden").Value != "1") .Select(cell => cell.Attribute("name")).Where(name => name != null); CellNames = cellNames; var disabledSortCellNames = rowElement.Elements("cell") .Where(cell => cell.Attribute("disableSorting") != null && cell.Attribute("disableSorting").Value == "1") .Where(cell => cell.Attribute("name") != null) .Select(cell => cell.Attribute("name").Value); DisabledSortCellNames = disabledSortCellNames; var cellWidths = rowElement.Elements("cell") .Where(cell => cell.Attribute("ishidden") == null || cell.Attribute("ishidden").Value != "1") .Where(cell => cell.Attribute("name") != null) .ToDictionary(cell => cell.Attribute("name").Value, cell => Convert.ToInt32(cell.Attribute("width").Value)); CellWidths = cellWidths; } Name = ServiceContext.RetrieveLocalizedLabel(savedQuery.ToEntityReference(), "name", LanguageCode); Id = savedQuery.GetAttributeValue <Guid>("savedqueryid"); }
private static void Trace(OrganizationServiceCachePluginMessage message) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("MessageName={0}, ServiceCacheName={1}, ConnectionStringName={2}", message.MessageName, message.ServiceCacheName, message.ConnectionStringName)); if (message.Target != null && message.Relationship == null) { var entity = message.Target.ToEntityReference(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Id={0}, LogicalName={1}", entity.Id, EntityNamePrivacy.GetEntityName(entity.LogicalName))); } if (message.Category != null) { var category = message.Category.Value; ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("category={0}", category)); } if (message.Target != null && message.Relationship != null && message.RelatedEntities != null) { var target = message.Target.ToEntityReference(); var relationship = message.Relationship.ToRelationship(); var relatedEntities = message.RelatedEntities.ToEntityReferenceCollection(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Target: Id={0}, LogicalName={1}", target.Id, EntityNamePrivacy.GetEntityName(target.LogicalName))); foreach (var entity in relatedEntities) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Related: Id={0}, LogicalName={1}, ", entity.Id, EntityNamePrivacy.GetEntityName(entity.LogicalName))); } } }
/// <summary> /// Indicates whether entity permissions permit the user to add notes to the target entity. /// </summary> protected virtual bool TryAssertAddNote(Guid regardingId) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Start Assert Add Note Privilege on: {0} {1}", Metadata.TargetEntityName, regardingId)); if (!Metadata.FormView.EnableEntityPermissions) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Permission Denied. Entity Permissions have not been enabled."); return(false); } var regarding = new EntityReference(Metadata.TargetEntityName, regardingId); var dataAdapterDependencies = new PortalConfigurationDataAdapterDependencies(); var serviceContext = dataAdapterDependencies.GetServiceContext(); var entityPermissionProvider = new CrmEntityPermissionProvider(); if (!entityPermissionProvider.PermissionsExist) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Permission Denied. Entity Permissions have not been defined. Your request could not be completed."); return(false); } var entityType = IsTimeline ? "adx_portalcomment" : "annotation"; var entityMetadata = serviceContext.GetEntityMetadata(regarding.LogicalName, EntityFilters.All); var primaryKeyName = entityMetadata.PrimaryIdAttribute; var entity = serviceContext.CreateQuery(regarding.LogicalName) .First(e => e.GetAttributeValue <Guid>(primaryKeyName) == regarding.Id); var canAppendTo = entityPermissionProvider.TryAssert(serviceContext, CrmEntityPermissionRight.AppendTo, entity, entityMetadata); var canCreate = entityPermissionProvider.TryAssert(serviceContext, CrmEntityPermissionRight.Create, entityType, regarding); var canAppend = entityPermissionProvider.TryAssert(serviceContext, CrmEntityPermissionRight.Append, entityType, regarding); if (canCreate & canAppend & canAppendTo) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Add Note Permission Granted: {0} {1}", EntityNamePrivacy.GetEntityName(Metadata.TargetEntityName), regardingId)); return(true); } if (!canCreate) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Permission Denied. You do not have the appropriate Entity Permissions to Create notes."); } else if (!canAppendTo) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Permission Denied. You do not have the appropriate Entity Permissions to Append To {0}.", EntityNamePrivacy.GetEntityName(entity.LogicalName))); } else { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Permission Denied. You do not have the appropriate Entity Permissions to Append notes."); } return(false); }
private void ForEachForeignRelationshipToNode(EntityNode node, Action <RelationshipDefinition, EntityNode> action) { var reference = node.ToEntityReference(); // scan over the existing nodes of the map foreach (var lookup in this) { // find the entity descriptor for the current node type var logicalName = lookup.Key; EntityDefinition ed; if (Solution.Entities.TryGetValue(logicalName, out ed)) { if (ed.Relationships != null) { // find the relationships that point to the current node type foreach (var relationship in ed.Relationships.Where(r => r.ForeignEntityLogicalname == reference.LogicalName && r.ToOne != null)) { // scan over the nodes of the entity set foreach (var otherNode in lookup.Value.Values) { // determine if the foreign node points to the current node or not var foreignNode = relationship.ToOne(otherNode); if (foreignNode != null && Equals(foreignNode.ToEntityReference(), reference)) { action(relationship, otherNode); } } } } } else { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Unknown: logicalName={0}", EntityNamePrivacy.GetEntityName(logicalName))); } } }
private EntityNode Unmerge(EntityReference entityReference, Func <EntityNode, EntityNode> getId) { EntityNode originalNode; if (TryGetValue(entityReference, out originalNode)) { EntityDefinition ed; if (Solution.Entities.TryGetValue(entityReference.LogicalName, out ed)) { // reset the N:1 relationships of the original node if (ed.Relationships != null) { foreach (var relationship in ed.Relationships.Where(r => r.ToOne != null && r.Disassociate != null)) { // remove the original node from the 1:N collection of the foreign node var foreignNode = relationship.ToOne(originalNode); if (foreignNode != null && !foreignNode.IsReference) { // disassociate using the relationship definition relationship.Disassociate(foreignNode, originalNode, getId(foreignNode)); } } } } else { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Unknown: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entityReference.LogicalName), entityReference.Id)); } if (!originalNode.IsReference) { // reset the 1:N relationships of the original node ForEachForeignRelationshipToNode(originalNode, (relationship, otherNode) => relationship.Disassociate(originalNode, otherNode, getId(originalNode))); } // remove the node from the map if (RemoveFromLookup(entityReference)) { return(originalNode); } } return(null); }
public EntityNode Deactivate(EntityReference entityReference) { entityReference.ThrowOnNull("entityReference"); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entityReference.LogicalName), entityReference.Id)); var removed = Unmerge(entityReference, ToEntityIdentifier); if (removed != null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Removed: Id={0}", removed.Id)); } return(removed); }
public void DeleteEntitySet(string entityLogicalName) { var indexers = _index.GetIndexers(entityLogicalName).ToArray(); if (!indexers.Any(indexer => indexer.Indexes(entityLogicalName))) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Application does not index entity {0}. No update performed.", entityLogicalName)); return; } ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Deleting index set for EntityLogicalName: {0}", EntityNamePrivacy.GetEntityName(entityLogicalName))); UsingWriter(MethodBase.GetCurrentMethod().Name, false, true, writer => writer.DeleteDocuments(new Term(_index.LogicalNameFieldName, entityLogicalName))); }
public override SiteMapNodeCollection GetChildNodes(SiteMapNode node) { TraceInfo("GetChildNodes({0})", node.Key); var children = new List <SiteMapNode>(); var portal = PortalContext; var context = portal.ServiceContext; var website = portal.Website; // Shorcuts do not have children, may have the same Url as a web page. if (IsShortcutNode(node)) { return(new SiteMapNodeCollection()); } var pageMappingResult = UrlMapping.LookupPageByUrlPath(context, website, node.Url); // If the node URL is that of a web page... if (pageMappingResult.Node != null && pageMappingResult.IsUnique) { var childEntities = context.GetChildPages(pageMappingResult.Node).Union(context.GetChildFiles(pageMappingResult.Node)).Union(context.GetChildShortcuts(pageMappingResult.Node)); foreach (var entity in childEntities) { try { if (entity.LogicalName == "adx_shortcut") { var targetNode = GetShortcutTargetNode(context, entity); var shortcutChildNode = GetShortcutCrmNode(context, entity, targetNode); if (shortcutChildNode != null && ChildNodeValidator.Validate(context, shortcutChildNode)) { children.Add(shortcutChildNode); } } else { var childNode = GetNode(context, entity); if (childNode != null && ChildNodeValidator.Validate(context, childNode)) { children.Add(childNode); } } } catch (Exception e) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format(@"Exception creating child node for node child entity [{0}:{1}]: {2}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id, e.ToString())); continue; } } } // Append values from other site map providers. foreach (SiteMapProvider subProvider in SiteMap.Providers) { // Skip this provider if it is the same as this one. if (subProvider.Name == Name) { continue; } var subProviderChildNodes = subProvider.GetChildNodes(node); if (subProviderChildNodes == null) { continue; } foreach (SiteMapNode childNode in subProviderChildNodes) { children.Add(childNode); } } children.Sort(new SiteMapNodeDisplayOrderComparer()); return(new SiteMapNodeCollection(children.ToArray())); }
protected ExecuteWorkflowResult ExecuteWorkflow(OrganizationServiceContext context, string workflowName, string targetEntityName, Guid targetEntityID) { var workflow = context.CreateQuery("workflow") .FirstOrDefault(w => w.GetAttributeValue <string>("name") == workflowName && w.GetAttributeValue <string>("primaryentity") == targetEntityName && w.GetAttributeValue <bool?>("ondemand").GetValueOrDefault(false)); if (workflow == null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format(@"Workflow named ""{0}"" with primary entity {1} not found.", workflowName, EntityNamePrivacy.GetEntityName(targetEntityName))); return(new WorkflowNotFoundResult(ResourceManager.GetString("Could_Not_Find_Workflow_With_Name_And_Target_EntityName_Message").FormatWith(workflowName, targetEntityName))); } var request = new OrganizationRequest("ExecuteWorkflow"); request.Parameters["WorkflowId"] = workflow.GetAttributeValue <Guid>("workflowid"); request.Parameters["EntityId"] = targetEntityID; var response = context.Execute(request); return(new ExecuteWorkflowResult(ResourceManager.GetString("Workflow_Executed_Successfully_Message").FormatWith(workflowName), response)); }
/// <summary> /// Initializes a new instance of the <see cref="SavedQueryNotFoundException" /> class. /// </summary> /// <param name="entityLogicalName">Logical Name of the entity the savedquery is associated to.</param> /// <param name="queryType">Query Type of the savedquery record in CRM.</param> /// <param name="isDefault">Is the default savedquery.</param> public SavedQueryNotFoundException(string entityLogicalName, int queryType, bool isDefault) : base($"A saved query for entity {EntityNamePrivacy.GetEntityName(entityLogicalName)} with the querytype {queryType} and isdefault {isDefault} couldn't be found.") { }
protected void ExecuteWorkflowOnSourceAndSubscribers(string entityDisplayName, string eventName, string subscriberAssociationName, EntityRole entityRole, string entityPrimaryKeyName) { var entityName = Source.LogicalName; ExecuteWorkflow("Adxstudio.Xrm {0} {1} (Master)".FormatWith(entityDisplayName, eventName), entityName, Source.Id); var entity = Context.CreateQuery(entityName).FirstOrDefault(e => e.GetAttributeValue <Guid>(entityPrimaryKeyName) == Source.Id); if (entity == null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format(@"Entity type ""{0}"" with primary key {1} not found.", EntityNamePrivacy.GetEntityName(entityName), Source.Id)); return; } var subscribers = entity.GetRelatedEntities(Context, subscriberAssociationName, entityRole); foreach (var subscriber in subscribers) { var subscriberEntityName = subscriber.LogicalName; ExecuteWorkflow("Adxstudio.Xrm {0} {1} (Subscriber)".FormatWith(entityDisplayName, eventName), subscriberEntityName, subscriber.Id); } }
/// <summary>The get dependency.</summary> /// <param name="entityName">The entity name.</param> /// <param name="id">The id.</param> /// <returns>The <see cref="string"/>.</returns> internal string GetDependency(string entityName, Guid?id) { if (!string.IsNullOrWhiteSpace(entityName)) { ADXTrace.Instance.TraceVerbose(TraceCategory.Application, string.Format("Entity {0} is Added to Enabled Entity List for Portal Cache", EntityNamePrivacy.GetEntityName(entityName))); WebAppConfigurationProvider.PortalUsedEntities.TryAdd(entityName, true); } return(DependencyEntityObjectFormat.FormatWith(this.CacheEntryChangeMonitorPrefix, entityName, id)); }
public void Remove(OrganizationServiceCachePluginMessage message) { if (message.Category != null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Category={0}", message.Category.Value)); Remove(message.Category.Value); } if (message.Target != null) { var entity = message.Target.ToEntityReference(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); Remove(entity); } if (message.RelatedEntities != null) { var relatedEntities = message.RelatedEntities.ToEntityReferenceCollection(); foreach (var entity in relatedEntities) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); Remove(entity); } } // For cache removals based on metadata invalidation or Publish/PublishAll messages, we // want to also invalidate entity data for all systemform and savedquery records, in // order to invalidate CrmEntityFormView/Web Forms forms. These entity types don't get // the normal Create/Update messages. if (IsPublishMessage(message) || IsMetadataMessage(message)) { Remove("systemform", null); Remove("savedquery", null); Remove("savedqueryvisualization"); Remove(CacheDependencyCalculator.DependencyMetadataFormat.FormatWith(CacheEntryChangeMonitorPrefix)); } }
private static EntityNode Refresh(CrmDbContext context, ContentMap map, EntityReference reference) { reference.ThrowOnNull("reference"); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(reference.LogicalName), reference.Id)); EntityDefinition ed; if (map.Solution.Entities.TryGetValue(reference.LogicalName, out ed)) { // retrieve a fresh entity which also acts as a backend validation var fetch = ed.CreateFetch(); Entity entity = null; try { string primaryIdAttribute = EventHubBasedInvalidation.CrmChangeTrackingManager.Instance.TryGetPrimaryKey(reference.LogicalName); // The condition for the filter on primary key var primaryAttributeCondition = new Condition { Attribute = primaryIdAttribute, Operator = ConditionOperator.Equal, Value = reference.Id }; var attributes = fetch.Entity.Attributes; var fQuery = new Fetch { Distinct = true, SkipCache = true, Entity = new FetchEntity { Name = reference.LogicalName, Attributes = attributes, Filters = new List <Filter>() { new Filter { Type = LogicalOperator.And, Conditions = new List <Condition>() { primaryAttributeCondition } } } } }; entity = context.Service.RetrieveSingle(fQuery, true, true); } catch (FaultException <OrganizationServiceFault> fe) { // an exception occurs when trying to retrieve a non-existing entity if (!fe.Message.EndsWith("Does Not Exist")) { throw; } } // Check if the entity matches on the defined relationships. if (!ed.ShouldIncludeInContentMap(entity)) { return(null); } // check if the entity is inactive according to the definition var option = entity != null?entity.GetAttributeValue <OptionSetValue>("statecode") : null; var isActive = ed.ActiveStateCode == null || (option != null && ed.ActiveStateCode.Value == option.Value); var node = map.Using(ContentMapLockType.Write, () => entity != null ? (isActive ? map.Replace(entity) : map.Deactivate(reference)) : map.Remove(reference)); return(node); } ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Unknown: logicalName={0}", EntityNamePrivacy.GetEntityName(reference.LogicalName))); return(null); }
protected override bool TryCreateHandler(OrganizationServiceContext context, string logicalName, Guid id, out IHttpHandler handler) { if (string.Equals(logicalName, "annotation", StringComparison.InvariantCulture)) { var annotation = context.CreateQuery(logicalName).FirstOrDefault(e => e.GetAttributeValue <Guid>("annotationid") == id); if (annotation != null) { var regarding = annotation.GetAttributeValue <EntityReference>("objectid"); if (regarding != null && string.Equals(regarding.LogicalName, "knowledgearticle", StringComparison.InvariantCulture)) { // Access to a note associated to a knowledge article requires the CMS Security to grant read of the annotation and the related knowledge article. // Additionally, if CAL or Product filtering is enabled and the CAL and/or Product providers reject access to the knowledge article // then access to the note is denied. If CAL and Product filtering are NOT enabled or CAL and/or Product Provider assertion passed, // we must continue to check the Entity Permissions. If the Entity Permission Provider grants read to the knowledge article then the // note can be accessed, otherwise access will be denied. // Assert CMS Security on the annotation and knowledge article. if (TryAssertByCrmEntitySecurityProvider(context, annotation.ToEntityReference()) && TryAssertByCrmEntitySecurityProvider(context, regarding)) { // Assert CAL and/or Product Filtering if enabled. var contentAccessLevelProvider = new ContentAccessLevelProvider(); var productAccessProvider = new ProductAccessProvider(); if (contentAccessLevelProvider.IsEnabled() || productAccessProvider.IsEnabled()) { if (!AssertKnowledgeArticleCalAndProductFiltering(annotation, context, contentAccessLevelProvider, productAccessProvider)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, $"Access to {EntityNamePrivacy.GetEntityName(annotation.LogicalName)} was denied. Id:{id} RegardingId={regarding.Id} RegardingLogicalName={EntityNamePrivacy.GetEntityName(regarding.LogicalName)}"); handler = null; return(false); } } // Assert Entity Permissions on the knowledge article. if (TryAssertByCrmEntityPermissionProvider(context, regarding)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, $"Access to {EntityNamePrivacy.GetEntityName(annotation.LogicalName)} was granted. Id:{id} RegardingId={regarding.Id} RegardingLogicalName={EntityNamePrivacy.GetEntityName(regarding.LogicalName)}"); handler = CreateAnnotationHandler(annotation); return(true); } } ADXTrace.Instance.TraceInfo(TraceCategory.Application, $"Access to {EntityNamePrivacy.GetEntityName(annotation.LogicalName)} was denied. Id:{id} RegardingId={regarding.Id} RegardingLogicalName={EntityNamePrivacy.GetEntityName(regarding.LogicalName)}"); handler = null; return(false); } // Assert CMS security on the regarding entity or assert entity permission on the annotation and the regarding entity. if (TryAssertByCrmEntitySecurityProvider(context, regarding) || TryAssertByCrmEntityPermissionProvider(context, annotation, regarding)) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, $"Access to {EntityNamePrivacy.GetEntityName(annotation.LogicalName)} was granted. Id={id} RegardingId={regarding?.Id} RegardingLogicalName={EntityNamePrivacy.GetEntityName(regarding?.LogicalName)}"); handler = CreateAnnotationHandler(annotation); return(true); } } } if (string.Equals(logicalName, "salesliteratureitem", StringComparison.InvariantCulture)) { var salesliteratureitem = context.CreateQuery(logicalName).FirstOrDefault(e => e.GetAttributeValue <Guid>("salesliteratureitemid") == id); if (salesliteratureitem != null) { //Currently salesliteratureitem.iscustomerviewable is not exposed to CRM UI, therefore get the parent and check visibility. //var isCustomerViewable = salesliteratureitem.GetAttributeValue<bool?>("iscustomerviewable").GetValueOrDefault(); var salesliterature = context.CreateQuery("salesliterature") .FirstOrDefault( e => e.GetAttributeValue <Guid>("salesliteratureid") == salesliteratureitem.GetAttributeValue <EntityReference>("salesliteratureid").Id); if (salesliterature != null) { var isCustomerViewable = salesliterature.GetAttributeValue <bool?>("iscustomerviewable").GetValueOrDefault(); if (isCustomerViewable) { handler = CreateSalesAttachmentHandler(salesliteratureitem); return(true); } } } } if (string.Equals(logicalName, "sharepointdocumentlocation", StringComparison.InvariantCulture)) { var location = context.CreateQuery(logicalName).FirstOrDefault(e => e.GetAttributeValue <Guid>("sharepointdocumentlocationid") == id); if (location != null) { var httpContext = HttpContext.Current; var regardingId = location.GetAttributeValue <EntityReference>("regardingobjectid"); // assert CMS access to the regarding entity or assert entity permission on the entity if (TryAssertByCrmEntitySecurityProvider(context, regardingId) || TryAssertByCrmEntityPermissionProvider(context, location, location.GetAttributeValue <EntityReference>("regardingobjectid"))) { var locationUrl = context.GetDocumentLocationUrl(location); var fileName = httpContext.Request["file"]; // Ensure safe file URL - it cannot begin or end with dot, contain consecutive dots, or any of ~ " # % & * : < > ? \ { | } fileName = Regex.Replace(fileName, @"(\.{2,})|([\~\""\#\%\&\*\:\<\>\?\/\\\{\|\}])|(^\.)|(\.$)", string.Empty); // also removes solidus var folderPath = httpContext.Request["folderPath"]; Uri sharePointFileUrl; if (!string.IsNullOrWhiteSpace(folderPath)) { // Ensure safe folder URL - it cannot begin or end with dot, contain consecutive dots, or any of ~ " # % & * : < > ? \ { | } folderPath = Regex.Replace(folderPath, @"(\.{2,})|([\~\""\#\%\&\*\:\<\>\?\\\{\|\}])|(^\.)|(\.$)", string.Empty).Trim('/'); sharePointFileUrl = new Uri("{0}/{1}/{2}".FormatWith(locationUrl.OriginalString, folderPath, fileName)); } else { sharePointFileUrl = new Uri("{0}/{1}".FormatWith(locationUrl.OriginalString, fileName)); } handler = CreateSharePointFileHandler(sharePointFileUrl, fileName); return(true); } if (!httpContext.Request.IsAuthenticated) { httpContext.Response.ForbiddenAndEndResponse(); } else { // Sending Forbidden gets caught by the Application_EndRequest and throws an error trying to redirect to the Access Denied page. // Send a 404 instead with plain text indicating Access Denied. httpContext.Response.StatusCode = (int)HttpStatusCode.NotFound; httpContext.Response.ContentType = "text/plain"; httpContext.Response.Write("Access Denied"); httpContext.Response.End(); } } } if (string.Equals(logicalName, "activitymimeattachment", StringComparison.InvariantCulture)) { var attachment = context.CreateQuery(logicalName).FirstOrDefault(e => e.GetAttributeValue <Guid>("attachmentid") == id); if (attachment != null) { // retrieve the parent object for the annoation var objectId = attachment.GetAttributeValue <EntityReference>("objectid"); // assert CMS access to the regarding entity or assert entity permission on the entity if (TryAssertByCrmEntitySecurityProvider(context, objectId) || TryAssertByCrmEntityPermissionProvider(context, attachment, attachment.GetAttributeValue <EntityReference>("objectid"))) { handler = CreateActivityMimeAttachmentHandler(attachment); return(true); } } } handler = null; return(false); }
private static DataCollection <Entity> RetrieveCRMRecords(CrmDbContext context, string primaryEntityAttribute, EntityReference reference, EntityDefinition ed, List <Guid> guids) { var fetch = ed.CreateFetch(); //Make Retrive Multiple Query object[] guidArray = guids.Cast <object>().ToArray(); var condition = new Condition(primaryEntityAttribute, ConditionOperator.In, guidArray); if (fetch.Entity.Filters == null || !fetch.Entity.Filters.Any()) { fetch.AddFilter(new Filter { Conditions = new List <Condition> { condition } }); } else { var firstFilter = fetch.Entity.Filters.FirstOrDefault(); if (firstFilter.Conditions == null) { firstFilter.Conditions = new List <Condition>(); } firstFilter.Conditions.Add(condition); } // retrieve a fresh entity which also acts as a backend validation ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Calling Retrieve Multiple Request for Entity {0} ", EntityNamePrivacy.GetEntityName(reference.LogicalName))); RetrieveMultipleResponse responses = (RetrieveMultipleResponse)context.Service.Execute(fetch.ToRetrieveMultipleRequest()); var entities = responses.EntityCollection.Entities; ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Retrieve Multiple Response for Entity {0} has Record Count {1} ", EntityNamePrivacy.GetEntityName(reference.LogicalName), responses.EntityCollection.Entities.Count)); return(entities); }
public virtual void Remove(OrganizationServiceCachePluginMessage message) { try { message.ThrowOnNull("message"); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("MessageName={0}, ServiceCacheName={1}, ConnectionStringName={2}", message.MessageName, message.ServiceCacheName, message.ConnectionStringName)); if (message.Target != null && message.Relationship == null) { var entity = message.Target.ToEntityReference(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Id={0}, LogicalName={1}", entity.Id, EntityNamePrivacy.GetEntityName(entity.LogicalName))); } if (message.Category != null) { var category = message.Category.Value; ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("category={0}", category)); } if (message.Target != null && message.Relationship != null && message.RelatedEntities != null) { var target = message.Target.ToEntityReference(); var relationship = message.Relationship.ToRelationship(); var relatedEntities = message.RelatedEntities.ToEntityReferenceCollection(); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Target: Id={0}, LogicalName={1}", target.Id, EntityNamePrivacy.GetEntityName(target.LogicalName))); foreach (var entity in relatedEntities) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Related: Id={0}, LogicalName={1}", entity.Id, EntityNamePrivacy.GetEntityName(entity.LogicalName))); } } _cache.ExtendedRemoveLocal(message); } catch (Exception error) { ADXTrace.Instance.TraceError(TraceCategory.Application, error.ToString()); } }
private void Disassociate(CrmDbContext context, ContentMap map, EntityReference target, Relationship relationship, EntityReferenceCollection relatedEntities) { target.ThrowOnNull("target"); relationship.ThrowOnNull("relationship"); relatedEntities.ThrowOnNull("relatedEntities"); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Target: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(target.LogicalName), target.Id)); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Relationship: SchemaName={0}, PrimaryEntityRole={1}", relationship.SchemaName, relationship.PrimaryEntityRole)); foreach (var entity in relatedEntities) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Related: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); } var entities = new List <EntityReference>(); if (this.EventHubJobSettings.IsEnabled) { //logic to ignore to get Intersect entity which we already have in eventhub model. EntityReference intersectEntity = new EntityReference(); intersectEntity.LogicalName = target.LogicalName; intersectEntity.Id = target.Id; entities.Add(intersectEntity); } else { // validate that the relationships do in fact not exist by querying for the intersects entities = map.Using(ContentMapLockType.Read, () => RetrieveDisassociatedIntersectEntities(context, map, target, relationship, relatedEntities).ToList()); } if (entities != null) { // add intersect entities to the content map map.Using(ContentMapLockType.Write, () => map.RemoveRange(entities)); } }
protected void CreateControls(Control container, Guid entityId) { // Add a placeholder element with the control ID that will always be present, so // that any potential cell label will still have an control to associate with. var placeholder = new PlaceHolder { ID = Metadata.ControlID }; container.Controls.Add(placeholder); var context = CrmConfigurationManager.CreateContext(ContextName, true); var quickForm = Metadata.QuickForm.QuickFormIds.FirstOrDefault(); if (quickForm == null) { return; } var filterExpression = new FilterExpression(); filterExpression.Conditions.Add(new ConditionExpression("formid", ConditionOperator.Equal, quickForm.FormId)); var systemForm = Xrm.Metadata.OrganizationServiceContextExtensions.GetMultipleSystemFormsWithAllLabels(filterExpression, context).FirstOrDefault(); if (systemForm == null) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Quick Form: A form with ID='{0}' could not be found.".FormatWith(quickForm.FormId))); return; } var formName = systemForm.GetAttributeValue <string>("name"); if (string.IsNullOrWhiteSpace(formName)) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Quick Form: Form with ID='{0}' does not have a name.".FormatWith(quickForm.FormId))); return; } var templatePath = GetPortalQuickFormTemplatePath(ContextName); if (string.IsNullOrWhiteSpace(templatePath)) { ADXTrace.Instance.TraceError(TraceCategory.Application, "Failed to retrieve Quick Form template path."); return; } var iframe = new HtmlIframe { ID = Metadata.ControlID, Src = "about:blank" }; iframe.Attributes.Add("class", "quickform"); iframe.Attributes.Add("data-path", templatePath); iframe.Attributes.Add("data-controlid", Metadata.ControlID); iframe.Attributes.Add("data-formname", formName); iframe.Attributes.Add("data-lookup-element", Metadata.DataFieldName); container.Controls.Remove(placeholder); container.Controls.Add(iframe); var primaryKeyAttributeName = MetadataHelper.GetEntityPrimaryKeyAttributeLogicalName(context, quickForm.EntityName); if (string.IsNullOrWhiteSpace(primaryKeyAttributeName)) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Error retrieving the Primary Key Attribute Name for '{0}'.", EntityNamePrivacy.GetEntityName(quickForm.EntityName))); return; } if (string.IsNullOrWhiteSpace(Metadata.DataFieldName)) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Quick Form: datafieldname is null for QuickForm with ID='{0}'", quickForm.FormId)); return; } var formEntity = context.CreateQuery(Metadata.TargetEntityName).FirstOrDefault(e => e.GetAttributeValue <Guid>(Metadata.TargetEntityPrimaryKeyName) == entityId); if (formEntity == null) { ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format("Failed to retrieve entity record with ID='{0}'", entityId)); return; } var quickFormEntityReference = formEntity.GetAttributeValue <EntityReference>(Metadata.DataFieldName); if (quickFormEntityReference == null) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Attribute on entity record with ID='{0}' is null. Quick Form not loaded.", entityId)); return; } var src = templatePath; src = src.AppendQueryString("entityid", quickFormEntityReference.Id.ToString()); src = src.AppendQueryString("entityname", quickForm.EntityName); src = src.AppendQueryString("entityprimarykeyname", primaryKeyAttributeName); src = src.AppendQueryString("formname", formName); src = src.AppendQueryString("controlid", Metadata.ControlID); iframe.Src = src; }
/// <summary> /// Process the message from the HTTP POST request and rebuild the search index. /// </summary> /// <param name="message"></param> public static void ProcessMessage(OrganizationServiceCachePluginMessage message, SearchIndexInvalidationData searchIndexInvalidationData = null, OrganizationServiceContext serviceContext = null) { if (!SearchManager.Enabled) { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Search isn't enabled for the current application."); return; } if (message == null) { ADXTrace.Instance.TraceError(TraceCategory.Application, "Search Index build failure. Plugin Message is null."); return; } SearchProvider provider; var forceBuild = message.Target != null && message.Target.LogicalName == "adx_website"; if (!TryGetSearchProvider(out provider)) { ADXTrace.Instance.TraceError(TraceCategory.Application, "Search Index build failure. Search Provider could not be found."); return; } if (forceBuild || BuildMessages.Contains(message.MessageName, MessageComparer)) { PerformBuild(provider); ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Search Index was successfully built."); return; } IContentMapProvider contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(); if (UpdateMessages.Contains(message.MessageName, MessageComparer)) { if (message.Target == null || string.IsNullOrEmpty(message.Target.LogicalName)) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an EntityName (entity logical name) parameter.", message.MessageName)); } if (message.Target == null || message.Target.Id == Guid.Empty) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an ID (entity ID) parameter.", message.MessageName)); } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (message.Target.LogicalName == "savedquery") { var cachedSavedQuery = SearchMetadataCache.Instance.SearchSavedQueries.FirstOrDefault(x => x.SavedQueryId == message.Target.Id); if (cachedSavedQuery != null) { // SavedQueryUniqueId is timestamp to verify which change was published and need to invalidate Search Index var actualSavedQueryUniqueId = SearchMetadataCache.Instance.GetSavedQueryUniqueId(message.Target.Id); if (cachedSavedQuery.SavedQueryIdUnique != actualSavedQueryUniqueId) { PerformUpdateAsync(provider, updater => updater.UpdateEntitySet(cachedSavedQuery.EntityName)); SearchMetadataCache.Instance.CompleteMetadataUpdateForSearchSavedQuery(cachedSavedQuery, actualSavedQueryUniqueId); } } } if (message.Target.LogicalName == "adx_webpage" && searchIndexInvalidationData != null) { // bypass cache and go straight to CRM in case cache hasn't been updated yet var response = serviceContext.Execute(new RetrieveRequest { Target = new EntityReference(message.Target.LogicalName, message.Target.Id), ColumnSet = new ColumnSet(new string[] { "adx_parentpageid", "adx_websiteid", "adx_publishingstateid", "adx_partialurl" }) }) as RetrieveResponse; if (response != null && response.Entity != null) { var updatedWebPage = response.Entity; // If the parent page or website change, we need to invalidate that whole section of the web page hierarchy since the web roles // may change, including both root and content pages if MLP is enabled. if (!EntityReferenceEquals(searchIndexInvalidationData.ParentPage, updatedWebPage.GetAttributeValue <EntityReference>("adx_parentpageid")) || !EntityReferenceEquals(searchIndexInvalidationData.Website, updatedWebPage.GetAttributeValue <EntityReference>("adx_websiteid"))) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_webpage", message.Target.Id)); } // If the publishing state or partial URL change, this will effect all the content pages and localized entities underneath them // if MLP is enabled. If MLP is disabled, LCID will equal null, and then just all pages/entities underneath this will reindex. else if (!EntityReferenceEquals(searchIndexInvalidationData.PublishingState, updatedWebPage.GetAttributeValue <EntityReference>("adx_publishingstateid")) || searchIndexInvalidationData.PartialUrl != updatedWebPage.GetAttributeValue <string>("adx_partialurl")) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_webpage", message.Target.Id, searchIndexInvalidationData.Lcid)); } } } if (message.Target.LogicalName == "adx_webpageaccesscontrolrule_webrole") { contentMapProvider.Using(contentMap => { WebPageAccessControlRuleToWebRoleNode webAccessControlToWebRoleNode; if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out webAccessControlToWebRoleNode)) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_webpage", webAccessControlToWebRoleNode.WebPageAccessControlRule.WebPage.Id)); } }); } if (message.Target.LogicalName == "adx_webpageaccesscontrolrule") { contentMapProvider.Using(contentMap => { WebPageAccessControlRuleNode webAccessControlNode; if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out webAccessControlNode)) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_webpage", webAccessControlNode.WebPage.Id)); } }); } if (message.Target.LogicalName == "adx_communityforumaccesspermission") { contentMapProvider.Using(contentMap => { ForumAccessPermissionNode forumAccessNode; if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out forumAccessNode)) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_communityforum", forumAccessNode.Forum.Id)); } }); } if (message.Target.LogicalName == "connection") { var fetch = new Fetch { Entity = new FetchEntity("connection") { Filters = new[] { new Filter { Conditions = new List <Condition> { new Condition("connectionid", ConditionOperator.Equal, message.Target.Id) } } } } }; var connectionEntity = ((RetrieveSingleResponse)serviceContext.Execute(fetch.ToRetrieveSingleRequest())).Entity; var record1Id = connectionEntity.GetAttributeValue <EntityReference>("record1id"); var record2Id = connectionEntity.GetAttributeValue <EntityReference>("record2id"); // new product association to knowledge article could mean new product filtering rules if (record1Id != null && record1Id.LogicalName == "knowledgearticle" && record2Id != null && record2Id.LogicalName == "product") { PerformUpdate(provider, updater => updater.UpdateEntity("knowledgearticle", record1Id.Id)); } } if (message.Target.LogicalName == "adx_contentaccesslevel") { var fetch = GetEntityFetch("adx_knowledgearticlecontentaccesslevel", "knowledgearticleid", "adx_contentaccesslevelid", message.Target.Id.ToString()); var entities = FetchEntities(serviceContext, fetch); var guids = entities.Select(e => e.GetAttributeValue <Guid>("knowledgearticleid")).ToList(); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("knowledgearticle", "knowledgearticleid", guids)); } if (message.Target.LogicalName == "product") { var fetch = GetEntityFetch("connection", "record2id", "record1id", message.Target.Id.ToString()); var entities = FetchEntities(serviceContext, fetch); var guids = entities.Select(e => e.GetAttributeValue <EntityReference>("record2id")).Select(g => g.Id).Distinct().ToList(); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("knowledgearticle", "knowledgearticleid", guids)); } if (message.Target.LogicalName == "annotation") { var annotationFetch = new Fetch { Entity = new FetchEntity("annotation", new[] { "objectid" }) { Filters = new[] { new Filter { Conditions = new List <Condition> { new Condition("annotationid", ConditionOperator.Equal, message.Target.Id), } } } } }; var response = (RetrieveSingleResponse)serviceContext.Execute(annotationFetch.ToRetrieveSingleRequest()); if (response.Entity == null) { ADXTrace.Instance.TraceError(TraceCategory.Application, $"Retrieve of annotation entity failed for annotationId : {message.Target.Id}"); throw new TransientNullReferenceException($"Retrieve of annotation entity failed for annotationId : {message.Target.Id}"); } var knowledgeArticle = response.Entity?.GetAttributeValue <EntityReference>("objectid"); if (knowledgeArticle == null) { ADXTrace.Instance.TraceError(TraceCategory.Application, $"Could not find objectId in the retrieved annotation with annotationId : {message.Target.Id}"); throw new TransientNullReferenceException($"Could not find objectId in the retrieved annotation with annotationId : {message.Target.Id}"); } if (knowledgeArticle.Id != Guid.Empty && knowledgeArticle.LogicalName == "knowledgearticle") { //Updating Knowledge Article related to this Annotation PerformUpdate(provider, updater => updater.UpdateEntity("knowledgearticle", knowledgeArticle.Id)); } } //Re-indexing annotations and related knowledge articles if NotesFilter gets changes if (message.Target.LogicalName == "adx_sitesetting" && message.Target.Name == "KnowledgeManagement/NotesFilter") { var notes = GetAllNotes(serviceContext); var knowledgeArticles = notes.Select(n => n.GetAttributeValue <EntityReference>("objectid")) .Distinct().Select(ka => ka.Id).Distinct() .ToList(); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("annotation", "annotationid", notes.Select(n => n.Id).Distinct().ToList())); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("knowledgearticle", "knowledgearticleid", knowledgeArticles)); return; } if (message.Target.LogicalName == "adx_sitesetting" && message.Target.Name == "KnowledgeManagement/DisplayNotes") { PerformUpdateAsync(provider, updater => updater.DeleteEntitySet("annotation")); var notes = GetAllNotes(serviceContext); var knowledgeArticles = notes.Select(n => n.GetAttributeValue <EntityReference>("objectid")) .Distinct().Select(ka => ka.Id).Distinct() .ToList(); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("annotation", "annotationid", notes.Select(n => n.Id).Distinct().ToList())); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("knowledgearticle", "knowledgearticleid", knowledgeArticles)); return; } } PerformUpdate(provider, updater => updater.UpdateEntity(message.Target.LogicalName, message.Target.Id)); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search Index was successfully updated. ({0}, {1}:{2})", message.MessageName, EntityNamePrivacy.GetEntityName(message.Target.LogicalName), message.Target.Id)); return; } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (AssociateDisassociateMessages.Contains(message.MessageName, MessageComparer)) { if (message.Target == null || string.IsNullOrEmpty(message.Target.LogicalName)) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an EntityName (entity logical name) parameter.", message.MessageName)); } if (message.Target == null || message.Target.Id == Guid.Empty) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an ID (entity ID) parameter.", message.MessageName)); } if (message.RelatedEntities == null) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an EntityName (entity logical name) parameter.", message.MessageName)); } if ((message.Target.LogicalName == "adx_webpage" && HasRelatedEntityType(message, "adx_webpageaccesscontrolrule")) || (message.Target.LogicalName == "adx_communityforum" && HasRelatedEntityType(message, "adx_communityforumaccesspermission")) || (message.Target.LogicalName == "adx_ideaforum" && HasRelatedEntityType(message, "adx_webrole"))) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree(message.Target.LogicalName, message.Target.Id)); } if (message.Target.LogicalName == "adx_webpageaccesscontrolrule" && (HasRelatedEntityType(message, "adx_webrole") || HasRelatedEntityType(message, "adx_publishingstate"))) { contentMapProvider.Using(contentMap => { WebPageAccessControlRuleNode webAccessControlNode; if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out webAccessControlNode)) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_webpage", webAccessControlNode.WebPage.Id)); } }); } if (message.Target.LogicalName == "adx_communityforumaccesspermission" && HasRelatedEntityType(message, "adx_webrole")) { contentMapProvider.Using(contentMap => { ForumAccessPermissionNode forumAccessNode; if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out forumAccessNode)) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree("adx_communityforum", forumAccessNode.Forum.Id)); } }); } if (message.Target.LogicalName == "adx_contentaccesslevel" && HasRelatedEntityType(message, "knowledgearticle")) { foreach (var entityReference in message.RelatedEntities) { if (entityReference.LogicalName == "knowledgearticle") { PerformUpdate(provider, updater => updater.UpdateEntity(entityReference.LogicalName, entityReference.Id)); } } } //Perform update for disassociate messages from WebNotification Plugin if (message.Target.LogicalName == "knowledgearticle" && (HasRelatedEntityType(message, "adx_contentaccesslevel"))) { PerformUpdate(provider, updater => updater.UpdateEntity(message.Target.LogicalName, message.Target.Id)); } ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search Index was successfully updated. ({0}, {1}:{2})", message.MessageName, EntityNamePrivacy.GetEntityName(message.Target.LogicalName), message.Target.Id)); return; } } if (DeleteMessages.Contains(message.MessageName, MessageComparer)) { if (message.Target == null || string.IsNullOrEmpty(message.Target.LogicalName)) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an EntityName (entity logical name) parameter.", message.MessageName)); } if (message.Target == null || message.Target.Id == Guid.Empty) { throw new HttpException((int)HttpStatusCode.BadRequest, string.Format("Message {0} requires an ID (entity ID) parameter.", message.MessageName)); } if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (message.Target.LogicalName == "adx_webpageaccesscontrolrule" && searchIndexInvalidationData.WebPage != null) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree(searchIndexInvalidationData.WebPage.LogicalName, searchIndexInvalidationData.WebPage.Id)); } if (message.Target.LogicalName == "adx_webpageaccesscontrolrule_webrole" && searchIndexInvalidationData.WebPage != null) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree(searchIndexInvalidationData.WebPage.LogicalName, searchIndexInvalidationData.WebPage.Id)); } if (message.Target.LogicalName == "adx_communityforumaccesspermission" && searchIndexInvalidationData.Forum != null) { PerformUpdateAsync(provider, updater => updater.UpdateCmsEntityTree(searchIndexInvalidationData.Forum.LogicalName, searchIndexInvalidationData.Forum.Id)); } if (message.Target.LogicalName == "connection") { // To update Knowledge Article that was related to this connection(Product) we need to retrieve KAid from index var relatedEntityList = GetRelatedEntities("connectionid", message.Target.Id, 1); if (!relatedEntityList.Any()) { return; } // Taking first here since there can only be one Knowledge Article related to connection var entity = relatedEntityList.First(); if (entity.LogicalName != null && entity.LogicalName.Equals("knowledgearticle")) { PerformUpdate(provider, updater => updater.UpdateEntity("knowledgearticle", entity.Id)); } return; } if (message.Target.LogicalName == "product" || message.Target.LogicalName == "adx_contentaccesslevel") { IEnumerable <EntityReference> relatedKnowledgeArticles = new List <EntityReference>(); var indexedFieldName = "adx_contentaccesslevel"; if (message.Target.LogicalName == "product") { indexedFieldName = FixedFacetsConfiguration.ProductFieldFacetName; } relatedKnowledgeArticles = GetRelatedEntities(indexedFieldName, message.Target.Id, 10000); if (!relatedKnowledgeArticles.Any()) { return; } var knowledgeArticlesIds = relatedKnowledgeArticles.Where(r => r.LogicalName.Equals("knowledgearticle")).Select(i => i.Id).ToList(); PerformUpdateAsync(provider, updater => updater.UpdateEntitySet("knowledgearticle", "knowledgearticleid", knowledgeArticlesIds)); } if (message.Target.LogicalName == "annotation") { var relatedKnowledgeArticles = GetRelatedEntities("annotationid", message.Target.Id, 10); var knowledgeArticleId = relatedKnowledgeArticles.Where(a => a.LogicalName == "knowledgearticle").Select(ka => ka.Id).FirstOrDefault(); //Updating Knowledge Article related to this Annotation PerformUpdate(provider, updater => updater.UpdateEntity("knowledgearticle", knowledgeArticleId)); } } PerformUpdate(provider, updater => updater.DeleteEntity(message.Target.LogicalName, message.Target.Id)); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Search Index was successfully updated. ({0}, {1}:{2})", message.MessageName, EntityNamePrivacy.GetEntityName(message.Target.LogicalName), message.Target.Id)); return; } var supportedMessages = DeleteMessages.Union(BuildMessages.Union(UpdateMessages, MessageComparer), MessageComparer); ADXTrace.Instance.TraceError(TraceCategory.Application, string.Format(@"Search Index Build Failed. Message ""{0}"" is not supported. Valid messages are {1}.", message.MessageName, string.Join(", ", supportedMessages.ToArray()))); }
public EntityNode AddOrGetExisting(Entity entity) { var reference = entity.ToEntityReference(); // retrieve the global lookup for the entity EntityNode node; if (!TryGetValue(reference, out node)) { EntityDefinition ed; if (Solution.Entities.TryGetValue(reference.LogicalName, out ed)) { // create a new node for the entity node = ed.ToNode(entity); // associate the entity nodes Merge(ed, reference, node); } } else { ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Exists: LogicalName={0}, Id={1}", EntityNamePrivacy.GetEntityName(entity.LogicalName), entity.Id)); } return(node); }