Eine SPFx-Solution kann in SharePoint Online standardmäßig allen Site Collections zur Verfügung gestellt werden. Dies wird erreicht, indem im Projekt in der Datei /config/package-solution.json
im „solution“-Objekt das Property „skipFeatureDeployment“ auf true gesetzt wird.
1{
2 "$schema": "https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json",
3 "solution": {
4 "name": "helloworld-client-side-solution",
5 "id": "517544a9-fa90-4b2e-848e-c15392b19eb0",
6 "version": "1.0.0.0",
7 "includeClientSideAssets": true,
8 "skipFeatureDeployment": true
9 },
10 "paths": {
11 "zippedPackage": "solution/helloworld.sppkg"
12 }
13}
Beim Hochladen der Solution vom Administrator wird diese dann automatisch einmalig für alle bereitgestellt. Die Solution taucht dann nicht im App-Bereich der Site Collections auf, ist aber entsprechend verfügbar (z. B. können die Webparts direkt verwendet werden). In jeder neu angelegten Site Collection sind die Inhalte der Solution direkt verfügbar.
Bei SharePoint 2016 On-Premise erzeugt diese Vorgehensweise jedoch einen Fehler beim Bereitstellen der Solution. Dies liegt daran, dass in SharePoint 2016 On-Premise bis dato nur SPFx 1.1 unterstützt wird. Dieses Property ist im Schema (https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json) zwar bereits bekannt und erzeugt keinen Kompilierungsfehler, darf aber nicht auf true gesetzt werden. Laut Microsoft wird dies erst ab Version 1.4 unterstützt.
Hier muss also ein anderer Weg beschritten werden, um die Solution zu verteilen.
Laut Microsoft könnte dies z. B. durch die Ausführung eines separaten Skriptes nach dem Anlegen einer neuen Site Collection realisiert werden. Das Grundprinzip beruht dabei auf dem bereits bekannten Hochladen von SharePoint AddIns. Dazu muss das entsprechende SPFx-Package aus dem App-Katalog geladen und dann auf der neuen Site Collection installiert werden.
1// AppCatalog
2ClientContext appContext = new ClientContext(appCatalogUrl);
3appContext.Credentials = credentials;
4
5Web web = appContext.Web;
6ListCollection lists = web.Lists;
7appContext.Load(web);
8appContext.Load(lists);
9appContext.ExecuteQuery();
10
11// Deutsch oder Englisch
12List cataloglist = lists.FirstOrDefault(c =>
13 c.Title == "Apps for SharePoint" || c.Title == "Apps für SharePoint");
14appContext.Load(cataloglist);
15
16string productID = "517544a9-fa90-4b2e-848e-c15392b19eb0";
17CamlQuery query = new CamlQuery();
18query.ViewXml = "<View><Query><Where><Eq>
19 <FieldRef Name='AppProductID'/><Value Type='Text'>" + productID + "</Value>
20 </Eq></Where></Query></View>";
21
22ListItemCollection listItems = cataloglist.GetItems(query);
23appContext.Load(listItems, c => c.Include(item => item, item => item["AppProductID"]));
24appContext.ExecuteQuery();
25
26ListItem item = listItems.First();
27appContext.Load(item);
28appContext.ExecuteQuery();
29
30File file = item.File;
31appContext.Load(file);
32appContext.ExecuteQuery();
33
34ClientResult<System.IO.Stream> data = file.OpenBinaryStream();
35appContext.ExecuteQuery();
36
37// SiteCollection
38ClientContext siteContext = new ClientContext(SiteCollectionUrl);
39Web web1 = siteContext.Web;
40siteContext.Load(web1);
41siteContext.ExecuteQuery();
42
43AppInstance appInstance = web1.LoadAndInstallApp(data.Value);
44siteContext.Load(appInstance);
45siteContext.ExecuteQuery();
Führt man dieses Skript aus, kommt es zu einer weiteren Fehlermeldung:
SideLoading ist nicht aktiviert!
Damit dies erfolgreich ist, muss das Feature „SideLoading“ ebenfalls kurzfristig aktiviert werden, bevor LoadAndInstallApp()
aufgerufen wird.
1FeatureCollection myFeatures = siteContext.Site.Features;
2context.Load(myFeatures);
3context.ExecuteQuery();
4Guid myFeatureId = new Guid("AE3A1339-61F5-4f8f-81A7-ABD2DA956A7D");
5
6// aktivieren
7myFeatures.Add(myFeatureId, true, FeatureDefinitionScope.None);
8context.ExecuteQuery();
9
10// ... LoadAndInstallApp() ausführen ...
11
12// deaktivieren
13myFeatures.Remove(myFeatureId, true);
14context.ExecuteQuery();
Führt man dieses erweiterte Skript aus, kommt es zu einer weiteren Fehlermeldung:
Value cannot be null. Parameter name: xeAppPermissionRequest
Dies liegt daran, dass in der App.manifest des SPFx-Packages (helloworld.sppkg) einige Properties fehlen. Für ein automatisches Deployment sind diese auch nicht notwendig, da wir hier aber so tun, als handele es sich um ein SharePoint Add-in, müssen diese Werte ergänzt werden.
1<?xml version="1.0" encoding="utf-8"?>
2<App xmlns="http://schemas.microsoft.com/sharepoint/2012/app/manifest"
3 Name="helloworld-client-side-solution"
4 ProductID="517544a9-fa90-4b2e-848e-c15392b19eb0" Version="1.0.0.0"
5 SharePointMinVersion="16.0.0.0" IsClientSideSolution="true">
6 <Properties>
7 <Title>helloworld-client-side-solution</Title>
8 <StartPage>/</StartPage>
9 </Properties>
10 <AppPrincipal>
11 <Internal></Internal>
12 </AppPrincipal>
13</App>
Dazu muss das erstellte Package in ein ZIP umbenannt werden. Dann kann dieser Ordner geöffnet werden und im Root-Verzeichnis liegt die App.manifest-Datei. In dieser Datei müssen die entsprechenden Properties ergänzt werden. Danach kann der ZIP-Ordner geschlossen und das Package wieder mit dem Original-Dateinamen versehen werden.
Damit funktioniert die Bereitstellung für die Site Collection.