0

We have to get site hierarchy (rootweb – all level sub sites) and show it in a tree view using client object model (Provider hosted App)

We have implemented this by parsing through each site/web and making recursive calls which is affecting the performance. Reference - http://www.morgantechspace.com/2016/02/get-all-sites-and-subsites-in-sharepoint-online-csom.html

Is there any other way to get all the site and subsites(All levels) with minimal time and in a single call.

zainul
  • 135
  • 12
  • Which version of SharePoint you are using? (2010, 2013, 2016, Online) – moe Jul 04 '17 at 06:29
  • Sorry forgot to mention sharepoint online – zainul Jul 04 '17 at 06:30
  • See: https://sharepoint.stackexchange.com/questions/101176/powershell-to-list-all-sites-and-subsites-in-sharepoint-online – moe Jul 04 '17 at 06:33
  • https://sharepoint.stackexchange.com/questions/218442/get-the-all-sub-sites-from-a-site-collection-along-with-site-hierarchy-using-cso – TARUN Jul 04 '17 at 06:33
  • Powershell approach is always optimal but you can not use it because your are working in provider hosted app. In all approaches, you have to loop through all the webs/subwebs. So the only way you can optimize your query is by loading only required details viz. Title, Url only – DvG Jul 04 '17 at 06:39
  • @moe I may not be able to use powershell. C# approach is required – zainul Jul 04 '17 at 06:44
  • @DvG there is no other way to decrease the looping which may increase performance? – zainul Jul 04 '17 at 06:45
  • As I explained, you can only choose selective properties to load (Title,Url, etc ) and then execute the query to increase the performance. – DvG Jul 04 '17 at 06:49
  • Is it possible to run the powershell script from my app and get the results back in it so that I can use it to populate the tree view as the issue is not yet resolved – zainul Jul 05 '17 at 10:39

2 Answers2

1

Regarding

Is there any other way to get all the site and subsites(All levels) with minimal time and in a single call.

search based approach could be more suitable in this regard (at least from performance perspective) as demonstrated below:

    public static List<WebInfo> GetAllWebs(ClientContext ctx)
    {
        var keywordQuery = new KeywordQuery(ctx)
        {
            QueryText = "contentclass:\"STS_Web\"",
            RowLimit = 500,
            StartRow = 0
        };
        keywordQuery.SelectProperties.Add("Title");
        keywordQuery.SelectProperties.Add("SPWebUrl");
        keywordQuery.SelectProperties.Add("Description");


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

        var resultTable = results.Value.FirstOrDefault();
        if (resultTable == null)
            return new List<WebInfo>();
        return resultTable.ResultRows.Select(row => new WebInfo()
            {
                Title = (string) row["Title"],
                Description = (string) row["Description"],
                AbsUrl = (string) row["SPWebUrl"]
            }).ToList();
    }

where

class WebInfo
{
    public string Title { get; set; }
    public string AbsUrl { get; set; }
    public string Description { get; set; }
}

Note: contentclass:"STS_Web" query targets web in search results

References

Search API usage in the SharePoint add-in model

SharePoint Power Searching Using ContentClass

Vadim Gremyachev
  • 42,498
  • 3
  • 86
  • 167
0

please check this post Get the all sub sites from a site collection along with site hierarchy using CSOM

 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;
            }
TARUN
  • 2,856
  • 20
  • 45
  • 1
    This makes no difference as Looping is still happening, and the similar approach is already been followed by him – DvG Jul 04 '17 at 06:39
  • Yeah @TARUN... I am also thinking the same... Will it help as there is still looping in there.. – zainul Jul 04 '17 at 06:42