示例#1
0
        /// <summary>
        /// Returns the current search configuration for the specified object level
        /// </summary>
        /// <param name="context"></param>
        /// <param name="searchSettingsObjectLevel"></param>
        /// <returns></returns>
        private static string GetSearchConfigurationImplementation(ClientRuntimeContext context, SearchObjectLevel searchSettingsObjectLevel)
        {
            SearchConfigurationPortability sconfig = new SearchConfigurationPortability(context);
            SearchObjectOwner owner = new SearchObjectOwner(context, searchSettingsObjectLevel);

            ClientResult<string> configresults = sconfig.ExportSearchConfiguration(owner);
            context.ExecuteQueryRetry();

            return configresults.Value;
        }
 public static Web EnsureWeb(ClientRuntimeContext cc, Web web, string propertyToCheck)
 {
     if (!web.IsObjectPropertyInstantiated(propertyToCheck))
     {
         // get instances to root web, since we are processing currently sub site
         cc.Load(web);
         cc.ExecuteQueryRetry();
     }
     return web;
 }
 public static Site EnsureSite(ClientRuntimeContext cc, Site site, string propertyToCheck)
 {
     if (!site.IsObjectPropertyInstantiated(propertyToCheck))
     {
         // get instances to root web, since we are processing currently sub site
         cc.Load(site);
         cc.ExecuteQueryRetry();
     }
     return site;
 }
示例#4
0
        /// <summary>
        /// Checks the server library version of the context for a minimally required version
        /// </summary>
        /// <param name="clientContext">clientContext to operate on</param>
        /// <param name="minimallyRequiredVersion">provide version to validate</param>
        /// <returns>True if it has minimal required version, false otherwise</returns>
        public static bool HasMinimalServerLibraryVersion(this ClientRuntimeContext clientContext, Version minimallyRequiredVersion)
        {
            bool hasMinimalVersion = false;

#if !ONPREMISES
            try
            {
                clientContext.ExecuteQueryRetry();
                hasMinimalVersion = clientContext.ServerLibraryVersion.CompareTo(minimallyRequiredVersion) >= 0;
            }
            catch (PropertyOrFieldNotInitializedException)
            {
                // swallow the exception.
            }
#else
            try
            {
                Uri            urlUri  = new Uri(clientContext.Url);
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create($"{urlUri.Scheme}://{urlUri.DnsSafeHost}:{urlUri.Port}/_vti_pvt/service.cnf");
                request.UseDefaultCredentials = true;

                var response = request.GetResponse();

                using (var dataStream = response.GetResponseStream())
                {
                    // Open the stream using a StreamReader for easy access.
                    using (System.IO.StreamReader reader = new System.IO.StreamReader(dataStream))
                    {
                        // Read the content.Will be in this format
                        // vti_encoding:SR|utf8-nl
                        // vti_extenderversion: SR | 15.0.0.4505

                        string version = reader.ReadToEnd().Split('|')[2].Trim();

                        // Only compare the first three digits
                        var compareToVersion = new Version(minimallyRequiredVersion.Major, minimallyRequiredVersion.Minor, minimallyRequiredVersion.Build, 0);
                        hasMinimalVersion = new Version(version.Split('.')[0].ToInt32(), 0, version.Split('.')[3].ToInt32(), 0).CompareTo(compareToVersion) >= 0;
                    }
                }
            }
            catch (WebException ex)
            {
                Log.Warning(Constants.LOGGING_SOURCE, CoreResources.ClientContextExtensions_HasMinimalServerLibraryVersion_Error, ex.ToDetailedString(clientContext));
            }
#endif
            return(hasMinimalVersion);
        }
