6

I had site collection is SharePoint online with the below hierarchy.

enter image description here

The value in the bracket is the site hierarchy (added for understanding only). I want to get all the subsite details along with Hierarchy level. I am able to get all the subsite details with the below code.

using (var clientContext = new ClientContext(destinationSiteUrl))
                {
                    clientContext.Credentials = new SharePointOnlineCredentials(UserName, secure);
                    DataTable dtsubsites = new DataTable();
                    Web oWebsite = clientContext.Web;
                    clientContext.Load(oWebsite.Webs);
                    clientContext.ExecuteQuery();
                    Dictionary<int, Web> mydict = new Dictionary<int, Web>();
                    var allWebs = new List<Web>();
                    var objallWebs = LoadAllWebs(clientContext.Site.RootWeb, allWebs);
                    foreach (var web in objallWebs)
                    {
                        ddlsubsites.Items.Add(web.Url.ToString());
                    }                    
                }

 public  List<Web> LoadAllWebs(Web web, List<Web> allWebs)
        {           
            var ctx = web.Context;
            ctx.Load(web);
            ctx.Load(web.Webs);
            ctx.ExecuteQuery();
            allWebs.Add(web);         
            foreach (var subWeb in web.Webs)
            {
                LoadAllWebs(subWeb, allWebs);               
            }           
            return allWebs;
        }

How to get the hierarchy level of each site? Any Suggestions, please.

3

Change allWebs into a list containing level+Web

Add a int level parameter to LoadAllWebs

In the first call pass 0 as level.
In the recursive call inside LoadAllWebs pass level+1

  • Thanks for the reply.. can you please explain a little more. means to use List<Tuple<T1, T2>> list or list<class> – TARUN Jun 16 '17 at 13:43
4

Here's a approach based of the Search which should be way faster and more ressource friendly.

It currently only groups subwebs after rootwebs, but could easily modified to also group the subwebs.

Result:

[ 22.04.2016 11:41:02 ] Infrastructure found by Search:
https://rootSPDomain.de
       https://rootSPDomain.de
       https://rootSPDomain.de/SubWeb1
       https://rootSPDomain.de/SubWeb1/SubWeb1
       https://rootSPDomain.de/SubWeb2
       https://rootSPDomain.de/SubWeb2/SubWeb1

Code:

    private static Dictionary<string, List<string>> GetAllWebsBySearch(ref int errorCount)
    {
        var webUrls = new Dictionary<string, List<string>>();

        try
        {
            using (var ctx = new ClientContext(Settings.Default.SearchCenterUrl))
            {
                var sites = SearchWebs(ctx, Settings.Default.SearchQuery + " contentclass:STS_Site");
                var webs = SearchWebs(ctx, Settings.Default.SearchQuery + " contentclass:STS_Web");

                if (sites.Count == 0)
                    Log.ThrowCritical(string.Format("No sites found for searchstring '{0}'",
                        Settings.Default.SearchQuery));

                foreach (var site in sites)
                    webUrls.Add(site, new List<string> { site });

                foreach (var web in webs)
                {
                    var parentSite = sites.Where(site => web.StartsWith(site)).OrderByDescending(s => s.Length).FirstOrDefault();
                    if (parentSite != null)
                    {
                        if (!webUrls[parentSite].Contains(web))
                            webUrls[parentSite].Add(web);
                    }
                    else
                    {
                        Log.Error(string.Format("Could not find site for web {0}", web));
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Log.Error(string.Format("Error while searching webs at {0}",
                Settings.Default.SearchCenterUrl));
            Log.Error(string.Format(CultureInfo.InvariantCulture, "{0}", ex.Message));
            errorCount++;
        }
        return webUrls;
    }

    private static List<string> SearchWebs(ClientContext ctx, string query)
    {
        var returnValue = new List<string>();
        var rowLimit = 500;
        var startRow = 0;
        var allResultsFetched = false;
        var fieldPath = "Path";

        while (!allResultsFetched)
        {
            Log.Verbose(string.Format(CultureInfo.InvariantCulture, "Search with query - {0}", query));
            var keywordQuery = new KeywordQuery(ctx)
            {
                QueryText = query,
                RowLimit = rowLimit
            };
            keywordQuery.SelectProperties.Clear();
            keywordQuery.SelectProperties.Add(fieldPath);
            keywordQuery.StartRow = startRow;
            keywordQuery.TrimDuplicates = false;

            var searchExecutor = new SearchExecutor(ctx);
            var results = searchExecutor.ExecuteQuery(keywordQuery);
            ctx.ExecuteQuery();

            foreach (var resultRow in results.Value[0].ResultRows)
            {
                var path = resultRow.Keys.Contains(fieldPath) && (resultRow[fieldPath] != null)
                    ? resultRow[fieldPath].ToString()
                    : string.Empty;
                returnValue.Add(path);
            }

            if (results.Value[0].RowCount < rowLimit)
                allResultsFetched = true;
            else
                startRow = startRow + rowLimit + 1;
        }
        return returnValue;
    }

    private static void LogInfrastructure(Dictionary<string, List<string>> webInfrastructure)
    {
        var message = "Infrastructure found by Search:\n";
        foreach (var site in webInfrastructure)
        {
            message += site.Key + "\n";
            foreach (var web in site.Value)
                message += "\t" + web + "\n";
            message += "\n";
        }

        Log.Message(message);
    }

Usage:

//get all web urls from the search
var webInfrastructure = GetAllWebsBySearch(ref errorCount);
LogInfrastructure(webInfrastructure);
2

Per Jakobsen solution worked for me. Please find the below code for reference

     using (var clientContext = new ClientContext(destinationSiteUrl))
       {
         clientContext.Credentials = new SharePointOnlineCredentials(UserName, secure);
         DataTable dtsubsites = new DataTable();
         Web oWebsite = clientContext.Web;
         clientContext.Load(oWebsite.Webs);
         clientContext.ExecuteQuery();
         var listclass = new List<webdetails>();
         var allWebs = new List<Web>();
         var objallWebs = LoadAllWebs(clientContext.Site.RootWeb, listclass, 0);
         GridView1.DataSource = objallWebs.ToList();
         GridView1.DataBind();
       }

 public class webdetails
  {
     public string csomweb { get; set; }
     public Int32 webhirarchy { get; set; }
  }

 public List<webdetails> LoadAllWebs(Web web, List<webdetails> allWebs,int level)
        {
            var ctx = web.Context;
            ctx.Load(web);
            ctx.Load(web.Webs);
            ctx.ExecuteQuery();
            // allWebs.Add(web);
            allWebs.Add(new webdetails { csomweb = web.Title, webhirarchy = level });
            foreach (var subWeb in web.Webs)
            {
                LoadAllWebs(subWeb, allWebs, level+1);
            }
            return allWebs;
        }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.