SPFx-Solution

SPFx-Solution – automatische Verteilung auf SP2016 Onpremise 

Tibor Csizmadia | Geschäftsführer DEVWARE GmbH | 29.04.2020

Eine SPFx-Solution kann in SharePoint Online standardmäßig allen SiteCollections 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.

{ 
  "$schema": "https://dev.office.com/json-schemas/spfx-build/package-solution.schema.json", 
  "solution": { 
    "name": "helloworld-client-side-solution", 
    "id": "517544a9-fa90-4b2e-848e-c15392b19eb0", 
    "version": "1.0.0.0", 
    "includeClientSideAssets": true, 
    "skipFeatureDeployment": true 
  }, 
  "paths": { 
    "zippedPackage": "solution/helloworld.sppkg" 
  } 
}

 

Beim Hochladen der Solution vom Administrator wird diese dann automatisch einmalig für alle bereitgestellt. Die Solution taucht dann nicht im App-Bereich der SiteCollections auf – ist aber entsprechend verfügbar (z.B. können die Webparts direkt verwendet werden). In jeder neu angelegten SiteCollection sind die Inhalte der Solution direkt verfügbar. 

Bei SharePoint 2016 Onpremise erzeugt diese Vorgehensweise jedoch einen Fehler beim Bereitstellen der Solution. Dies liegt daran, dass in SharePoint 2016 Onpremise 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. Nach Aussage von 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 SiteCollection realisiert werden. Das Grundprinzip beruht dabei auf das bereits bekannte Hochladen von SharePoint AddIns. Dazu muss das entsprechende SPFx-Package aus dem App-Katalog geladen und dann auf der neuen SiteCollection installiert werden. 

(hier am Beispiel eines CSOM-Skriptes) 

// AppCatalog 
    ClientContext appContext = new ClientContext(appCatalogUrl); 
    appContext.Credentials = credentials; 
 
    Web web = appContext.Web; 
    ListCollection lists = web.Lists; 
    appContext.Load(web); 
    appContext.Load(lists); 
    appContext.ExecuteQuery(); 
 
    // Deutsch oder Englisch 
    List cataloglist = lists.FirstOrDefault(c =>  
        c.Title == "Apps for SharePoint" || c.Title == "Apps für SharePoint"); 
    appContext.Load(cataloglist); 
 
    string productID = "517544a9-fa90-4b2e-848e-c15392b19eb0" 
    CamlQuery query = new CamlQuery(); 
    query.ViewXml = "<View><Query><Where><Eq> 
            <FieldRef Name='AppProductID'/><Value Type='Text'>" + productID + "</Value> 
        </Eq></Where></Query></View>"; 
 
    ListItemCollection listItems = cataloglist.GetItems(query); 
    appContext.Load(listItems, c => c.Include(item => item, item => item["AppProductID"])); 
    appContext.ExecuteQuery(); 
 
    ListItem item = listItems.First(); 
    appContext.Load(item); 
    appContext.ExecuteQuery(); 
 
    File file = item.File; 
    appContext.Load(file); 
    appContext.ExecuteQuery(); 
 
    ClientResult<System.IO.Stream>data = file.OpenBinaryStream(); 
    appContext.ExecuteQuery(); 
 
 
    // SiteCollection 
    ClientContext siteContext = new ClientContext(SiteCollectionUrl); 
    Web web1 = siteContext.Web; 
    siteContext.Load(web1); 
    siteContext.ExecuteQuery(); 
 
    AppInstance appInstance = web1.LoadAndInstallApp(data.Value); 
    siteContext.Load(appInstance); 
    siteContext.ExecuteQuery();

 

Führt man dieses Skript aus kommt es zu einer weiteren Fehlermeldung:  

SideLoading ist nicht aktiviert!  

Um hier zum Erfolg zu kommen muss das Feature „SideLoading“ ebenfalls kurzfristig aktiviert werden bevor ‚LoadAndInstallApp() aufgerufen wird. 

FeatureCollection myFeatures = siteContext.Site.Features; 
    context.Load(myFeatures); 
    context.ExecuteQuery(); 
    Guid myFeatureId = new Guid("AE3A1339-61F5-4f8f-81A7-ABD2DA956A7D"); 
 
    // aktivieren 
    myFeatures.Add(myFeatureId, true, FeatureDefinitionScope.None); 
    context.ExecuteQuery(); 
 
    // ... LoadAndInstallApp() ausführen ... 
 
    // deaktivieren 
    myFeatures.Remove(myFeatureId, true); 
    context.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 iApp.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 Addin müssen diese Werte ergänzt werden. 

<?xml version="1.0" encoding="utf-8"?>  
<App xmlns="http://schemas.microsoft.com/sharepoint/2012/app/manifest"   
   Name="helloworld-client-side-solution"   
   ProductID="517544a9-fa90-4b2e-848e-c15392b19eb0" Version="1.0.0.0"   
   SharePointMinVersion="16.0.0.0" IsClientSideSolution="true">  
  <Properties>  
    <Title>helloworld-client-side-solution</Title>  
    <StartPage>/</StartPage>  
  </Properties>  
  <AppPrincipal>  
    <Internal></Internal>  
  </AppPrincipal>  
</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 dann die entsprechenden Properties ergänzen; den Zip-Ordner schließen und dem Package wieder den Original-Dateinamen geben. 

Und schon funktioniert die Bereitstellung für die SiteCollection. 

Tibor Csizmadia | Geschäftsführer DEVWARE GmbH | 29.04.2020

 

 

Sie suchen einen Software Dienstleister?
Informationen zu unseren Leistungen finden Sie in unserem Portfolio