The way to create Timer Jobs in SharePoint Online is different from how they were created in the farm applications in the OnPremise versions.

It is not possible to create solutions using the server object model, nor to deploy farm solutions that interact with the central administration. This is why we need to create a solution that uses the client object model (CSOM) to simulate the behavior we had with traditional Timer Jobs. These solutions are programmed and implemented in an external scenario to SharePoint, so it is not responsible for its execution.

There are several possibilities for the creation of remote Jobs in SharePoint Online:

  • One of them, would be the Azure WebJobs.
  • The other would be the creation of a console application that runs through a scheduled server task in order to avoid the need to have an Azure environment enabled. This possibility will be in which we will focus on this post.

Previous steps

To be able to interact with SharePoint Online from a console application we will use the NuGet AppForSharePointOnlineWebToolkit package.

Once the package is installed, we see that all the necessary Dlls and classes have been added in order to function correctly.

Next, we have to configure our console application so that the connection is correct. To do this, we will edit the App.config file and add the corresponding entries to the URL of the site, the name of the list with which we are going to interact, the customer ID and the client’s secret:

<add key=“SiteUrl“ value=“<URL del Site>“/>

<add key=“ClientId“ value=“db22d478-4a9b-461c-8240-616dd1cfbbe0“/>

<add key=“ClientSecret“ value=“KoowtUu3tpdwSYo0WCczGTnAVyZpkIHOPcxd24KQefM=“/>

 

To generate the client ID and the correct client secret for our application, we access the page:

https:///_layouts/15/appregnew.aspx

Click on “Generate” to obtain the customer ID and later on “Generate” for the client’s secret password.

Those data generated are those that we will include in the App.config of the console application.The next step will be the configuration of the permissions of our console application to be able to interact with SharePoint Online.  We will configure these permissions in the URL:

https:///_layouts/15/appinv.aspx

In this application page, we will add the client ID generated previously, press “Search” to obtain the information of our application and to configure the correct permissions.

Once the permisions hace beeen added, the confirmation window of our application appears, indicating which permits will be granted.

 

Job Programming

We already have our console application configured correctly to interact with SharePoint Online, later we will program the actions that our Job Timer will perform.In this example, you are going to check if an item has been created in a list in the last seven days. If it has been created, an email is sent to the administrator of the site.

static void Main(string[] args)

{

Uri siteUrl = new Uri(ConfigurationManager.AppSettings[“SiteUrl“]);

 

//Get the realm for the URL

string realm = TokenHelper.GetRealmFromTargetUrl(siteUrl);

 

//Get the access token for the URL

string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUrl.Authority, realm).AccessToken;

 

//Get client context with access token

using (var ctx =

TokenHelper.GetClientContextWithAccessToken(siteUrl.ToString(), accessToken))

{

DateTime startDate = DateTime.Now.Date;

DateTime endDate = DateTime.Now.AddDays(-7);

 

 

if (ListExists(ctx.Web, “ParteActividad“))

{

List listParteActividad = ctx.Web.Lists.GetByTitle(“ParteActividad“);

 

for (DateTime day = startDate; day >= endDate; day = day.AddDays(-1))

{

CamlQuery queryPersonaParteActividad = new CamlQuery();

queryPersonaParteActividad.ViewXml = “<View Scope=\”RecursiveAll\”><Query><Where><Eq><FieldRef Name=’Created‘/><ValueIncludeTimeValue=’False’ Type=’DateTime‘>” + day.ToString(“yyyy-MM-ddTHH:mm:ssZ“) + “</Value></Eq></Where></Query></View>”;

ListItemCollection collListItemPersonasParte = listParteActividad.GetItems(queryPersonaParteActividad);

ctx.Load(collListItemPersonasParte);

ctx.ExecuteQuery();

 

if (collListItemPersonasParte.Count > 0)

{

string htmlBodyInit = “Se ha creado un elemento el día “ + day.ToShortDateString();

string htmlSubject = “Comprobación elemento”;

 

SendEmail(ctx, “administrador@bravent.net”, htmlSubject, htmlBodyInit);

break;

}

 

}

}

}

}

 

public static void SendEmail(ClientContext ctx, string email, string htmlSubject, string htmlBody)

{

var emailp = new EmailProperties();

emailp.To = new List<string> { email };

emailp.Body = htmlBody;

emailp.Subject = htmlSubject;

Utility.SendEmail(ctx, emailp);

ctx.ExecuteQuery();

}

 

public static bool ListExists(Web web, string listTitle)

{

ListCollection lists = web.Lists;

IEnumerable<List> results = web.Context.LoadQuery<List>(lists.Where(list => list.Title == listTitle));

web.Context.ExecuteQuery();

List existingList = results.FirstOrDefault();

 

if (existingList != null)

{

return true;

}

 

emailp.Body = htmlBody;

emailp.Subject = htmlSubject;

Utility.SendEmail(ctx, emailp);

ctx.ExecuteQuery();

}

 

public static bool ListExists(Web web, string listTitle)

{

ListCollection lists = web.Lists;

IEnumerable<List> results = web.Context.LoadQuery<List>(lists.Where(list => list.Title == listTitle));

web.Context.ExecuteQuery();

List existingList = results.FirstOrDefault();

 

if (existingList != null)

{

return true;

}

 

return false;

}

With the console application created, we just have to host the application on the server where it will run and configure the scheduled task to run when we need it.

 

Written by: Brintias Team