Beispiel #1
0
        public void TestContains()
        {
            Entity entity = new Entity();
            entity.Add(new ComponentA());
            Assert.AreEqual(true, entity.Contains<ComponentA>());

            entity.Remove<ComponentA>();
            Assert.AreEqual(false, entity.Contains<ComponentA>());
        }
 public void SetAutonumbers(Entity entity)
 {
     var autonumbers = GetActiveAutonumbersForType(entity.LogicalName);
     foreach (var autonumber in autonumbers)
     {
         if (autonumber.OverwriteIfPopulated
             || !entity.Contains(autonumber.AutonumberField))
             SetAutonumber(entity, autonumber);
     }
 }
Beispiel #3
0
 public static Entity ReplicateWithFields(Entity entity, IEnumerable<string> fieldsToSubmit)
 {
     var submissionEntity = new Entity(entity.LogicalName) {Id = entity.Id};
     if (fieldsToSubmit != null)
     {
         foreach (var field in fieldsToSubmit)
         {
             if (entity.Contains(field))
                 XrmEntity.SetField(submissionEntity, field, XrmEntity.GetField(entity, field));
         }
     }
     return submissionEntity;
 }
Beispiel #4
0
 public void Create(Entity entity, IEnumerable<string> fieldsToSubmit)
 {
     if (fieldsToSubmit != null && fieldsToSubmit.Any())
     {
         var submissionEntity = new Entity(entity.LogicalName) {Id = entity.Id};
         foreach (var field in fieldsToSubmit)
         {
             if (entity.Contains(field))
                 XrmEntity.SetField(submissionEntity, field, XrmEntity.GetField(entity, field));
         }
         Create(submissionEntity);
     }
 }
        public static string ToJSON(Entity entity, Formatting format, int indent)
        {
            StringBuilder sb = new StringBuilder();
            var space = format == Formatting.Indented ? " " : "";
            sb.Append(
                Sep(format, indent + 0) + "{" + space +
                Sep(format, indent + 1) + "\"entity\":" + space + "\"" + entity.LogicalName + "\"," +
                Sep(format, indent + 1) + "\"id\":" + space + "\"{" + entity.Id.ToString() + "}\"," +
                Sep(format, indent + 1) + "\"attributes\":" + space + "[");

            bool first = true;
            foreach (KeyValuePair<string, object> attribute in entity.Attributes)
            {
                Object value = attribute.Value;
                if (attribute.Key == entity.LogicalName + "id")
                {
                    continue;
                }
                if (attribute.Key.EndsWith("_base") && entity.Contains(attribute.Key.Substring(0, attribute.Key.Length - 5)))
                {
                    continue;
                }

                if (first)
                {
                    sb.Append(Sep(format, indent + 2) + "{");
                    first = false;
                }
                else
                    sb.Append("," + Sep(format, indent + 2) + "{");

                if (value is AliasedValue)
                {
                    if (!string.IsNullOrEmpty(((AliasedValue)value).AttributeLogicalName))
                    {
                        sb.Append(Sep(format, indent + 3) + "\"attributelogicalname\":" + space + "\"" + (((AliasedValue)value).AttributeLogicalName) + "\",");
                    }
                    if (!string.IsNullOrEmpty(((AliasedValue)value).EntityLogicalName))
                    {
                        sb.Append(Sep(format, indent + 3) + "\"entitylogicalname\":" + space + "\"" + (((AliasedValue)value).EntityLogicalName) + "\",");
                    }
                    value = (((AliasedValue)value).Value);
                }

                sb.Append(Sep(format, indent + 3) + "\"name\":" + space + "\"" + attribute.Key + "\",");
                sb.Append(Sep(format, indent + 3) + "\"type\":" + space + "\"" + LastClassName(value) + "\",");

                if (value is EntityReference)
                {
                    sb.Append(Sep(format, indent + 3) + "\"entity\":" + space + "\"" + ((EntityReference)value).LogicalName + "\",");
                    if (!string.IsNullOrEmpty(((EntityReference)value).Name))
                    {
                        sb.Append(Sep(format, indent + 3) + "\"namevalue\":" + space + "\"" + ((EntityReference)value).Name + "\",");
                    }
                    value = ((EntityReference)value).Id;

                }

                if (value != null)
                {
                    sb.Append(string.Format(Sep(format, indent + 3) + "\"value\":" + space + "\"{0}\"", AttributeToBaseType(value)));
                }

                sb.Append(Sep(format, indent + 2) + "}");
            }
            sb.Append(Sep(format, indent + 1) + "]");
            sb.Append(Sep(format, indent + 0) + "}");
            return sb.ToString();
        }
Beispiel #6
0
        private string GetEntityName(Entity e)
        {
            try
            {
                var entityName = string.Empty;

                if (e.Contains("privilegeobjecttypecode.objecttypecode"))
                {
                    var alias = e.GetAttributeValue<AliasedValue>("privilegeobjecttypecode.objecttypecode");

                    entityName = alias != null ? alias.Value as string : string.Empty;
                }

                if (!string.IsNullOrEmpty(entityName))
                {
                    var entityMetadata = _entityMetadata
                        .Where(m => m.LogicalName == entityName)
                        .FirstOrDefault();

                    if (entityMetadata != null &&
                        entityMetadata.DisplayName != null &&
                        entityMetadata.DisplayName.UserLocalizedLabel != null)
                    {
                        entityName = entityMetadata.DisplayName.UserLocalizedLabel.Label;
                    }
                }

                return entityName;
            }
            catch
            {
                MessageBox.Show("Error encountered in GetEntityName");
                return "ERROR";
            }
        }
        private string ReplaceParameters(string text, Entity Target, IOrganizationService Service)
        {
            if (String.IsNullOrWhiteSpace(text))
            {
                return "";
            }

            foreach (RuntimeParameter param in RuntimeParameter.GetParametersFromString(text))
            {
                if (!param.IsParentParameter())
                {
                    text = text.Replace(param.ParameterText, param.GetParameterValue(Target));
                }
                else
                {
                    if (Target.Contains(param.ParentLookupName))
                    {
                        var parentRecord = Service.Retrieve(Target.GetAttributeValue<EntityReference>(param.ParentLookupName).LogicalName, Target.GetAttributeValue<EntityReference>(param.ParentLookupName).Id, new ColumnSet(param.AttributeName));
                        text = text.Replace(param.ParameterText, param.GetParameterValue(parentRecord));
                    }
                    else  // Target record has no parent, so use default value
                    {
                        text = text.Replace(param.ParameterText, param.DefaultValue);
                    }
                }
            }

            return text;
        }
        public string GetParameterValue(Entity Target)
        {
            if (Target.Contains(AttributeName))
            {
                if (Target[AttributeName] is EntityReference)
                {
                    // Lookup condition is based on GUID
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<EntityReference>(AttributeName).Id) : Target.GetAttributeValue<EntityReference>(AttributeName).Name;
                }
                else if (Target[AttributeName] is OptionSetValue)
                {
                    // Conditional OptionSetValue is based on the integer value
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<OptionSetValue>(AttributeName).Value.ToString()) : Target.FormattedValues[AttributeName];
                }
                else if (Target[AttributeName] is bool)
                {
                    // Note: Boolean values ignore the match value, they just use the attribute value itself as the condition
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<bool>(AttributeName)) : Target.FormattedValues[AttributeName];
                }
                else if (Target[AttributeName] is DateTime)
                {
                    // If there is a format AND a condition, apply formatting first, then evaluate condition as a string
                    // If there is a condition without any format, evaluate condition as DateTime
                    return String.IsNullOrEmpty(StringFormatter) ? Conditional.GetResult(Target.GetAttributeValue<DateTime>(AttributeName)) : Conditional.GetResult(Target.GetAttributeValue<DateTime>(AttributeName).ToString(StringFormatter));
                }
                else if (Target[AttributeName] is Money)
                {
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<Money>(AttributeName).Value) : Target.GetAttributeValue<Money>(AttributeName).Value.ToString(StringFormatter);
                }
                else if (Target[AttributeName] is int)
                {
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<double>(AttributeName)) : Target.GetAttributeValue<double>(AttributeName).ToString(StringFormatter);
                }
                else if (Target[AttributeName] is decimal)
                {
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<decimal>(AttributeName)) : Target.GetAttributeValue<decimal>(AttributeName).ToString(StringFormatter);
                }
                else if (Target[AttributeName] is double)
                {
                    return Conditional.HasCondition ? Conditional.GetResult(Target.GetAttributeValue<double>(AttributeName)) : Target.GetAttributeValue<double>(AttributeName).ToString(StringFormatter);
                }
                else if (Target[AttributeName] is string)
                {
                    return Conditional.GetResult(Target[AttributeName].ToString());
                }
            }
            else if (AttributeName.Equals("rand"))
            {
                string length = "";
                string stringStyle = "upper";
                int stringLength = 5;  // Seems like reasonable default

                if (StringFormatter.Contains('?'))
                {
                    length = StringFormatter.Split('?')[0];
                    stringStyle = StringFormatter.Split('?')[1].ToLower();
                }
                else
                {
                    length = StringFormatter;
                }

                if (!Int32.TryParse(length, out stringLength))
                {
                    stringLength = 5;
                }

                string stringValues = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                if (stringStyle == "mix")
                {
                    stringValues = stringValues + stringValues.ToLower();
                }
                else if (stringStyle == "lower")
                {
                    stringValues = stringValues.ToLower();
                }

                Random rnd = new Random();
                return String.Join("", Enumerable.Range(0, stringLength).Select(n => stringValues[rnd.Next(stringValues.Length)]));
            }

            return DefaultValue;
        }
 private void OpenView()
 {
     EnableControls(false);
     if (views == null || views.Count == 0)
     {
         LoadViews(OpenView);
         return;
     }
     var viewselector = new SelectViewDialog(this);
     viewselector.StartPosition = FormStartPosition.CenterParent;
     if (viewselector.ShowDialog() == DialogResult.OK)
     {
         view = viewselector.View;
         var fetchDoc = new XmlDocument();
         if (view.Contains("fetchxml"))
         {
             fetchDoc.LoadXml(view["fetchxml"].ToString());
             FetchUpdated(fetchDoc.OuterXml);
         }
     }
     EnableControls(true);
 }
