I have the following c# csom (client side object model) code to get sub sites and nested sub sites of a site collection. This code runs perfectly for most site collections, but it not working for a single site collection which has a lot of sub-sites and nested sub sites.
private static List<Web> RecursiveSites(ClientContext siteCtx, Web site) { var allSites = new List<Web>(); allSites.Add(site); if (site.Webs.Count > 0) { siteCtx.Load(site.Webs, w => w.Include(a => a.Title, a => a.Url, a => a.Webs)); siteCtx.ExecuteQuery(); foreach (Web web in site.Webs) { allSites.AddRange(RecursiveSites(siteCtx, web)); } } return allSites; }
I am receiving below error:
Microsoft.SharePoint.Client.ServerException: The request uses too many resources
After googled sometime, I’ve found an article in MSDN that explains the request limits of the csom. You can refer this under the heading Request limits of the CSOM at bottom of this article https://msdn.microsoft.com/en-us/library/office/jj163082.aspx
The CSOM in Project Server 2013 is built on the CSOM implementation in SharePoint Server 2013 and inherits the limits for the maximum size of a request. SharePoint has a 2 MB limit for an operations request, and a 50 MB limit for the size of a submitted binary object. The request size is limited to protect the server from excessively long queues of operations and from processing delays for large binary objects.
Solution
In SharePoint On-Premise, you can resolve this issue by setting the maxObjectPaths in WebApplication to a higher value using Powershell:
#Get the value: Get-SPWebApplication | %{$_.ClientCallableSettings} #Set the Value: Add-PSSnapin Microsoft.SharePoint.PowerShell $webApp = Get-SPWebApplication "http://myspwebapp/" $webApp.ClientCallableSettings.MaxObjectPaths = 2500 $webApp.Update()
But in SharePoint Online, there is no way to access the ClientCallableSettings.MaxObjectPaths property. so we need to re-write the code to reduce request size. I have changed the code in a way to send request for one site instead of all sub sites at the same time, now the code execute the siteCtx.ExecuteQuery() inside the loop instead of outside the loop.
private static List<Web> RecursiveSites(ClientContext siteCtx, Web site) { var allSites = new List<Web>(); allSites.Add(site); if (site.Webs.Count > 0) { foreach (Web web in site.Webs) { siteCtx.Load(web , w => w.Title, w => w.Url, w => w.Webs); siteCtx.ExecuteQuery(); allSites.AddRange(RecursiveSites(siteCtx, web)); } } return allSites; }