示例#5
0
        /// <summary>
        /// Delete the search configuration at the specified object level - does not apply to managed properties.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="searchObjectLevel"></param>
        /// <param name="searchConfiguration"></param>
        private static void DeleteSearchConfigurationImplementation(ClientRuntimeContext context, SearchObjectLevel searchObjectLevel, string searchConfiguration)
        {
#if ONPREMISES
            if (searchObjectLevel == SearchObjectLevel.Ssa)
            {
                // Reference: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.search.portability.searchconfigurationportability_members.aspx
                throw new Exception("You cannot import customized search configuration settings to a Search service application (SSA).");
            }
#endif
            SearchConfigurationPortability searchConfig = new SearchConfigurationPortability(context);
            SearchObjectOwner owner = new SearchObjectOwner(context, searchObjectLevel);

            // Delete search configuration
            searchConfig.DeleteSearchConfiguration(owner, searchConfiguration);
            context.Load(searchConfig);
            context.ExecuteQueryRetry();
        }
 private static bool IsTenantAdminSite(ClientRuntimeContext clientContext)
 {
     try
     {
         var tenant = new Tenant(clientContext);
         clientContext.ExecuteQueryRetry();
         return(true);
     }
     catch (ClientRequestException)
     {
         return(false);
     }
     catch (ServerException)
     {
         return(false);
     }
 }
        /// <summary>
        /// Gets an access token from a <see cref="ClientContext"/> instance. Only works when using an add-in or app-only authentication flow.
        /// </summary>
        /// <param name="clientContext"><see cref="ClientContext"/> instance to obtain an access token for</param>
        /// <returns>Access token for the given <see cref="ClientContext"/> instance</returns>
        public static string GetAccessToken(this ClientRuntimeContext clientContext)
        {
            string accessToken = null;
            EventHandler <WebRequestEventArgs> handler = (s, e) =>
            {
                string authorization = e.WebRequestExecutor.RequestHeaders["Authorization"];
                if (!string.IsNullOrEmpty(authorization))
                {
                    accessToken = authorization.Replace("Bearer ", string.Empty);
                }
            };

            // Issue a dummy request to get it from the Authorization header
            clientContext.ExecutingWebRequest += handler;
            clientContext.ExecuteQueryRetry();
            clientContext.ExecutingWebRequest -= handler;

            return(accessToken);
        }
示例#8
0
 private static bool IsTenantAdminSite(ClientRuntimeContext clientContext)
 {
     if (clientContext.Url.ToLower().Contains(".sharepoint."))
     {
         return(clientContext.Url.ToLower().Contains("-admin.sharepoint."));
     }
     else
     {
         // fall back to old code in case of vanity domains
         try
         {
             var tenant = new Microsoft.Online.SharePoint.TenantAdministration.Tenant(clientContext);
             clientContext.ExecuteQueryRetry();
             return(true);
         }
         catch (ServerException)
         {
             return(false);
         }
     }
 }
示例#9
0
        public static bool HasMinimalServerLibraryVersion(this ClientRuntimeContext clientContext, Version minimallyRequiredVersion)
        {
            bool hasMinimalVersion = false;

#if !ONPREMISES
            try
            {
                clientContext.ExecuteQueryRetry();
                hasMinimalVersion = clientContext.ServerLibraryVersion.CompareTo(minimallyRequiredVersion) >= 0;
            }
            catch (PropertyOrFieldNotInitializedException)
            {
                // swallow the exception.
            }
#else
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(clientContext.Url);

                var response = request.GetResponse();
                if (response.Headers.AllKeys.Contains(MicrosoftSharePointTeamServicesHeader))
                {
                    var responseVersion = new Version(response.Headers[MicrosoftSharePointTeamServicesHeader]);
                    hasMinimalVersion = responseVersion.CompareTo(minimallyRequiredVersion) >= 0;
                }
            }
            catch (WebException ex)
            {
                var response = ex.Response;
                if (response.Headers.AllKeys.Contains(MicrosoftSharePointTeamServicesHeader))
                {
                    var responseVersion = new Version(response.Headers[MicrosoftSharePointTeamServicesHeader]);
                    hasMinimalVersion = responseVersion.CompareTo(minimallyRequiredVersion) >= 0;
                }
            }
#endif
            return(hasMinimalVersion);
        }