Beispiel #10
0
        private string GetAdministrator(Entity e)
        {
            try
            {
                if (e.Contains("administratorid.domainname"))
                {
                    var er = e.GetAttributeValue<AliasedValue>("administratorid.domainname");

                    if (er != null && er.Value != null)
                    {
                        return er.Value as string;
                    }
                }

                return null;
            }
            catch
            {
                throw new Exception("Error encountered in GetAdministrator");
            }
        }
        /// <summary>
        ///     Return the entity record which is configured as the logical parent of this records autonumber
        /// </summary>
        public Entity GetParentEntity(Entity entity, XrmAutonumber autonumber, IEnumerable<string> fields)
        {
            //Need to split the links to the parent and create a query which returns the parent record via the links
            if (!entity.Contains(autonumber.FirstLinkLookup))
                return null;

            //Create a query which traverses through the keys and entities we defined in our autonumber links
            var query = new QueryExpression();
            query.ColumnSet = XrmService.CreateColumnSet(fields);
            LinkEntity carry = null;
            //for each foreign key entity pairing work from last to first
            for (var i = autonumber.LinksToParent.LinkToParents.Count(); i > 0; i--)
            {
                var thisLink = autonumber.LinksToParent.LinkToParents.ElementAt(i - 1);
                //if this is the last item we need to create it as the type of entity we are returning
                if (i == autonumber.LinksToParent.LinkToParents.Count())
                    query.EntityName = thisLink.LinkTarget;
                //otherwise if this is not the last item we need to add a link from the previous type to this type
                else
                {
                    var previousPair = autonumber.LinksToParent.LinkToParents.ElementAt(i);
                    if (carry == null)
                        carry = query.AddLink(thisLink.LinkTarget, previousPair.LinkFieldTarget, previousPair.LinkFieldSource);
                    else
                        carry = carry.AddLink(thisLink.LinkTarget, previousPair.LinkFieldTarget, previousPair.LinkFieldSource);
                }
                //if this is the first item we need to add a filter on the first id with the value in the lookup from the record we are creating the autonumber for
                if (i == 1)
                {
                    var thisLookupId = entity.GetLookupGuid(thisLink.LinkFieldSource);
                    if (!thisLookupId.HasValue)
                        return null;
                    if (autonumber.LinksToParent.LinkToParents.Count() != 1)
                        carry.LinkCriteria.AddCondition(carry.LinkToEntityName + "id", ConditionOperator.Equal, thisLookupId.Value);
                    else
                        query.Criteria.AddCondition(query.EntityName + "id", ConditionOperator.Equal, thisLookupId.Value);
                }
            }
            //Run the query and if a result return it
            var parent = XrmService.RetrieveMultiple(query);
            if (parent.Entities.Count > 0)
                return parent.Entities[0];
            return null;
        }
        public void When_A_Plugin_Is_Executed_Configurations_Can_Be_Used()
        {
            var fakedContext = new XrmFakedContext();

            var guid1 = Guid.NewGuid();
            var target = new Entity("contact") { Id = guid1 };

            var inputParams = new ParameterCollection { new KeyValuePair<string, object>("Target", target) };

            var unsecureConfiguration = "Unsecure Configuration";
            var secureConfiguration = "Secure Configuration";

            //Execute our plugin against the selected target
            var plugCtx = fakedContext.GetDefaultPluginContext();
            plugCtx.InputParameters = inputParams;

            fakedContext.ExecutePluginWithConfigurations<ConfigurationPlugin>(plugCtx, unsecureConfiguration, secureConfiguration);

            Assert.True(target.Contains("unsecure"));
            Assert.True(target.Contains("secure"));
            Assert.Equal((string)target["unsecure"], unsecureConfiguration);
            Assert.Equal((string)target["secure"], secureConfiguration);
        }
 private static void CreateRecordWithStatusIfAny(Entity entity, IOrganizationService service)
 {
     //if trying to set the state, save it, remove from the entity and save it for changing the status after the creation
     var savedStatusCode = -1;
     var savedStateCode = -1;
     if (entity.Contains("statecode") && entity.Contains("statuscode"))
     {
         savedStateCode = entity.Attributes["statecode"] is OptionSetValue ?
             entity.GetAttributeValue<OptionSetValue>("statecode").Value : -1;
         savedStatusCode = entity.Attributes["statuscode"] is OptionSetValue ?
             entity.GetAttributeValue<OptionSetValue>("statuscode").Value : -1;
         entity.Attributes.Remove("statecode");
         entity.Attributes.Remove("statuscode");
     }
     var entityId = service.Create(entity);
     if (savedStatusCode != -1 && savedStateCode != -1)
     {
         var changeStateToNewRecordRequest = new SetStateRequest
         {
             State = new OptionSetValue(savedStateCode),
             Status = new OptionSetValue(savedStatusCode),
             EntityMoniker = new EntityReference(entity.LogicalName, entityId)
         };
         service.Execute(changeStateToNewRecordRequest);
     }
 }
 // This currently only supports ONE attribute being updated, can be expanded to set/touch several attributes in the future
 private void UpdateAttributes(bool onlychange, string entity, List<string> attributes, object value, Entity record, object currentvalue)
 {
     if (!onlychange || !ValuesEqual(value, currentvalue))
     {
         var updaterecord = new Entity(entity);
         updaterecord.Id = record.Id;
         foreach (var attribute in attributes)
         {
             updaterecord.Attributes.Add(attribute, value);
         }
         Service.Update(updaterecord);
         if (record.Contains(attributes[0]))
         {
             record[attributes[0]] = value;
         }
         else
         {
             record.Attributes.Add(attributes[0], value);
         }
     }
 }
