Timer Jobs werden in SharePoint onPremise regelmäßig für wiederkehrenden Aktivitäten eingesetzt. Ein TimerJob muss als Farm-Solution programmiert werden. Und hier stößt man bei Office365 an Grenzen. Eine Farmsolution ist nicht möglich.
Um TimerJobs aber auch unter Office365 zu nutzen, muss auf die Webaufträge einer Azure-WebSite ausgewichen werden. Ein Webauftrag ist nichts anderes als eine Konsolen -Anwendung die über das Azure-Portal ausgeführt wird. Dies kann auch zeitgesteuert erfolgen. Wenn nun diese Konsolen -Anwendung auf SharePoint zugreifen kann, ist der Timer Job auch schon wieder fertig!
Die Konsolen Anwendung als SharePoint App
Jede Anwendung kann als SharePoint App agieren, wenn sie in SharePoint registriert wurde. Damit wird ein Zugriff auf SharePoint ermöglicht. Um eine App zu registrieren, ist es notwendig einen App-Principal zu erstellen. Dieser ist der App-SharePoint User dem Berechtigungen erteilt werden. Im Layouts Verzeichnis kann die Seite “_layouts/AppRegNew.aspx” aufgerufen werden um die App zu registrieren.
Mit den beiden “Generieren”-Schaltflächen können zufällige Werte für Client-ID und “Geheimer Clientschlüssel” erstellt werden. Den Clientschlüssel habe ich für den Screenshot abgeändert
Als App-Domäne verwendet ich “localhost”. Nach dem Click auf “Erstellen” erhält man eine Zusammenfassung der erstellten App. Es ist ratsam, den Inhalt in die Zwischenablage zu kopieren, und von dort in den Code der Anwendung in ein Kommentar schreiben.
Die App ist zwar nun registriert, allerdings hat der App-User noch keine Rechte. Daher ist es notwendig die Permissions zu setzen. In einem App-Projekt geschieht dies in der Manifest-Datei. Bei unserem Timerjob setzen wir die App-Permission-Requests über die Weboberfläche.
Unter _layouts/AppInv.aspx können wir eine registrierte App aufrufen. Allerdings benötigen wir die App Id. Kein Problem, wir haben sie ja vorher in die Zwischenablage kopiert. Allerdings sprach die Registrierungsseite von einer “Client-ID” (Ob hier zwei unterschiedliche Entwickler daran gearbeitet haben )
Mit einem Klick auf “Nachschlagen” kann die App aufgerufen werden und die “Berechtigungsanforderungs-XML” gesetzt werden.
Der XML Code entspricht dem, der auch bei einem App-Projekt erstellt wird. Um das Erstellen zu vereinfachen kann man auch einfach ein App-Projekt beginnen. Danach die Permissions mit dem Editor setzen und so den XML Code kopieren. Zu beachten ist, dass die App danach mit App-Ony Rechten arbeiten soll. (Siehe meinen Blogzu App-Only-Calls)
In meinem Beispiel setze ich weitreichende Rechte:
1: <AppPermissionRequests AllowAppOnlyPolicy="true">
2: <AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="Manage" />
3: </AppPermissionRequests>
Nach dem Klick auf “Erstellen” kommt die Vertrauens-Frage:
Jeder darf für sich entscheiden ob er seinem Code vertraut
Der Programmcode der Anwendung
Nachdem nun die App registriert wurde, muss die Anwendung selbst erstellt werden. Wir starten mit einem simplem Konsolen-Projekt. Da wir aber mit AccessToken udgl hantieren müssen, ist es ratsam über NuGet das Package “AppForSharePointWebToolkit” zu laden. Dieses bringt die Klassen für SharePointContext und den TokenHelper in unser Projekt. Außerdem werden die Dlls-für SharePoint CSOM registriert.
Das ClientSecret und der ClientID müssen in der App.config Datei der Anwendung hinterlegt werden. Die App-Config sollte dann in etwa so aussehen (ClientSecret habe ich wieder verändert ).
<configuration>
<appSettings>
<add key="ClientId" value="c33f72da-0344-4c02-9028-dc720bba11e0"/>
<add key="ClientSecret" value="MRuC...........="/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Im Wesentlichen enthält die Main-Funktion nur Aufrufe ins CSOM. Der dafür notwendige ClientContext wird über die Methode “GetClientContextWithAccessToken” der Klasse “Tokenhelper” erstellt.
1: static void Main(string[] args)
2: {
3: string url = "https://......./sites/Dev";
4: Uri uri = new Uri(url);
5: string realm = TokenHelper.GetRealmFromTargetUrl(uri);
6: string accessToken = TokenHelper.GetAppOnlyAccessToken(
7: TokenHelper.SharePointPrincipal,
8: uri.Authority, realm).AccessToken;
9:
10: using (var ctx = TokenHelper.GetClientContextWithAccessToken(url, accessToken))
11: {
12: List liste = ctx.Web.Lists.GetByTitle("TestListe");
13: var neuesItem = liste.AddItem(new ListItemCreationInformation());
14: neuesItem["Title"] = string.Format("Last Run at {0}", DateTime.Now.ToShortTimeString());
15: neuesItem.Update();
16: ctx.ExecuteQuery();
17: }
18: }
Nachdem die Anwendung fertig ist, muss diese nun noch auf Azure deployed werden.
Job-Einrichtung unter Azure
Ein Webauftrag unter Azure wird als .ZIP-Datei in Azure hochgeladen. In der Zip-Datei muss ein EXE liegen. Also kann unsere Konsolen-Anwendung kompiliert werden, und das Debug- oder Release-Verzeichnis in eine ZIP Datei gepackt werden.
In der Verwaltungsseite einer Azure-Website ist die Seite “Webjobs” zu finden.
Hiermit kann ein neuer Job angelegt werden. Auf Seite 1 muss ein Name für den Job angegeben werden. Weiters muss die Zip Datei ausgewählt werden und es muss definiert werden, ob der Job zeitgesteuert (Run on a schedule) gestartet wird. Im Fall einer Zeitsteuerung muss auch die Region ausgewählt werden.
Auf Seite 2 wird noch das Wiederholungsintervall sowie Start- und End-Zeitpunkt definiert:
Danach wird die ZIP Datei hochgeladen und der TimerJob ist fertig konfiguriert!