示例#1
0
        public FetchXmlIndexDocumentFactory(ICrmEntityIndex index, FetchXml fetchXml, string titleAttributeLogicalName, FetchXmlLocaleConfig localeConfig)
        {
            if (index == null)
            {
                throw new ArgumentNullException("index");
            }

            if (fetchXml == null)
            {
                throw new ArgumentNullException("fetchXml");
            }

            if (titleAttributeLogicalName == null)
            {
                throw new ArgumentNullException("titleAttributeLogicalName");
            }

            if (localeConfig == null)
            {
                throw new ArgumentNullException("localeConfig");
            }

            _index = index;
            _contentMapProvider        = AdxstudioCrmConfigurationManager.CreateContentMapProvider();
            _fetchXml                  = fetchXml;
            _titleAttributeLogicalName = titleAttributeLogicalName;
            _localeConfig              = localeConfig;

            _dataContext = _index.DataContext;
        }
示例#2
0
        private bool HasAdminPrivileges()
        {
            var contentMap    = AdxstudioCrmConfigurationManager.CreateContentMapProvider();
            var webSiteEntity = PortalContext.Current.Website;

            if (webSiteEntity == null)
            {
                return(false);
            }

            WebsiteNode webSite = null;

            contentMap.Using(map => map.TryGetValue(webSiteEntity, out webSite));

            if (webSite == null)
            {
                return(false);
            }

            // Get names of current user roles
            var roleNames = Roles.GetRolesForUser();

            // Select these role nodes
            var userRoles = webSite.WebRoles.Where(role => roleNames.Contains(role.Name));

            // Select web site access permissions
            var permissions = userRoles.SelectMany(role => role.WebsiteAccesses);

            // Check if there is permission with all options active
            var hasAcccess =
                permissions.Any(p => p.ManageContentSnippets.Value && p.ManageSiteMarkers.Value &&
                                p.ManageWebLinkSets.Value && p.PreviewUnpublishedEntities.Value);

            return(hasAcccess);
        }
示例#3
0
        private IWebsiteAccessPermissionProvider GetWebsiteAccessPermissionProvider()
        {
            var portalContext      = CreatePortalContext();
            var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(PortalName);

            return(new RequestCachingWebsiteAccessPermissionProvider(new WebsiteAccessPermissionProvider(portalContext.Website, contentMapProvider), portalContext.Website.ToEntityReference()));
        }
        private EntityReference GetExistingParent(EntityReference child)
        {
            var contentMapProvider      = AdxstudioCrmConfigurationManager.CreateContentMapProvider();
            var dataAdapterDependencies = new PortalConfigurationDataAdapterDependencies(requestContext: Request.RequestContext);

            return(contentMapProvider == null
                                ? GetExistingParent(child, dataAdapterDependencies)
                                : contentMapProvider.Using(map => GetExistingParent(child, dataAdapterDependencies, map)));
        }
        private IFileSystem CreateFileSystem()
        {
            var contentMapProvider      = AdxstudioCrmConfigurationManager.CreateContentMapProvider();
            var contentMapUrlProvider   = PortalCrmConfigurationManager.CreateDependencyProvider().GetDependency <IContentMapEntityUrlProvider>();
            var dataAdapterDependencies = new PortalConfigurationDataAdapterDependencies(requestContext: Request.RequestContext);

            return(contentMapProvider == null || contentMapUrlProvider == null
                                ? (IFileSystem) new EntityFileSystem(dataAdapterDependencies)
                                : new ContentMapFileSystem(contentMapProvider, contentMapUrlProvider, dataAdapterDependencies));
        }
        private static IEnumerable <Tuple <string, string, int> > ContentStyles(IPortalViewContext portalViewContext, SiteMapNode node, IDictionary <string, object> cache)
        {
            if (node == null)
            {
                return(Enumerable.Empty <Tuple <string, string, int> >());
            }

            var cacheKey = "{0}:ContentStyles:{1}".FormatWith(typeof(StyleExtensions).FullName, node.Url);

            object cached;

            if (cache.TryGetValue(cacheKey, out cached) && cached is IEnumerable <Tuple <string, string, int> > )
            {
                return(cached as IEnumerable <Tuple <string, string, int> >);
            }

            // Get all adx_webpages in the site map path, starting from and including the current entity. These are
            // potential containers for content-managed stylesheets.
            var path    = new List <EntityReference>();
            var current = node;

            while (current != null)
            {
                var entityNode = current as CrmSiteMapNode;

                if (entityNode != null && entityNode.HasCrmEntityName("adx_webpage"))
                {
                    path.Add(entityNode.Entity.ToEntityReference());
                }

                current = current.ParentNode;
            }

            if (!path.Any())
            {
                return(Enumerable.Empty <Tuple <string, string, int> >());
            }

            var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(portalViewContext.PortalName);

            var styles = contentMapProvider == null
                                ? ContentStyles(portalViewContext, path)
                                : ContentStyles(portalViewContext, path, contentMapProvider);

            cache[cacheKey] = styles;

            return(styles);
        }
        private bool SolutionDependenciesAvailable(string[] requiredSolutions)
        {
            if (requiredSolutions == null || !requiredSolutions.Any())
            {
                return(true);
            }

            var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(this.PortalViewContext.PortalName);

            if (contentMapProvider == null)
            {
                return(true);
            }

            var availableSolutions = contentMapProvider.Using(map => map.Solution.Solutions);

            return(requiredSolutions.Intersect(availableSolutions, StringComparer.OrdinalIgnoreCase).Count() == requiredSolutions.Length);
        }