Beispiel #15
0
        private bool GetIsUnderDefaultBusinessUnit(Entity e)
        {
            try
            {
                if (e.Contains("businessunitid.parentbusinessunitid"))
                {
                    var er = e.GetAttributeValue<AliasedValue>("businessunitid.parentbusinessunitid");

                    if (er != null && er.Value != null)
                    {
                        return false;
                    }
                }

                return true;
            }
            catch
            {
                throw new Exception("Error encountered in GetIsUnderDefaultBusinessUnit");
            }
        }
 private void UpdateState(bool touch, bool onlychange, OptionSetValue statusvalue, OptionSetValue statevalue, Entity record)
 {
     var currentstate = record.Contains("statecode") ? record["statecode"] : new OptionSetValue(-1);
     var currentstatus = record.Contains("statuscode") ? record["statuscode"] : new OptionSetValue(-1);
     if (touch)
     {
         statevalue = (OptionSetValue)currentstate;
         statusvalue = (OptionSetValue)currentstatus;
     }
     if (!onlychange || !ValuesEqual(currentstate, statevalue) || !ValuesEqual(currentstatus, statusvalue))
     {
         var req = new SetStateRequest()
         {
             EntityMoniker = record.ToEntityReference(),
             State = statevalue,
             Status = statusvalue
         };
         var resp = Service.Execute(req);
         if (record.Contains("statecode"))
         {
             record["statecode"] = statevalue;
         }
         else
         {
             record.Attributes.Add("statecode", statevalue);
         }
         if (record.Contains("statuscode"))
         {
             record["statuscode"] = statusvalue;
         }
         else
         {
             record.Attributes.Add("statuscode", statusvalue);
         }
     }
 }
