We were recently working on automating back-end processes on SharePoint for a client, and had chosen SharePoint PnP Timer Job Framework
as our base SDK to build our background processes to enable them to execute against all versions of SharePoint, including online and on-prem.
We initially developed against SharePoint Online and everything worked smoothly. Our TimerJob
derived jobs worked just fine and applied our logic correctly against Office 365 SharePoint. However, when our we tested the same Jobs against in-house SharePoint test environments, we observed unexpected NullReferenceException
s in our TimerJob.TimerJobRun
event handlers. On debugging, we noticed all the ClientContext
instances (namely TimerJobRunEventArgs.SiteClientContext
, TimerJobRunEventArgs.TenantClientContext
and TimerJobRunEventArgs.WebClientContext
) were coming across as null in TimerJob.TimerJobRun
handler.
As we debugged into reasons for the same, no noticeable red flag cropped up and all our code was written as it should for a TimerJob
. We tried with bare skeleton TimeJobs against the in-house SharePoint test environments, and they produced the same errors, ClientContext
instances were null in TimerJobRun
handler.
Then we noticed the SharePointVersion
property on the TimerJob
instance. Its description says:
1 2 |
Gets or sets the SharePoint version. Default value is detected based on the laoded CSOM assembly version, but can be overriden in case you want to for example use v16 assemblies in v15 (on-premises) |
Well we were executing against SharePoint 2013, and with NuGet packages being the de-facto standard for referencing SDKs, we certainly were on the latest versions of SharePointPnPCoreOnline and Microsoft.SharePointOnline.CSOM nuget packages. The CSOM package version we were using was 16.1.7115.1200, which meant we were essentially using CSOM version 16 with SharePoint version 15.
The below table summaries various SharePoint public and internal version numbers:
Public Version | Internal Version |
---|---|
SharePoint 2007 | 13 |
SharePoint 2010 | 14 |
SharePoint 2013 | 15 |
SharePoint 2016 | 16 |
SharePoint Online | 16 (as of writing this) |
The SharePoint Online / Office 365 version is usually the latest stable SharePoint version, and can change with newer SharePoint releases.
Anyways coming back, all we needed to fix the Object reference errors was to set SharePointVersion
to 15 explicitly in code, and that again started producing the ClientContext
instances correctly in TimerJobRun
handler. We figured it was probably a good idea to always explicitly specify SharePointVersion
on TimerJob
instances to make the code future proof as nuget packages can be upgraded anytime. Additionally in our case, because the destination SharePoint site urls were being picked dynamically at run-time from configuration, we added an additional property to specify the SharePoint version for those urls in the configuration itself. You can choose to either hard-code or use another appropriate mechanism to figure out the correct SharePoint version to set on your job instances.