January 3, 2017

Solving SharePoint error: The request uses too many resources



Scenario:
I was deleting a group of items in a SharePoint list. After selecting the items, I clicked 'Delete Item' from the ribbon but nothing happened! the items were not deleted, the page didn't refresh and not even single item moved to the site recycle bin. The UI didn't show any error message.

Below is excerpt from ULS logs:
 Name=Request (POST:{SiteUrl}/_vti_bin/client.svc/ProcessQuery)

 Begin CSOM Request ManagedThreadId=8, NativeThreadId=20404
 Original error: Microsoft.SharePoint.Client.ClientServiceException: The request uses too many resources.     at Microsoft.SharePoint.Client.ClientMethodsProcessor.Process()
RequestMessage: <Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="15.0.0.0" ApplicationName="Javascript Library"><Actions>................... 

The RequestMessage part is very long to put here.


Digging for answers:
This error is from server side. Since I am doing item deletion from default OOB list view (which uses client-side object model), I decided to work on the Client.svc (from 15 hive: \ISAPI\Client.svc):

<%@ServiceHost language="c#" Service="Microsoft.SharePoint.Client.ClientRequestService, Microsoft.SharePoint.Client.ServerRuntime, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

So I looked for the logic inthe assembly Microsoft.SharePoint.Client.ServerRuntime.dll.
Inside Microsoft.SharePoint.Client.ClientMethodsProcessor.Process() method:

int maxObjectPaths = this.m_serviceSurrogate.ClientCallableSettings.MaxObjectPaths;
int num = 0;
if (maxObjectPaths > 0 && num > maxObjectPaths)
{
       throw new ClientServiceException(Resources.GetString("ClientRequestExceedMaxResources"));
}

At run time, if number of total selected items are larger than 'ClientCallableSettings.MaxObjectPaths' then it will throw the error message internally, and the client side will just do nothing.

From PowerShell, I checked current value of 'MaxObjectPaths' property for target web application:
$WebApp.ClientCallableSettings.MaxObjectPaths
The returned value was 256 (which is the default value).

Okay, the immediate conclusion is that I can delete up to 256 (to be less than or equal to current value of MaxObjectPaths).. Let's test that:

Test: set MaxObjectPaths to 2 then try to delete 3 items only.
$WebApp.ClientCallableSettings.MaxObjectPaths = 2
$WebApp.Update()
Result: It failed with same error "The request uses too many resources" in ULS.

To understand why this happened, I needed to go back and recheck the error detail in more depth from ULS logs. 


Process Request Format & Analysis:
After careful inspection, I put the below format for RequestMessage property sent by client to Server to process:

<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" SchemaVersion="15.0.0.0" LibraryVersion="15.0.0.0" ApplicationName="Javascript Library">

<Actions>
<ExceptionHandlingScopeSimple Id="..">
<ObjectPath Id="3" ObjectPathId="2" />
<ObjectPath Id="5" ObjectPathId="4" />
<ObjectPath Id="7" ObjectPathId="6" />
<ObjectPath Id="9" ObjectPathId="8" />
<ObjectPath Id="11" ObjectPathId="10" />
<Method Name="MethodName" Id="12" ObjectPathId="10" />
</ExceptionHandlingScopeSimple>
</Actions>

<ObjectPaths>
<StaticProperty Id="2" TypeId="{TypeID}" Name="Current" />
<Property Id="4" ParentId="2" Name="Web" />
<Property Id="6" ParentId="4" Name="Lists" />
<Method Id="8" ParentId="6" Name="GetById"><Parameters><Parameter Type="String">{ListID}</Parameter></Parameters></Method>
<Method Id="10" ParentId="8" Name="GetItemById"><Parameters><Parameter Type="Number">ItemID</Parameter></Parameters></Method>
</ObjectPaths>

</Request>
 

The RequestMessage contains the required details of the operation that is requested by Client to be performed by Server.
It starts with 'ObjectPath' nodes under <ObjectPaths>. The highlighted parts in Yellow indicates the required SharePoint IDs. The first 4 nodes (in light Grey) are essential to know where target items are located. It starts with Item type, then web, then list. The actual items starts at the 5th node, they are represented by <Method> that sets the calling method 'GetById' with that item ID.
In other words there will be always 4 initial nodes followed by method nodes equal to number of items.
If everything works fine, then it will process the <Actions> section, where for every item (referred to by ObjectPathId parameter) it is required to run a specific method (MethodName for example: 'Recycle').


Conclusion:
Based on my tests & format analysis above, client batch operation can support a number of items equal to (ClitentCallableSettings.MaxObjectPaths - 4)
Example: If ClitentCallableSettings.MaxObjectPaths = 256 then we can delete up to 252


Solution:
1. Use PowerShell to check existing value of MaxObjectPaths property for target web    application:
     $WebApp.ClientCallableSettings.MaxObjectPaths


2. If total number of items (to be deleted or updated) > (MaxObjectPaths - 4) then set a larger value for MaxObjectPaths:
    $WebApp.ClientCallableSettings.MaxObjectPaths = $TotalItemsCount + $requiredDiff
    $WebApp.Update()

Example: to be able to delete 256 items in 1 batch, then set MaxObjectPaths to 260


Note:

·         Be aware for performance impact before setting MaxObjectPaths value.

 

No comments:

Post a Comment