示例#8
0
        public virtual string GetRedirectWebPageUrl(IPortalContext context, string portalName = null)
        {
            if (context == null || RedirectWebpageId == null || RedirectWebpageId == Guid.Empty)
            {
                return(null);
            }

            var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(portalName);

            var page = contentMapProvider.Using(contentMap => Select(RedirectWebpageId.GetValueOrDefault(), contentMap));

            if (page == null)
            {
                return(null);
            }

            var urlProvider = PortalCrmConfigurationManager.CreateDependencyProvider(portalName).GetDependency <IContentMapEntityUrlProvider>();

            return(contentMapProvider.Using(contentMap => urlProvider.GetUrl(contentMap, page)));
        }
示例#9
0
        private ApplicationPath GetApplicationPathForSiteMarker(RequestContext request)
        {
            return(GetApplicationPathForSiteMarker(request.HttpContext.Items, () =>
            {
                var crmWebsite = request.HttpContext.GetWebsite();

                if (crmWebsite == null)
                {
                    return null;
                }

                var website = crmWebsite.Entity;

                if (website == null)
                {
                    return null;
                }

                var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(PortalName);

                if (contentMapProvider == null)
                {
                    var serviceContext = PortalCrmConfigurationManager.CreateServiceContext(PortalName);

                    website = serviceContext.MergeClone(website);

                    return GetApplicationPathForSiteMarker(serviceContext, website, request.HttpContext.Items);
                }

                return contentMapProvider.Using(contentMap =>
                {
                    WebsiteNode websiteNode;

                    return contentMap.TryGetValue(website, out websiteNode)
                                                ? GetApplicationPathForSiteMarker(contentMap, websiteNode, request.HttpContext.Items)
                                                : null;
                });
            }));
        }
示例#10
0
        public override void Initialize(string name, NameValueCollection config)
        {
            base.Initialize(name, config);

            var portalName = config["portalName"];

            var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(portalName);

            _underlyingProvider = contentMapProvider != null
                                ? new ContentMapUncachedProvider(contentMapProvider)
                                : new UncachedProvider(portalName);

            var cacheInfoFactory = new CrmEntitySecurityCacheInfoFactory(GetType().FullName);

            bool cachingEnabled;

            if (!bool.TryParse(config["cachingEnabled"], out cachingEnabled))
            {
                cachingEnabled = true;
            }

            if (cachingEnabled)
            {
                _underlyingProvider = new ApplicationCachingCrmEntitySecurityProvider(_underlyingProvider, cacheInfoFactory);
            }

            bool requestCachingEnabled;

            if (!bool.TryParse(config["requestCachingEnabled"], out requestCachingEnabled))
            {
                requestCachingEnabled = true;
            }

            if (requestCachingEnabled && HttpContext.Current != null)
            {
                _underlyingProvider = new RequestCachingCrmEntitySecurityProvider(_underlyingProvider, cacheInfoFactory);
            }
        }
 /// <summary> Initializes a new instance of the <see cref="ContentMapAccessProvider"/> class. </summary>
 /// <param name="contentMapProvider"> The content map provider. </param>
 protected ContentMapAccessProvider(IContentMapProvider contentMapProvider)
 {
     this.ContentMapProvider = contentMapProvider ?? AdxstudioCrmConfigurationManager.CreateContentMapProvider();
 }
 public WebsiteAccessPermissionProvider(Entity website, HttpContext context)
     : this(website, context != null ? context.GetContentMapProvider() : AdxstudioCrmConfigurationManager.CreateContentMapProvider())
 {
 }
 private static IContentMapProvider GetContentMapProvider(string portalName)
 {
     return(AdxstudioCrmConfigurationManager.CreateContentMapProvider(portalName));
 }
        protected virtual IWebsiteAccessPermissionProvider CreateWebsiteAccessPermissionProvider(IPortalContext portal)
        {
            var contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider(PortalName);

            return(new WebsiteAccessPermissionProvider(portal.Website, contentMapProvider));
        }
示例#15
0
        private SearchIndexBuildRequest.SearchIndexInvalidationData GetSearchIndexInvalidationData(OrganizationServiceCachePluginMessage message)
        {
            if (message.Target == null || string.IsNullOrEmpty(message.Target.LogicalName) || message.Target.Id == Guid.Empty)
            {
                return(null);
            }

            var searchIndexInvalidationData = new SearchIndexBuildRequest.SearchIndexInvalidationData();

            IContentMapProvider contentMapProvider = AdxstudioCrmConfigurationManager.CreateContentMapProvider();

            contentMapProvider.Using(contentMap =>
            {
                if (message.Target.LogicalName == "adx_webpage")
                {
                    WebPageNode webPageNode;

                    if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out webPageNode))
                    {
                        searchIndexInvalidationData.PartialUrl = webPageNode.PartialUrl;

                        if (webPageNode.Parent != null)
                        {
                            searchIndexInvalidationData.ParentPage = new EntityReference("adx_webpage", webPageNode.Parent.Id);
                        }

                        if (webPageNode.Website != null)
                        {
                            searchIndexInvalidationData.Website = new EntityReference("adx_website", webPageNode.Website.Id);
                        }

                        if (webPageNode.PublishingState != null)
                        {
                            searchIndexInvalidationData.PublishingState = new EntityReference("adx_publishingstate", webPageNode.PublishingState.Id);
                        }
                    }
                }

                if (message.Target.LogicalName == "adx_webpageaccesscontrolrule_webrole")
                {
                    WebPageAccessControlRuleToWebRoleNode webAccessControlToWebRoleNode;

                    if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out webAccessControlToWebRoleNode))
                    {
                        WebPageAccessControlRuleNode webAccessControlNode = webAccessControlToWebRoleNode.WebPageAccessControlRule;
                        if (webAccessControlNode != null && webAccessControlNode.WebPage != null)
                        {
                            searchIndexInvalidationData.WebPage = new EntityReference("adx_webpage", webAccessControlNode.WebPage.Id);
                        }
                    }
                }

                if (message.Target.LogicalName == "adx_webpageaccesscontrolrule")
                {
                    WebPageAccessControlRuleNode webAccessControlNode;

                    if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out webAccessControlNode))
                    {
                        if (webAccessControlNode.WebPage != null)
                        {
                            searchIndexInvalidationData.WebPage = new EntityReference("adx_webpage", webAccessControlNode.WebPage.Id);
                        }
                    }
                }

                if (message.Target.LogicalName == "adx_communityforumaccesspermission")
                {
                    ForumAccessPermissionNode forumAccessNode;

                    if (contentMap.TryGetValue(new EntityReference(message.Target.LogicalName, message.Target.Id), out forumAccessNode))
                    {
                        if (forumAccessNode.Forum != null)
                        {
                            searchIndexInvalidationData.Forum = new EntityReference("adx_communityforum", forumAccessNode.Forum.Id);
                        }
                    }
                }
            });

            return(searchIndexInvalidationData);
        }
 public PublishedDatesAccessProvider(HttpContext context)
     : this(context != null ? context.GetContentMapProvider() : AdxstudioCrmConfigurationManager.CreateContentMapProvider())
 {
 }
示例#17
0
        public void UpdateCmsEntityTree(string entityLogicalName, Guid rootEntityId, int?lcid = null)
        {
            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Begin updating Cms Entity Tree for logical name: {0}, rootEntityId: {1}", entityLogicalName, rootEntityId));
            var timer = Stopwatch.StartNew();

            if (entityLogicalName == "adx_webpage")
            {
                IContentMapProvider contentMapProvider  = AdxstudioCrmConfigurationManager.CreateContentMapProvider();
                Guid[] descendantLocalizedWebPagesGuids = CmsIndexHelper.GetDescendantLocalizedWebpagesForWebpage(contentMapProvider, rootEntityId, lcid).ToArray();
                Guid[] descendantRootWebPagesGuids      = CmsIndexHelper.GetDescendantRootWebpagesForWebpage(contentMapProvider, rootEntityId).ToArray();

                // -------------------- WEB PAGES ------------------------------
                if (descendantLocalizedWebPagesGuids.Any())
                {
                    var localizedWebPagesUnderTargetWebPageFilter = new Fetch.Filter
                    {
                        Type       = Microsoft.Xrm.Sdk.Query.LogicalOperator.Or,
                        Conditions = new List <Fetch.Condition>()
                        {
                            new Fetch.Condition
                            {
                                Attribute = "adx_webpageid",
                                Operator  = Microsoft.Xrm.Sdk.Query.ConditionOperator.In,
                                Values    = descendantLocalizedWebPagesGuids.Cast <object>().ToList()
                            },
                        }
                    };

                    var webPageIndexers = _index.GetIndexers("adx_webpage", filters: new List <Fetch.Filter> {
                        localizedWebPagesUnderTargetWebPageFilter
                    });

                    UpdateWithIndexers("adx_webpage", webPageIndexers);
                }

                // -------------------- FORUMS ------------------------------
                if (descendantRootWebPagesGuids.Any())
                {
                    var rootWebPagesUnderTargetWebPageFilter = new Fetch.Filter
                    {
                        Type       = Microsoft.Xrm.Sdk.Query.LogicalOperator.Or,
                        Conditions = new List <Fetch.Condition>()
                        {
                            new Fetch.Condition
                            {
                                Attribute = "adx_webpageid",
                                Operator  = Microsoft.Xrm.Sdk.Query.ConditionOperator.In,
                                Values    = descendantRootWebPagesGuids.Cast <object>().ToList()
                            },
                        }
                    };

                    var forumBlogToParentPageLink = new Fetch.Link
                    {
                        Name          = "adx_webpage",
                        FromAttribute = "adx_webpageid",
                        ToAttribute   = "adx_parentpageid",
                        Filters       = new List <Fetch.Filter>()
                        {
                            rootWebPagesUnderTargetWebPageFilter
                        }
                    };

                    Fetch.Link languageFilter = null;

                    if (lcid.HasValue)
                    {
                        languageFilter = new Fetch.Link
                        {
                            Name          = "adx_websitelanguage",
                            FromAttribute = "adx_websitelanguageid",
                            ToAttribute   = "adx_websitelanguageid",
                            Type          = Microsoft.Xrm.Sdk.Query.JoinOperator.Inner,
                            Alias         = "websitelangforupdatefilter",
                            Links         = new List <Fetch.Link>()
                            {
                                new Fetch.Link
                                {
                                    Name          = "adx_portallanguage",
                                    FromAttribute = "adx_portallanguageid",
                                    ToAttribute   = "adx_portallanguageid",
                                    Type          = Microsoft.Xrm.Sdk.Query.JoinOperator.Inner,
                                    Alias         = "portallangforupdatefilter",
                                    Filters       = new List <Fetch.Filter>()
                                    {
                                        new Fetch.Filter
                                        {
                                            Type       = Microsoft.Xrm.Sdk.Query.LogicalOperator.And,
                                            Conditions = new List <Fetch.Condition>()
                                            {
                                                new Fetch.Condition
                                                {
                                                    Attribute = "adx_lcid",
                                                    Operator  = Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal,
                                                    Value     = lcid.Value
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        };
                    }

                    var forumBlogLinks = new List <Fetch.Link>()
                    {
                        forumBlogToParentPageLink
                    };
                    if (languageFilter != null)
                    {
                        forumBlogLinks.Add(languageFilter);
                    }

                    var forumIndexers = _index.GetIndexers("adx_communityforum", links: forumBlogLinks);
                    UpdateWithIndexers("adx_communityforum", forumIndexers);

                    var forumThreadForumLinks = new List <Fetch.Link>()
                    {
                        forumBlogToParentPageLink
                    };
                    if (languageFilter != null)
                    {
                        forumThreadForumLinks.Add(languageFilter);
                    }

                    var forumThreadToParentPageLink = new Fetch.Link
                    {
                        Name          = "adx_communityforum",
                        FromAttribute = "adx_communityforumid",
                        ToAttribute   = "adx_forumid",
                        Links         = forumThreadForumLinks
                    };

                    var forumThreadIndexers = _index.GetIndexers("adx_communityforumthread",
                                                                 links: new List <Fetch.Link>()
                    {
                        forumThreadToParentPageLink
                    });
                    UpdateWithIndexers("adx_communityforumthread", forumThreadIndexers);

                    var forumPostToParentPageLink = new Fetch.Link
                    {
                        Name          = "adx_communityforumthread",
                        FromAttribute = "adx_communityforumthreadid",
                        ToAttribute   = "adx_forumthreadid",
                        Alias         = "adx_communityforumpost_communityforumthread",
                        Links         = new List <Fetch.Link>()
                        {
                            forumThreadToParentPageLink
                        }
                    };

                    var forumPostIndexers = _index.GetIndexers("adx_communityforumpost",
                                                               links: new List <Fetch.Link>()
                    {
                        forumPostToParentPageLink
                    });
                    UpdateWithIndexers("adx_communityforumpost", forumPostIndexers);

                    // -------------------- BLOGS ------------------------------
                    var blogIndexers = _index.GetIndexers("adx_blog", links: forumBlogLinks);
                    UpdateWithIndexers("adx_blog", blogIndexers);

                    var blogPostBlogLinks = new List <Fetch.Link>()
                    {
                        forumBlogToParentPageLink
                    };
                    if (languageFilter != null)
                    {
                        blogPostBlogLinks.Add(languageFilter);
                    }

                    var blogPostParentPageLink = new Fetch.Link
                    {
                        Name          = "adx_blog",
                        FromAttribute = "adx_blogid",
                        ToAttribute   = "adx_blogid",
                        Alias         = "adx_blog_blogpost",
                        Links         = blogPostBlogLinks
                    };

                    var blogPostIndexers = _index.GetIndexers("adx_blogpost", links: new List <Fetch.Link> {
                        blogPostParentPageLink
                    });
                    UpdateWithIndexers("adx_blogpost", blogPostIndexers);
                }
            }
            else if (entityLogicalName == "adx_communityforum")
            {
                UpdateEntity("adx_communityforum", rootEntityId);

                var inForumFilterForThread = new Fetch.Filter
                {
                    Type       = Microsoft.Xrm.Sdk.Query.LogicalOperator.And,
                    Conditions = new List <Fetch.Condition>()
                    {
                        new Fetch.Condition
                        {
                            Attribute = "adx_forumid",
                            Operator  = Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal,
                            Value     = rootEntityId
                        }
                    }
                };

                var forumThreadIndexers = _index.GetIndexers("adx_communityforumthread", filters: new List <Fetch.Filter> {
                    inForumFilterForThread
                });
                UpdateWithIndexers("adx_communityforumthread", forumThreadIndexers);

                var inForumFilterForPost = new Fetch.Link
                {
                    Name          = "adx_communityforumthread",
                    FromAttribute = "adx_communityforumthreadid",
                    ToAttribute   = "adx_forumthreadid",
                    Alias         = "adx_communityforumpost_communityforumthread",
                    Filters       = new List <Fetch.Filter>()
                    {
                        inForumFilterForThread
                    }
                };

                var forumPostIndexers = _index.GetIndexers("adx_communityforumpost", links: new List <Fetch.Link> {
                    inForumFilterForPost
                });
                UpdateWithIndexers("adx_communityforumpost", forumPostIndexers);
            }
            else if (entityLogicalName == "adx_ideaforum")
            {
                UpdateEntity("adx_ideaforum", rootEntityId);

                var inIdeaForumFilter = new Fetch.Filter
                {
                    Type       = Microsoft.Xrm.Sdk.Query.LogicalOperator.And,
                    Conditions = new List <Fetch.Condition>()
                    {
                        new Fetch.Condition
                        {
                            Attribute = "adx_ideaforumid",
                            Operator  = Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal,
                            Value     = rootEntityId
                        }
                    }
                };

                var ideaIndexers = _index.GetIndexers("adx_idea", filters: new List <Fetch.Filter> {
                    inIdeaForumFilter
                });
                UpdateWithIndexers("adx_idea", ideaIndexers);
            }

            timer.Stop();
            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Cms Entity Tree updated for logical name: {0}, rootEntityId: {1}, timespan: {2}", entityLogicalName, rootEntityId, timer.ElapsedMilliseconds));
        }
 /// <summary> Initializes a new instance of the <see cref="WebPageAccessControlSecurityProvider"/> class. </summary>
 /// <param name="context"> The context. </param>
 public WebPageAccessControlSecurityProvider(HttpContext context)
     : this(context != null ? context.GetContentMapProvider() : AdxstudioCrmConfigurationManager.CreateContentMapProvider())
 {
 }
 /// <summary> Initializes a new instance of the <see cref="ContentMapAccessProvider"/> class. </summary>
 /// <param name="context"> The context. </param>
 protected ContentMapAccessProvider(HttpContext context)
     : this(context != null ? context.GetContentMapProvider() : AdxstudioCrmConfigurationManager.CreateContentMapProvider())
 {
 }
        /// <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())));
        }
 private IContentMapProvider GetContentMapProvider()
 {
     return(AdxstudioCrmConfigurationManager.CreateContentMapProvider(PortalName));
 }