示例#10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cc">ClientContext object of an arbitrary site collection accessible by the defined enumeration username and password</param>
        /// <param name="keywordQueryValue">Query to execute</param>
        /// <param name="sites">List of found site collections</param>
        /// <param name="keywordQuery">KeywordQuery instance that will perform the actual queries</param>
        /// <param name="startRow">Row as of which we want to see the results</param>
        /// <returns>Total result rows of the query</returns>
        private static int ProcessQuery(ClientRuntimeContext cc, string keywordQueryValue, List <string> sites, KeywordQuery keywordQuery, int startRow)
        {
            int totalRows = 0;

            keywordQuery.QueryText = keywordQueryValue;
            keywordQuery.RowLimit  = 500;
            keywordQuery.StartRow  = startRow;
            keywordQuery.SelectProperties.Add("SPSiteUrl");
            keywordQuery.SortList.Add("SPSiteUrl", SortDirection.Ascending);
            SearchExecutor searchExec = new SearchExecutor(cc);

            // Important to avoid trimming "similar" site collections
            keywordQuery.TrimDuplicates = false;

            ClientResult <ResultTableCollection> results = searchExec.ExecuteQuery(keywordQuery);

            cc.ExecuteQueryRetry();

            if (results != null)
            {
                if (results.Value[0].RowCount > 0)
                {
                    totalRows = results.Value[0].TotalRows;

                    foreach (var row in results.Value[0].ResultRows)
                    {
                        if (row["SPSiteUrl"] != null)
                        {
                            sites.Add(row["SPSiteUrl"].ToString());
                        }
                    }
                }
            }

            return(totalRows);
        }
示例#11
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="cc">ClientContext object of an arbitrary site collection accessible by the defined enumeration username and password</param>
        /// <param name="keywordQueryValue">Query to execute</param>
        /// <param name="sites">List of found site collections</param>
        /// <param name="keywordQuery">KeywordQuery instance that will perform the actual queries</param>
        /// <param name="startRow">Row as of which we want to see the results</param>
        /// <returns>Total result rows of the query</returns>
        private static int ProcessQuery(ClientRuntimeContext cc, string keywordQueryValue, List<string> sites, KeywordQuery keywordQuery, int startRow)
        {
            int totalRows = 0;

            keywordQuery.QueryText = keywordQueryValue;
            keywordQuery.RowLimit = 500;
            keywordQuery.StartRow = startRow;
            keywordQuery.SelectProperties.Add("SPSiteUrl");
            keywordQuery.SortList.Add("SPSiteUrl", SortDirection.Ascending);
            SearchExecutor searchExec = new SearchExecutor(cc);
            ClientResult<ResultTableCollection> results = searchExec.ExecuteQuery(keywordQuery);
            cc.ExecuteQueryRetry();

            if (results != null)
            {
                if (results.Value[0].RowCount > 0)
                {
                    totalRows = results.Value[0].TotalRows;

                    foreach (var row in results.Value[0].ResultRows)
                    {
                        if (row["SPSiteUrl"] != null)
                        {
                            sites.Add(row["SPSiteUrl"].ToString());
                        }
                    }
                }
            }

            return totalRows;
        }