Beispiel #17
0
        private string GetNameFromEntityReference(Entity e, string attribute)
        {
            try
            {
                var name = string.Empty;

                if (e.Contains(attribute))
                {
                    var er = e.GetAttributeValue<EntityReference>(attribute);

                    name = er != null ? er.Name : string.Empty;
                }

                return name;
            }
            catch
            {
                throw new Exception("Error encountered in GetNameFromEntityReference for attribute " + attribute);
            }
        }
        /// <summary>
        /// Updates the provided web resource
        /// </summary>
        /// <param name="script">Web resource to update</param>
        internal Guid UpdateWebResource(Entity script)
        {
            try
            {
                if (!script.Contains("webresourceid"))
                {
                    Entity existingEntity = RetrieveWebResource(script["name"].ToString());

                    if (existingEntity == null)
                        return CreateWebResource(script);

                    script.Id = existingEntity.Id;

                    if (!script.Contains("displayname") && existingEntity.Contains("displayname"))
                        script["displayname"] = existingEntity["displayname"];

                    if (!script.Contains("description") && existingEntity.Contains("description"))
                        script["description"] = existingEntity["description"];

                    innerService.Update(script);
                    return script.Id;
                }

                innerService.Update(script);
                return script.Id;
            }
            catch (Exception error)
            {
                throw new Exception("Error while updating web resource: " + error.Message);
            }
        }
Beispiel #19
0
        private string GetAccessRight(Entity e)
        {
            try
            {
                var accessRight = e.Contains("accessright") ?
                    (int)e["accessright"] : -1;

                switch ((AccessRights)accessRight)
                {
                    case AccessRights.AppendAccess:
                        return "Append";
                    case AccessRights.AppendToAccess:
                        return "Append To";
                    case AccessRights.AssignAccess:
                        return "Assign";
                    case AccessRights.CreateAccess:
                        return "Create";
                    case AccessRights.DeleteAccess:
                        return "Delete";
                    case AccessRights.None:
                        return "None";
                    case AccessRights.ReadAccess:
                        return "Read";
                    case AccessRights.ShareAccess:
                        return "Share";
                    case AccessRights.WriteAccess:
                        return "Write";
                }

                return string.Empty;
            }
            catch
            {
                MessageBox.Show("Error encountered in GetAccessRight");
                return "ERROR";
            }
        }
