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 NullReferenceExceptions 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:

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.

Share this: