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));
                }
            }
        }
 public virtual void Refresh(ContentMap map, List <EntityReference> references)
 {
     using (var context = this.CreateContext())
     {
         Refresh(context, map, references);
     }
 }
 public virtual void Disassociate(ContentMap map, EntityReference target, Relationship relationship, EntityReferenceCollection relatedEntities)
 {
     using (var context = this.CreateContext())
     {
         this.Disassociate(context, map, target, relationship, relatedEntities);
     }
 }
 public virtual EntityNode Refresh(ContentMap map, EntityReference reference)
 {
     using (var context = this.CreateContext())
     {
         return(Refresh(context, map, reference));
     }
 }
Exemple #5
0
        /// <summary> Select the site marker target page. </summary>
        /// <param name="siteMarkerName"> The site marker name. </param>
        /// <param name="contentMap"> The content map. </param>
        /// <returns> The <see cref="ISiteMarkerTarget"/>. </returns>
        private ISiteMarkerTarget Select(string siteMarkerName, ContentMap contentMap)
        {
            WebPageNode target;

            if (!this.TryGetPageNodeFromSiteMarkerNode(siteMarkerName, contentMap, out target))
            {
                return(null);
            }

            return(this.ToSiteMarkerTarget(target));
        }
        protected virtual void BuildContentMap(ContentMap map, IEnumerable <Entity> entities)
        {
            var sw = Stopwatch.StartNew();

            map.AddRange(entities);

            ApplyBaseSolutionVersionToWebsite(map);

            sw.Stop();

            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Duration: {0} ms", sw.ElapsedMilliseconds));
        }
Exemple #7
0
        /// <summary> The try get page node from site marker node. </summary>
        /// <param name="siteMarkerName"> The site marker name. </param>
        /// <param name="contentMap"> The content map. </param>
        /// <param name="targetNode"> The target node. </param>
        /// <returns> The <see cref="bool"/>. </returns>
        private bool TryGetPageNodeFromSiteMarkerNode(string siteMarkerName, ContentMap contentMap, out WebPageNode targetNode)
        {
            var website = HttpContext.Current.GetWebsite().Entity;
            IDictionary <EntityReference, EntityNode> siteMarkers;

            targetNode = null;

            if (!contentMap.TryGetValue("adx_sitemarker", out siteMarkers))
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, "No Sitemarkers found on Content Map");
                return(false);
            }

            var siteMarkerNode = siteMarkers.Values
                                 .Cast <SiteMarkerNode>()
                                 .FirstOrDefault(e => e.Website.Id == website.Id && e.Name == siteMarkerName);

            if (siteMarkerNode == null || siteMarkerNode.WebPage == null)
            {
                return(false);
            }

            if (!contentMap.TryGetValue(siteMarkerNode.WebPage, out targetNode))
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("No WebPage found on Sitemarker:{0}", siteMarkerNode.Id));
                return(false);
            }

            if (!this.Language.IsCrmMultiLanguageEnabled)
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("WebPage found for Sitemarker:{0} Page:{1}", siteMarkerNode.Id, targetNode.Id));
                return(true);
            }

            // MLP - Find the content webpage for the current language from the target page
            var contentWebPage = targetNode.LanguageContentPages.FirstOrDefault(p => p.WebPageLanguage == this.Language.ContextLanguage.WebsiteLanguageNode);

            if (contentWebPage != null)
            {
                ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("WebPage found for Sitemarker:{0} Language:{1}", siteMarkerNode.Id, this.Language.ContextLanguage.Lcid));
                targetNode = contentWebPage;
                return(true);
            }

            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("No WebPage found for Sitemarker:{0} Language:{1}", siteMarkerNode.Id, this.Language.ContextLanguage.Lcid));
            return(false);
        }
Exemple #8
0
        /// <summary> Select site marker target page with read access. </summary>
        /// <param name="siteMarkerName"> The site marker name. </param>
        /// <param name="contentMap"> The content map. </param>
        /// <returns> The <see cref="ISiteMarkerTarget"/>. </returns>
        private ISiteMarkerTarget SelectWithReadAccess(string siteMarkerName, ContentMap contentMap)
        {
            var         securityProvider = this.Dependencies.GetSecurityProvider();
            var         serviceContext   = this.Dependencies.GetServiceContext();
            WebPageNode target;

            if (!this.TryGetPageNodeFromSiteMarkerNode(siteMarkerName, contentMap, out target))
            {
                return(null);
            }

            if (!securityProvider.TryAssert(serviceContext, target.ToEntity(), CrmEntityRight.Read))
            {
                return(null);
            }

            return(this.ToSiteMarkerTarget(target));
        }
        /// <summary>
        /// Applies base solution version to website. This should only be called AFTER the ContentMap is completely built.
        /// </summary>
        /// <param name="map">ContentMap to apply base solution version.</param>
        private void ApplyBaseSolutionVersionToWebsite(ContentMap map)
        {
            // Apply base solution version to Website
            const string websiteKey = "adx_website";

            if (map.ContainsKey(websiteKey) && map[websiteKey] != null)
            {
                var retrieveBaseSolutionCrmVersion = this.PortalSolutions.BaseSolutionCrmVersion;

                foreach (var node in map[websiteKey])
                {
                    var websiteNode = node.Value as WebsiteNode;

                    if (websiteNode != null)
                    {
                        websiteNode.CurrentBaseSolutionCrmVersion = retrieveBaseSolutionCrmVersion;
                    }
                }
            }
        }
        private ContentMap GetContentMap(CrmDbContext context)
        {
            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("LockTimeout={0}", this.LockTimeout));

            var sw = Stopwatch.StartNew();

            var solution   = this.SolutionDefinitionProvider.GetSolution();
            var parameters = this.SolutionDefinitionProvider.GetQueryParameters();
            var map        = new ContentMap(solution)
            {
                LockTimeout = this.LockTimeout.GetValueOrDefault(TimeSpan.FromMinutes(1))
            };
            var entities = this.GetEntities(context, map.Solution, parameters).ToList();

            map.Using(ContentMapLockType.Write, () => this.BuildContentMap(map, entities));

            sw.Stop();

            ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("Duration: {0} ms", sw.ElapsedMilliseconds));

            return(map);
        }
        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));
            }
        }
        private static IEnumerable <EntityReference> RetrieveDisassociatedIntersectEntities(CrmDbContext context, ContentMap map, EntityReference target, Relationship relationship, IEnumerable <EntityReference> relatedEntities)
        {
            var solution = map.Solution;

            // retrieve the intersect entity definition

            ManyRelationshipDefinition mrd;
            EntityDefinition           ed;

            if (solution.ManyRelationships != null &&
                solution.ManyRelationships.TryGetValue(relationship.SchemaName, out mrd) &&
                solution.Entities.TryGetValue(mrd.IntersectEntityname, out ed))
            {
                // retrieve the target node

                EntityNode targetNode;

                if (map.TryGetValue(target, out targetNode))
                {
                    // retrieve the set of existing relationships for validation purposes

                    var entities = RetrieveIntersectEntities(context, map, target, relationship, relatedEntities).Select(e => e.ToEntityReference()).ToList();

                    // reflexive N:N relationships are not supported

                    var targetRelationship = ed.Relationships.Single(r => r.ForeignEntityLogicalname == target.LogicalName && r.ToMany != null);

                    // retrieve the intersect nodes that point to the target

                    var intersects = targetRelationship.ToMany(targetNode).ToList();

                    foreach (var related in relatedEntities)
                    {
                        EntityNode relatedNode;

                        if (map.TryGetValue(related, out relatedNode))
                        {
                            var relatedRelationship = ed.Relationships.Single(r => r.ForeignEntityLogicalname == related.LogicalName && r.ToOne != null);

                            // filter the intersect nodes that point to the related node (as well as the target)
                            // ensure that the intersect does not exist in the collection of retrieved intersects

                            var intersectsToRemove = intersects
                                                     .Where(i => Equals(relatedRelationship.ToOne(i), relatedNode))
                                                     .Select(i => i.ToEntityReference())
                                                     .Where(i => entities.All(e => !Equals(e, i)));

                            foreach (var intersect in intersectsToRemove)
                            {
                                yield return(intersect);
                            }
                        }
                    }
                }
            }
        }
        private static IEnumerable <Entity> RetrieveIntersectEntities(CrmDbContext context, ContentMap map, EntityReference target, Relationship relationship, IEnumerable <EntityReference> relatedEntities)
        {
            var solution = map.Solution;

            // retrieve the intersect entity definition

            ManyRelationshipDefinition mrd;
            EntityDefinition           ed;

            if (solution.ManyRelationships != null &&
                solution.ManyRelationships.TryGetValue(relationship.SchemaName, out mrd) &&
                solution.Entities.TryGetValue(mrd.IntersectEntityname, out ed))
            {
                // build the N:N query to retrieve the intersect entities

                var fetch = ed.CreateFetch();

                // reflexive N:N relationships are not supported

                var targetRelationship = ed.Relationships.Single(r => r.ForeignEntityLogicalname == target.LogicalName);

                var filters = fetch.Entity.Filters.FirstOrDefault() ?? new Filter {
                    Conditions = new List <Condition>()
                };
                filters.Conditions.Add(new Condition(targetRelationship.ForeignIdAttributeName, ConditionOperator.Equal, target.Id));

                var relatedIds   = relatedEntities.Select(related => related.Id).Cast <object>().ToArray();
                var firstRelated = relatedEntities.FirstOrDefault();

                if (firstRelated != null)
                {
                    var relatedRelationship = ed.Relationships.Single(r => r.ForeignEntityLogicalname == firstRelated.LogicalName);

                    filters.Conditions.Add(new Condition(relatedRelationship.ForeignIdAttributeName, ConditionOperator.In, relatedIds));

                    var result = context.Service.RetrieveMultiple(fetch);

                    return(result.Entities);
                }
            }

            return(null);
        }
        /// <summary>
        /// Test whether or not an Entity's published dates are visible in the current context.
        /// </summary>
        /// <param name="context">OrganizationServiceContext</param>
        /// <param name="entity">CRM Entity</param>
        /// <param name="right">Entity Right</param>
        /// <param name="dependencies">Cache Dependency Trace</param>
        /// <param name="map">Content Map</param>
        /// <returns></returns>
        protected override bool TryAssert(OrganizationServiceContext context, Entity entity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            if (entity == null || right == CrmEntityRight.Change)
            {
                return(false);
            }

            dependencies.AddEntityDependency(entity);
            dependencies.AddEntitySetDependency("adx_webrole");
            dependencies.AddEntitySetDependency("adx_websiteaccess");

            var entityName = entity.LogicalName;

            var releaseDate = DateTime.MinValue;
            var expiryDate  = DateTime.MaxValue;

            if (entityName == "adx_webpage" ||
                entityName == "adx_webfile" ||
                entityName == "adx_event" ||
                entityName == "adx_survey" ||
                entityName == "adx_ad")
            {
                releaseDate = entity.GetAttributeValue <DateTime?>("adx_releasedate").GetValueOrDefault(DateTime.MinValue);
                expiryDate  = entity.GetAttributeValue <DateTime?>("adx_expirationdate").GetValueOrDefault(DateTime.MaxValue);
            }
            else if (entityName == "adx_weblink")
            {
                if (!entity.GetAttributeValue <bool?>("adx_disablepagevalidation").GetValueOrDefault(false))
                {
                    var pageReference = entity.GetAttributeValue <EntityReference>("adx_pageid");

                    if (pageReference != null)
                    {
                        WebPageNode rootPage;
                        if (map.TryGetValue(pageReference, out rootPage))
                        {
                            var weblinkWebPage = HttpContext.Current.GetContextLanguageInfo().FindLanguageSpecificWebPageNode(rootPage, false);

                            if (weblinkWebPage != null)
                            {
                                return(TryAssert(context, weblinkWebPage.ToEntity(), right, dependencies));
                            }
                        }
                    }
                }

                return(true);
            }
            else if (entityName == "adx_shortcut")
            {
                if (!entity.GetAttributeValue <bool?>("adx_disabletargetvalidation").GetValueOrDefault(false))
                {
                    var pageReference    = entity.GetAttributeValue <EntityReference>("adx_webpageid");
                    var webFileReference = entity.GetAttributeValue <EntityReference>("adx_webfileid");

                    if (pageReference != null)
                    {
                        WebPageNode rootPage;
                        if (map.TryGetValue(pageReference, out rootPage))
                        {
                            var shortcutWebPage = HttpContext.Current.GetContextLanguageInfo().FindLanguageSpecificWebPageNode(rootPage, false);

                            if (shortcutWebPage != null)
                            {
                                return(TryAssert(context, shortcutWebPage.ToEntity(), right, dependencies));
                            }
                        }
                    }
                    else if (webFileReference != null)
                    {
                        WebFileNode webFile;
                        if (map.TryGetValue(webFileReference, out webFile))
                        {
                            return(TryAssert(context, webFile.ToEntity(), right, dependencies));
                        }
                    }
                }

                var parentPageReference = entity.GetAttributeValue <EntityReference>("adx_parentpage_webpageid");

                if (parentPageReference != null)
                {
                    WebPageNode rootPage;
                    if (map.TryGetValue(parentPageReference, out rootPage))
                    {
                        var parentPage = HttpContext.Current.GetContextLanguageInfo().FindLanguageSpecificWebPageNode(rootPage, false);

                        return(TryAssert(context, parentPage.ToEntity(), right, dependencies));
                    }
                }

                return(true);
            }

            return(UserCanPreview(context, entity) || InnerTryAssert(releaseDate, expiryDate));
        }
        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)));
                }
            }
        }
        protected override bool TryAssert(OrganizationServiceContext context, Entity entity, CrmEntityRight right, CrmEntityCacheDependencyTrace dependencies, ContentMap map)
        {
            switch (entity.LogicalName)
            {
            case "adx_weblink":
                WebLinkNode link;
                if (map.TryGetValue(entity, out link))
                {
                    return(TryAssert(link) || UserCanPreview(context, entity));
                }
                break;

            case "adx_webpage":
                WebPageNode page;
                if (map.TryGetValue(entity, out page))
                {
                    return(TryAssert(page.PublishingState) || UserCanPreview(context, entity));
                }
                break;

            case "adx_weblinkset":
                WebLinkSetNode linkset;
                if (map.TryGetValue(entity, out linkset))
                {
                    return(TryAssert(linkset.PublishingState) || UserCanPreview(context, entity));
                }
                break;

            case "adx_webfile":
                WebFileNode file;
                if (map.TryGetValue(entity, out file))
                {
                    return(TryAssert(file.PublishingState) || UserCanPreview(context, entity));
                }
                break;

            case "adx_shortcut":
                ShortcutNode shortcut;
                if (map.TryGetValue(entity, out shortcut))
                {
                    return(TryAssert(shortcut) || UserCanPreview(context, entity));
                }
                break;

            case "adx_communityforum":
                ForumNode forum;
                if (map.TryGetValue(entity, out forum))
                {
                    return(TryAssert(forum.PublishingState) || UserCanPreview(context, entity));
                }
                break;
            }

            return(this.TryAssert(context, entity, right, dependencies));
        }
        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);
        }