示例#12
0
        private List <Model.Term> GetTerms <T>(ClientRuntimeContext context, TaxonomyItem parent, int defaultLanguage, Boolean isSiteCollectionTermGroup = false)
        {
            List <Model.Term> termsToReturn = new List <Model.Term>();
            TermCollection    terms;
            var customSortOrder = string.Empty;

            if (parent is TermSet)
            {
                terms           = ((TermSet)parent).Terms;
                customSortOrder = ((TermSet)parent).CustomSortOrder;
            }
            else
            {
                terms           = ((Term)parent).Terms;
                customSortOrder = ((Term)parent).CustomSortOrder;
            }
            context.Load(terms, tms => tms.IncludeWithDefaultProperties(t => t.Labels, t => t.CustomSortOrder,
                                                                        t => t.IsReused, t => t.IsSourceTerm, t => t.SourceTerm, t => t.IsDeprecated, t => t.Description, t => t.Owner));
            context.ExecuteQueryRetry();

            foreach (var term in terms)
            {
                var modelTerm = new Model.Term();
                if (!isSiteCollectionTermGroup || term.IsReused)
                {
                    modelTerm.Id = term.Id;
                }
                modelTerm.Name = term.Name;
                modelTerm.IsAvailableForTagging = term.IsAvailableForTagging;
                modelTerm.IsReused     = term.IsReused;
                modelTerm.IsSourceTerm = term.IsSourceTerm;
                modelTerm.SourceTermId = (term.SourceTerm != null) ? term.SourceTerm.Id : Guid.Empty;
                modelTerm.IsDeprecated = term.IsDeprecated;
                modelTerm.Description  = term.Description;
                modelTerm.Owner        = term.Owner;

                if ((!term.IsReused || term.IsSourceTerm) && term.Labels.Any())
                {
                    foreach (var label in term.Labels)
                    {
                        if ((label.Language == defaultLanguage && label.Value != term.Name) || label.Language != defaultLanguage)
                        {
                            var modelLabel = new Model.TermLabel();
                            modelLabel.IsDefaultForLanguage = label.IsDefaultForLanguage;
                            modelLabel.Value    = label.Value;
                            modelLabel.Language = label.Language;

                            modelTerm.Labels.Add(modelLabel);
                        }
                    }
                }
                //else
                //{
                //    foreach (var label in term.Labels)
                //    {
                //        var modelLabel = new Model.TermLabel();
                //        modelLabel.IsDefaultForLanguage = label.IsDefaultForLanguage;
                //        modelLabel.Value = label.Value;
                //        modelLabel.Language = label.Language;

                //        modelTerm.Labels.Add(modelLabel);
                //    }
                //}

                foreach (var localProperty in term.LocalCustomProperties)
                {
                    modelTerm.LocalProperties.Add(localProperty.Key, localProperty.Value);
                }

                // Shared Properties have to be extracted just for source terms or not reused terms
                if (!term.IsReused || term.IsSourceTerm)
                {
                    foreach (var customProperty in term.CustomProperties)
                    {
                        modelTerm.Properties.Add(customProperty.Key, customProperty.Value);
                    }
                }

                if (term.TermsCount > 0)
                {
                    modelTerm.Terms.AddRange(GetTerms <Term>(context, term, defaultLanguage, isSiteCollectionTermGroup));
                }
                termsToReturn.Add(modelTerm);
            }
            if (!string.IsNullOrEmpty(customSortOrder))
            {
                int count = 1;
                foreach (var id in customSortOrder.Split(new[] { ':' }))
                {
                    var term = termsToReturn.FirstOrDefault(t => t.Id == Guid.Parse(id));
                    if (term != null)
                    {
                        term.CustomSortOrder = count;
                        count++;
                    }
                }
                termsToReturn = termsToReturn.OrderBy(t => t.CustomSortOrder).ToList();
            }


            return(termsToReturn);
        }
 /// <summary>
 /// Check if all tokens where replaced. If the field is a taxonomy field then we will check for the values of the referenced termstore and termset. 
 /// </summary>
 /// <param name="fieldXml">The xml to parse</param>
 /// <param name="parser"></param>
 /// <param name="context"></param>
 /// <returns></returns>
 protected static bool IsFieldXmlValid(string fieldXml, TokenParser parser, ClientRuntimeContext context)
 {
     var isValid = true;
     var leftOverTokens = parser.GetLeftOverTokens(fieldXml);
     if (!leftOverTokens.Any())
     {
         var fieldElement = XElement.Parse(fieldXml);
         if (fieldElement.Attribute("Type").Value == "TaxonomyFieldType")
         {
             var termStoreIdElement = fieldElement.XPathSelectElement("//ArrayOfProperty/Property[Name='SspId']/Value");
             if (termStoreIdElement != null)
             {
                 var termStoreId = Guid.Parse(termStoreIdElement.Value);
                 TaxonomySession taxSession = TaxonomySession.GetTaxonomySession(context);
                 try
                 {
                     taxSession.EnsureProperty(t => t.TermStores);
                     var store = taxSession.TermStores.GetById(termStoreId);
                     context.Load(store);
                     context.ExecuteQueryRetry();
                     if (store.ServerObjectIsNull.HasValue && !store.ServerObjectIsNull.Value)
                     {
                         var termSetIdElement = fieldElement.XPathSelectElement("//ArrayOfProperty/Property[Name='TermSetId']/Value");
                         if (termSetIdElement != null)
                         {
                             var termSetId = Guid.Parse(termSetIdElement.Value);
                             try
                             {
                                 var termSet = store.GetTermSet(termSetId);
                                 context.Load(termSet);
                                 context.ExecuteQueryRetry();
                                 isValid = termSet.ServerObjectIsNull.HasValue && !termSet.ServerObjectIsNull.Value;
                             }
                             catch (Exception)
                             {
                                 isValid = false;
                             }
                         }
                     }
                 }
                 catch (Exception)
                 {
                     isValid = false;
                 }
             }
             else
             {
                 isValid = false;
             }
         }
     }
     else
     {
         //Some tokens where not replaced
         isValid = false;
     }
     return isValid;
 }
示例#14
0
        private bool IsFieldXmlValid(string fieldXml, TokenParser parser, ClientRuntimeContext context)
        {
            var isValid        = true;
            var leftOverTokens = parser.GetLeftOverTokens(fieldXml);

            if (!leftOverTokens.Any())
            {
                var fieldElement = XElement.Parse(fieldXml);
                if (fieldElement.Attribute("Type").Value == "TaxonomyFieldType")
                {
                    var termStoreIdElement =
                        fieldElement.XPathSelectElement("//ArrayOfProperty/Property[Name='SspId']/Value");
                    if (termStoreIdElement != null)
                    {
                        var termStoreId = Guid.Parse(termStoreIdElement.Value);
                        var taxSession  = TaxonomySession.GetTaxonomySession(context);
                        try
                        {
                            taxSession.EnsureProperty(t => t.TermStores);
                            var store = taxSession.TermStores.GetById(termStoreId);
                            context.Load(store);
                            context.ExecuteQueryRetry();
                            if (store.ServerObjectIsNull.HasValue && !store.ServerObjectIsNull.Value)
                            {
                                var termSetIdElement =
                                    fieldElement.XPathSelectElement("//ArrayOfProperty/Property[Name='TermSetId']/Value");
                                if (termSetIdElement != null)
                                {
                                    var termSetId = Guid.Parse(termSetIdElement.Value);
                                    try
                                    {
                                        var termSet = store.GetTermSet(termSetId);
                                        context.Load(termSet);
                                        context.ExecuteQueryRetry();
                                        isValid = termSet.ServerObjectIsNull.HasValue &&
                                                  !termSet.ServerObjectIsNull.Value;
                                    }
                                    catch (Exception)
                                    {
                                        isValid = false;
                                    }
                                }
                            }
                        }
                        catch (Exception)
                        {
                            isValid = false;
                        }
                    }
                    else
                    {
                        isValid = false;
                    }
                }
            }
            else
            {
                //Some tokens where not replaced
                isValid = false;
            }
            return(isValid);
        }
示例#15
0
        /// <summary>
        /// Sets the search configuration at the specified object level
        /// </summary>
        /// <param name="context"></param>
        /// <param name="searchObjectLevel"></param>
        /// <param name="searchConfiguration"></param>
        private static void SetSearchConfigurationImplementation(ClientRuntimeContext context, SearchObjectLevel searchObjectLevel, string searchConfiguration)
        {
#if CLIENTSDKV15
            if (searchObjectLevel == SearchObjectLevel.Ssa)
            {
                // Reference: https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.search.portability.searchconfigurationportability_members.aspx
                throw new Exception("You cannot import customized search configuration settings to a Search service application (SSA).");
            }
#endif
            SearchConfigurationPortability searchConfig = new SearchConfigurationPortability(context);
            SearchObjectOwner owner = new SearchObjectOwner(context, searchObjectLevel);

            // Import search configuration
            searchConfig.ImportSearchConfiguration(owner, searchConfiguration);
            context.Load(searchConfig);
            context.ExecuteQueryRetry();
        }
        private static NavigationTermSet GetEditableNavigationTermSetByProviderName(
            Web web, ClientRuntimeContext context, String providerName)
        {
            // Get the current taxonomy session and update cache, just in case
            TaxonomySession taxonomySession = TaxonomySession.GetTaxonomySession(web.Context);
            taxonomySession.UpdateCache();

            context.ExecuteQueryRetry();

            // Retrieve the Navigation TermSet for the current web
            NavigationTermSet navigationTermSet = TaxonomyNavigation.GetTermSetForWeb(web.Context,
                web, providerName, true);
            context.Load(navigationTermSet);
            context.ExecuteQueryRetry();

            // Retrieve an editable TermSet for the current target navigation
            NavigationTermSet editableNavigationTermSet = navigationTermSet.GetAsEditable(taxonomySession);
            context.Load(editableNavigationTermSet);
            context.ExecuteQueryRetry();

            return (editableNavigationTermSet);
        }
        private static bool IsTenantAdminSite(ClientRuntimeContext clientContext)
        {
            try
            {
                var tenant = new Tenant(clientContext);
                clientContext.ExecuteQueryRetry();
                return true;
            }
            catch (ClientRequestException)
            {
                return false;
            }
            catch (ServerException)
            {
                return false;
            }

        }