Beispiel #20
0
 private static Entity CleanEntityForUpdate(EntityMetadata metadata, Entity recordToUpdate)
 {
     foreach (var attribute in metadata.Attributes)
     {
         if (!attribute.IsValidForUpdate.Value && recordToUpdate.Contains(attribute.LogicalName))
         {
             recordToUpdate.Attributes.Remove(attribute.LogicalName);
         }
     }
     return recordToUpdate;
 }
Beispiel #21
0
        /// <summary>
        /// Copy view layout form source view to all specified target views
        /// </summary>
        /// <param name="sourceView">Source view</param>
        /// <param name="targetViews">List of target views</param>
        /// <param name="service">Crm organization service</param>
        /// <returns>Indicates if all views have been updated</returns>
        public static List<Tuple<string, string>> PropagateLayout(Entity sourceView, List<Entity> targetViews, IOrganizationService service)
        {
            var errors = new List<Tuple<string, string>>();
            string multiObjectAttribute = string.Empty;

            try
            {
                foreach (Entity targetView in targetViews)
                {
                    if (targetView.Id != sourceView.Id)
                    {
                        bool canUpdateLinkedAttributes = true;

                        if (sourceView["layoutxml"].ToString().Contains(".") && (int)targetView["querytype"] == VIEW_ASSOCIATED)
                        {
                            errors.Add(new Tuple<string, string>(targetView["name"].ToString(), "The associated view has not been updated because of related attributes"));
                            //canUpdateLinkedAttributes = false;
                            continue;
                        }

                        // Update grid cells
                        XmlDocument targetLayout = new XmlDocument();
                        targetLayout.LoadXml(targetView["layoutxml"].ToString());

                        XmlAttribute multiAttr = targetLayout.SelectSingleNode("grid/row").Attributes["multiobjectidfield"];
                        if (multiAttr != null)
                            multiObjectAttribute = multiAttr.Value;

                        // We empty the existing cells
                        for (int i = targetLayout.SelectSingleNode("grid/row").ChildNodes.Count; i > 0; i--)
                        {
                            XmlNode toDelete = targetLayout.SelectSingleNode("grid/row").ChildNodes[i - 1];
                            targetLayout.SelectSingleNode("grid/row").RemoveChild(toDelete);
                        }

                        XmlDocument sourceLayout = new XmlDocument();
                        sourceLayout.LoadXml(sourceView["layoutxml"].ToString());

                        XmlNodeList sourceCellNodes = sourceLayout.SelectNodes("grid/row/cell");

                        var cells = new List<string>();

                        foreach (XmlNode cellNode in sourceCellNodes)
                        {
                            if (!cellNode.Attributes["name"].Value.Contains(".") || (int)targetView["querytype"] != VIEW_ASSOCIATED)
                            {
                                cells.Add(cellNode.Attributes["name"].Value);

                                XmlNode nodeDest = targetLayout.ImportNode(cellNode.Clone(), true);
                                targetLayout.SelectSingleNode("grid/row").AppendChild(nodeDest);
                            }
                        }

                        targetView["layoutxml"] = targetLayout.OuterXml;

                        // Retrieve target fetch data
                        if (targetView.Contains("fetchxml"))
                        {
                            XmlDocument targetFetchDoc = new XmlDocument();
                            targetFetchDoc.LoadXml(targetView["fetchxml"].ToString());

                            // Apply same sorting
                            XmlNodeList targetSortNodes = targetFetchDoc.SelectNodes("fetch/entity/order");

                            // Removes existing sorting
                            for (int i = targetSortNodes.Count; i > 0; i--)
                            {
                                XmlNode toDelete = targetSortNodes[i - 1];
                                targetSortNodes[i - 1].ParentNode.RemoveChild(toDelete);
                            }

                            XmlDocument sourceFetchDoc = new XmlDocument();
                            sourceFetchDoc.LoadXml(sourceView["fetchxml"].ToString());

                            XmlNodeList sourceAttrNodes = sourceFetchDoc.SelectNodes("fetch/entity/attribute");

                            foreach (XmlNode attrNode in sourceAttrNodes)
                            {
                                if (targetFetchDoc.SelectSingleNode("fetch/entity/attribute[@name='" + attrNode.Attributes["name"].Value + "']") == null)
                                {
                                    XmlNode attrNodeToAdd = targetFetchDoc.ImportNode(attrNode, true);
                                    targetFetchDoc.SelectSingleNode("fetch/entity").AppendChild(attrNodeToAdd);
                                }
                            }

                            foreach (XmlNode cellNode in sourceCellNodes)
                            {
                                string name = cellNode.Attributes["name"].Value;
                                if (!name.Contains(".") && targetFetchDoc.SelectSingleNode("fetch/entity/attribute[@name='" + name + "']") == null)
                                {
                                    XmlElement attrNodeToAdd = targetFetchDoc.CreateElement("attribute");
                                    attrNodeToAdd.SetAttribute("name", name);
                                    targetFetchDoc.SelectSingleNode("fetch/entity").AppendChild(attrNodeToAdd);
                                }
                            }

                            XmlNodeList sourceSortNodes = sourceFetchDoc.SelectNodes("fetch/entity/order");

                            // Removes existing sorting
                            foreach (XmlNode orderNode in sourceSortNodes)
                            {
                                XmlNode orderNodeToAdd = targetFetchDoc.ImportNode(orderNode, true);
                                targetFetchDoc.SelectSingleNode("fetch/entity").AppendChild(orderNodeToAdd);
                            }

                            if (canUpdateLinkedAttributes)
                            {
                                // Retrieve source fetch data
                                if (sourceView.Contains("fetchxml"))
                                {
                                    //XmlDocument sourceFetchDoc = new XmlDocument();
                                    //sourceFetchDoc.LoadXml(sourceView["fetchxml"].ToString());

                                    XmlNodeList linkNodes = sourceFetchDoc.SelectNodes("fetch/entity/link-entity");

                                    foreach (XmlNode sourceLinkNode in linkNodes)
                                    {
                                        var alias = sourceLinkNode.Attributes["alias"].Value;

                                        if (cells.FirstOrDefault(c => c.StartsWith(alias + ".")) == null)
                                            continue;

                                        XmlNode targetLinkNode = targetFetchDoc.SelectSingleNode("fetch/entity/link-entity[@alias=\"" + alias + "\"]");

                                        // Adds the missing link-entity node
                                        if (targetLinkNode == null)
                                        {
                                            XmlNode nodeDest = targetFetchDoc.ImportNode(sourceLinkNode.Clone(), true);
                                            XmlAttribute typeAttr = nodeDest.Attributes["link-type"];
                                            if (typeAttr == null)
                                            {
                                                typeAttr = targetFetchDoc.CreateAttribute("link-type");
                                                typeAttr.Value = "outer";
                                                nodeDest.Attributes.Append(typeAttr);
                                            }
                                            else
                                            {
                                                typeAttr.Value = "outer";
                                            }

                                            targetFetchDoc.SelectSingleNode("fetch/entity").AppendChild(nodeDest);
                                        }

                                        // Retrieves node again (if it was added)
                                        targetLinkNode = targetFetchDoc.SelectSingleNode("fetch/entity/link-entity[@alias=\"" + alias + "\"]");

                                        // Removes existing attributes
                                        for (int i = targetLinkNode.ChildNodes.Count; i > 0; i--)
                                        {
                                            if (targetLinkNode.ChildNodes[i - 1].Name == "attribute")
                                            {
                                                XmlNode toDelete = targetLinkNode.ChildNodes[i - 1];
                                                targetLinkNode.RemoveChild(toDelete);
                                            }
                                        }

                                        // Adds the attribute nodes from the source node
                                        foreach (XmlNode node in sourceLinkNode.ChildNodes)
                                        {
                                            if (node.Name == "attribute")
                                            {
                                                XmlNode attributeNode = targetLinkNode.SelectSingleNode("attribute[@name='" + node.Attributes["name"].Value + "']");

                                                if (attributeNode == null)
                                                {
                                                    XmlNode nodeDest = targetFetchDoc.ImportNode(node.Clone(), true);
                                                    targetLinkNode.AppendChild(nodeDest);
                                                }
                                            }
                                        }
                                    }

                                }

                                // Suppression des éléments Attribute inutiles dans la requête
                                List<string> attributesToRemove = new List<string>();

                                foreach (XmlNode attributeNode in targetFetchDoc.SelectNodes("//attribute"))
                                {

                                    if (attributeNode.Attributes["name"].Value == multiObjectAttribute)
                                        break;

                                    bool isFoundInCell = false;

                                    foreach (XmlNode cellNode in sourceLayout.SelectNodes("grid/row/cell"))
                                    {
                                        if (attributeNode.ParentNode.Name == "link-entity")
                                        {
                                            if (cellNode.Attributes["name"].Value == attributeNode.ParentNode.Attributes["alias"].Value + "." + attributeNode.Attributes["name"].Value)
                                            {
                                                isFoundInCell = true;
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            if (attributeNode.Attributes["name"].Value == (attributeNode.ParentNode.Attributes["name"].Value + "id") || cellNode.Attributes["name"].Value == attributeNode.Attributes["name"].Value)
                                            {
                                                isFoundInCell = true;
                                                break;
                                            }
                                        }
                                    }

                                    if (!isFoundInCell)
                                    {
                                        if (attributeNode.ParentNode.Name == "link-entity")
                                        {
                                            attributesToRemove.Add(attributeNode.ParentNode.Attributes["alias"].Value + "." + attributeNode.Attributes["name"].Value);
                                        }
                                        else
                                        {
                                            attributesToRemove.Add(attributeNode.Attributes["name"].Value);
                                        }
                                    }
                                }

                                foreach (string attributeName in attributesToRemove)
                                {
                                    XmlNode node = null;

                                    if (attributeName.Contains("."))
                                    {
                                        node = targetFetchDoc.SelectSingleNode("fetch/entity/link-entity[@alias='" + attributeName.Split('.')[0] + "']/attribute[@name='" + attributeName.Split('.')[1] + "']");
                                        targetFetchDoc.SelectSingleNode("fetch/entity/link-entity[@alias='" + node.ParentNode.Attributes["alias"].Value + "']").RemoveChild(node);
                                    }
                                    else
                                    {
                                        node = targetFetchDoc.SelectSingleNode("fetch/entity/attribute[@name='" + attributeName + "']");
                                        targetFetchDoc.SelectSingleNode("fetch/entity").RemoveChild(node);
                                    }
                                }

                                foreach (XmlNode linkentityNode in targetFetchDoc.SelectNodes("fetch/entity/link-entity"))
                                {
                                    if (linkentityNode != null && linkentityNode.ChildNodes.Count == 0)
                                    {
                                        targetFetchDoc.SelectSingleNode("fetch/entity").RemoveChild(linkentityNode);
                                    }
                                }

                                targetView["fetchxml"] = targetFetchDoc.OuterXml;
                            }
                        }

                        try
                        {
                            var viewToUpdate = new Entity(targetView.LogicalName)
                            {
                                Id = targetView.Id
                            };
                            viewToUpdate["fetchxml"] = targetView["fetchxml"];
                            viewToUpdate["layoutxml"] = targetView["layoutxml"];

                            service.Update(viewToUpdate);
                        }
                        catch (Exception error)
                        {
                            errors.Add(new Tuple<string, string>(targetView["name"].ToString(), error.Message));
                        }
                    }
                }

                return errors;
            }
            catch (Exception error)
            {
                string errorMessage = CrmExceptionHelper.GetErrorMessage(error, false);

                throw new Exception("Error while copying layout to target views: " + errorMessage);
            }
        }