コード例 #1
0
        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);
            }
        }
コード例 #2
0
            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);
            }
コード例 #3
0
        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);
        }
コード例 #4
0
        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");
        }
コード例 #5
0
        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));
                }
            }
        }
コード例 #6
0
        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)));
                }
            }
        }
コード例 #7
0
        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);
        }
コード例 #9
0
 /// <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.")
 {
 }
コード例 #10
0
        /// <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");
        }
コード例 #11
0
        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)));
                }
            }
        }
コード例 #12
0
        /// <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);
        }
コード例 #13
0
        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)));
                }
            }
        }
コード例 #14
0
        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);
        }
コード例 #15
0
        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);
        }
コード例 #16
0
        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)));
        }
コード例 #17
0
        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()));
        }
コード例 #18
0
        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));
        }
コード例 #19
0
 /// <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.")
 {
 }
コード例 #20
0
        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));
        }
コード例 #22
0
        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));
            }
        }
コード例 #23
0
        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);
        }
コード例 #24
0
        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);
        }
コード例 #25
0
        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());
            }
        }
コード例 #27
0
        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())));
        }
コード例 #30
0
        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);
        }