示例#18
0
        private static List<string> ParseSubTerms(string subTermPath, Term term, bool includeId, string delimiter, ClientRuntimeContext clientContext)
        {
            var items = new List<string>();
            if (term.ServerObjectIsNull == null || term.ServerObjectIsNull == false)
            {
                clientContext.Load(term.Terms);
                clientContext.ExecuteQueryRetry();
            }

            foreach (var subTerm in term.Terms)
            {
                var termName = DenormalizeName(subTerm.Name);
                var termPath = string.Format("{0}{3}{1}{2}", subTermPath, termName, (includeId) ? string.Format(";#{0}", subTerm.Id.ToString()) : "", delimiter);

                items.Add(termPath);

                if (term.TermsCount > 0)
                {
                    items.AddRange(ParseSubTerms(termPath, subTerm, includeId, delimiter, clientContext));
                }

            }
            return items;
        }
示例#19
0
        private List <Model.Term> GetTerms <T>(ClientRuntimeContext context, TaxonomyItem parent, int defaultLanguage)
        {
            List <Model.Term> termsToReturn = new List <Model.Term>();
            TermCollection    terms         = null;
            var customSortOrder             = string.Empty;

            if (parent is TermSet)
            {
                terms           = ((TermSet)parent).Terms;
                customSortOrder = ((TermSet)parent).CustomSortOrder;
            }
            else
            {
                terms           = ((Term)parent).Terms;
                customSortOrder = ((Term)parent).CustomSortOrder;
            }
            context.Load(terms, tms => tms.IncludeWithDefaultProperties(t => t.Labels, t => t.CustomSortOrder));
            context.ExecuteQueryRetry();

            foreach (var term in terms)
            {
                var modelTerm = new Model.Term();
                modelTerm.Id   = term.Id;
                modelTerm.Name = term.Name;
                modelTerm.IsAvailableForTagging = term.IsAvailableForTagging;


                if (term.Labels.Any())
                {
                    foreach (var label in term.Labels)
                    {
                        if ((label.Language == defaultLanguage && label.Value != term.Name) || label.Language != defaultLanguage)
                        {
                            var modelLabel = new Model.TermLabel();
                            modelLabel.IsDefaultForLanguage = label.IsDefaultForLanguage;
                            modelLabel.Value    = label.Value;
                            modelLabel.Language = label.Language;

                            modelTerm.Labels.Add(modelLabel);
                        }
                    }
                }
                //else
                //{
                //    foreach (var label in term.Labels)
                //    {
                //        var modelLabel = new Model.TermLabel();
                //        modelLabel.IsDefaultForLanguage = label.IsDefaultForLanguage;
                //        modelLabel.Value = label.Value;
                //        modelLabel.Language = label.Language;

                //        modelTerm.Labels.Add(modelLabel);
                //    }
                //}

                foreach (var localProperty in term.LocalCustomProperties)
                {
                    modelTerm.LocalProperties.Add(localProperty.Key, localProperty.Value);
                }

                foreach (var customProperty in term.CustomProperties)
                {
                    modelTerm.Properties.Add(customProperty.Key, customProperty.Value);
                }
                if (term.TermsCount > 0)
                {
                    modelTerm.Terms.AddRange(GetTerms <Term>(context, term, defaultLanguage));
                }
                termsToReturn.Add(modelTerm);
            }
            if (!string.IsNullOrEmpty(customSortOrder))
            {
                int count = 1;
                foreach (var id in customSortOrder.Split(new[] { ':' }))
                {
                    var term = termsToReturn.FirstOrDefault(t => t.Id == Guid.Parse(id));
                    if (term != null)
                    {
                        term.CustomSortOrder = count;
                        count++;
                    }
                }
                termsToReturn = termsToReturn.OrderBy(t => t.CustomSortOrder).ToList();
            }


            return(termsToReturn);
        }