Kolumne: SharePoint ganz praktisch

Felddefinition und Inhaltstypen (Teil 2)
Kommentare

Die vorige Ausgabe dieser Kolumne hat sich mit dem Aufbau von Inhaltstypen sowie mit der deklarativen Erstellung eigener Inhaltstypen befasst. Die heutige Ausgabe widmet sich der deklarativen Anlage von Felddefinitionen und deren Verwendung in Inhaltstypen. Weiterhin wird gezeigt, wie Listen deklarativ angelegt werden. Abschließend wird die programmatische Erstellung der zuvor deklarativ erstellten Artefakte demonstriert.

Die letzte Ausgabe der Kolumne wurde mit der deklarativen Anlage eines Inhaltstypen beendet. Bisher wurden für die beispielhaft erstellten eigenen Inhaltstypen jeweils vorhandene SharePoint-Felder (Field Definition) verwendet. Für neue SharePoint-Anwendungen ist es aber in der Regel sinnvoll, eigene Feldtypen im Vorfeld zu definieren und diese dann für die neuen Inhaltstypen zu verwenden. Die Anlage eigener Felddefinitionen wird zunächst über den deklarativen Ansatz erläutert. Felddefinitionen werden – wie die zuvor erstellten Inhaltstypen auch – über eine elements.xml innerhalb eines SharePoint-Moduls definiert. Diese Datei kann in Visual Studio 2013 sehr einfach über die Vorlage „Site Columns“ angelegt werden (Abb. 1).

Abb. 1: Site-Column-Vorlage in Visual Studio 2013

Listing 1 verdeutlicht, wie in der Definition vorzugehen ist. Beispielhaft werden vier Felder definiert, die jeweils einen anderen Datentypen verwenden.

 ID="{964b697a-cd16-45e7-b8ac-dacdd29f839c}" Name="Productname"
DisplayName="Produktname" Type="Text" Required="TRUE" 
Group="dev-sky Felder">
http://schemas.microsoft.com/sharepoint/">  
  
  
    
      Software
      Hardware
      Service
    
  
  

Das Feld „Produktname“ ist ein einfaches Textfeld, das Feld „Letzte Preisanpassung“ ist ein Datumsfeld und das Feld „Einheitspreis“ stellt eine Währung dar. Als Besonderheit definiert das Feld „Kategorie“ ein Auswahlfeld. Hier können später die definierten Einträge aus dem Choices-Knoten ausgewählt werden. Es ist natürlich auch möglich, die Auswahlwerte aus einer anderen SharePoint-Liste zu beziehen. Für solche Fälle ist ein so genanntes  Lookup-Feld zu definieren. Eine vollständige Übersicht über die XML-Felddefinition Syntax ist unter [1] zu finden. Dort sind auch alle möglichen Datentypen und weitere Konfigurationsmöglichkeiten aufgeführt.

Das Beispiel in Listing1 beschränkt sich auf die Definition der wesentlichsten Elemente. Die neuen Felder können wie die eingebauten SharePoint-Felder für eigene Inhaltstypen verwendet werden. Visual Studio 2013 ermöglicht bei der Definition des Inhaltstypen auch eine direkte Auswahl der neuen Felder aus der SharePoint-Lösung (Abb. 2). Listing 2 zeigt die daraus entstandene Definition des Inhaltstypen. 

Abb. 2: Zusammenstellung der Felder für den neuen Inhaltstypen mit Editor-Unterstützung

 

http://schemas.microsoft.com/sharepoint/„>










Bereitstellung über separate Featurepakete

Im Anschluss an die Definition von neuen Feldern und Inhaltstypen müssen diese in SharePoint installiert werden. Die Felddefinitionen sollten dabei über ein separates Feature unabhängig von den neuen Inhaltstypen bereitgestellt werden. Der oder die Inhaltstypen selbst sind dann wiederum über ein separates Feature bereitzustellen. Um zu gewährleisten, dass die Felder vor der Aktivierung der Inhaltstypen verfügbar sind, kann eine Abhängigkeit zwischen den beiden Featurepaketen festgelegt werden. In diesem Fall ist das Feature der Inhaltstypen abhängig vom Feature der Felddefinitionen.

Abbildung 3 zeigt, wie diese Abhängigkeit über Visual Studio definiert werden kann. Wird später zunächst versucht, das Inhaltstypenfeature zu aktivieren, wird dies von SharePoint mit einer Fehlermeldung abgewiesen (Abb. 4). Beide Features enthalten Datenstrukturdefinitionen. Damit diese in jedem SharePoint-Web verfügbar sind, muss der Gültigkeitsbereich (Scope) der Features auf Site gesetzt werden. Andernfalls kann das Inhaltstypenfeature nur innerhalb eines SharePoint-Webs aktiviert werden.

Abb. 3: Abhängigkeit zwischen SharePoint-Feature definieren

Abb. 4: SharePoint-Fehlermeldung

Nach erfolgreicher Installation der beiden Pakete steht der Inhaltstyp zur Verwendung bereit. Zum Test kann im einfachsten Fall eine benutzerdefinierte Liste mit aktivierten Inhaltstypen eingerichtet werden. Der benutzerdefinierten Liste kann dann der neue Inhaltstyp zugeordnet werden. Abbildung 5 zeigt hierzu einen erfassten Listeneintrag, basierend auf den neuen Inhaltstypen.

Abb. 5: Vorlage für die Erstellung einer Listenvorlage

Benutzerfreundlicher ist es jedoch, wenn die SharePoint-Lösung selbst schon eine vorgefertigte und einsatzbereite Liste installiert. Wie dies erreicht werden kann, wird im nächsten Abschnitt erläutert.

Listendefinitionen und Listeninstanzen

Zusätzlich zu den beiden Features soll der Lösung ein weiteres Feature hinzugefügt werden, das eine Listenvorlage sowie eine konkrete Listeninstanz bereitstellt. Dieses Feature ist pro SharePoint-Web gültig, somit muss der Gültigkeitsbereich des neuen Features später auf „Web“ gesetzt werden.

Visual Studio 2013 unterstützt die deklarative Anlage von Listenvorlagen inklusive einer konkreten Listeninstanz. Für die Neuanlage ist die Vorlage „List“ (Abb. 6) zu wählen. Im nächsten Schritt muss entschieden werden, ob eine anpassbare Listenvorlage oder eine Listeninstanz erstellt werden soll. Hier ist die erste Option zu aktivieren. Nach Abschluss des Assistenten wurde der SharePoint-Lösung eine Listenvorlage sowie eine Listeninstanzdefinition hinzugefügt.

Abb. 6: Listenkonfigurationsoberfläche

Der neuen Liste muss abschließend der zuvor definierte Inhaltstyp zugewiesen werden. Die bereits standardmäßig zugeordneten SharePoint-eigenen Inhaltstypen können aus der Liste entfernt werden. Dies gelingt über die Schaltfläche Content Types der Listenkonfiguration (Abb. 6). Bisher besitzt die SharePoint-Lösung zwei Features mit dem Gültigkeitsbereich „Site“. Für die Listenvorlage wird ein neues Feature mit dem Gültigkeitsbereich „Web“ benötigt, das der Visual-Studio-Lösung noch hinzugefügt werden muss. Da die Listenvorlage zwingend den neuen Inhaltstypen benötigt, sollte auch hier eine Abhängigkeit zwischen den Features definiert werden (Abb. 7). Nach der Installation der Lösung in SharePoint und der Aktivierung des Listenfeatures wird eine neue Produktliste angelegt. Diese kann direkt verwendet und mit Inhalten gefüllt werden. 

Abb. 7: Anhängigkeiten zwischen Listenvorlagenfeature und Feature für die Inhaltstypen

Programmatische Erstellung

Die bisherigen Beispiele verwendeten XML-Deklarationen für die Definitionen neuer Felder, Inhaltstypen und Listen. Teilweise besteht aber die Notwendigkeit, bestimmte Elemente programmatisch zu erstellen. Ein typisches Beispiel dafür ist die nachträgliche und automatische Erweiterung einer Listeninstanz um eine zusätzliche Spalte. Das SharePoint-API ermöglicht es auf einfache Weise, alle bisher gezeigten Elemente per Programmcode anzulegen. Listing 3 zeigt beispielhaft, wie ein neuer Inhaltstyp direkt über das SharePoint-API erstellt werden kann. Wie auch bei der deklarativen Anlage wird ein eindeutiger Guid (ID) für den neuen Content Type benötigt. Einzelheiten zur Guid-Vergabe wurden in der letzten Kolumne erläutert.

 public static readonly SPContentTypeId ctid = new SPContentTypeId("0x010600076ade3f1a4c411ca378622feb18ea2d");
public static void CreateContentType()
{
  using (SPSite container = new SPSite("URL ..."))
  {
    using (SPWeb web = container.OpenWeb())
    {
      if (!web.Fields.ContainsField("Letzter Kundenkontakt"))
      {
        web.Fields.Add("Letzter Kundenkontakt",SPFieldType.DateTime, true);
        web.Fields["Letzter Kundenkontakt"].Group = "dev-sky Felder";
        web.Fields["Letzter Kundenkontakt"].Update();
      }
      if (web.ContentTypes[ctid] == null)
      {
        SPContentType kundenContentType =
        new SPContentType(ctid, web.ContentTypes, "Kundendaten");
        kundenContentType.Group = "dev-sky Inhaltstypen";
        kundenContentType.Description = "...";
        // Entferne Job-Feld 
        kundenContentType.FieldLinks.Delete(
          new Guid("c4e0f350-52cc-4ede-904c-dd71a3d11f7d"));
        // Entferne State/Province-Feld 
        kundenContentType.FieldLinks.Delete(
          new Guid("ceac61d3-dda9-468b-b276-f4a6bb93f14f"));
        // Entferne Web-Page-Feld 
        kundenContentType.FieldLinks.Delete(
          new Guid("a71affd2-dcc7-4529-81bc-2fe593154a5f"));
        // Füge Feld E-Mail2 hinzu 
        kundenContentType.FieldLinks.Add(new SPFieldLink
         (web.AvailableFields[new
          Guid("e232d6c8-9f49-4be2-bb28-b90570bcf167")]));
        // Füge Feld Office hinzu
        kundenContentType.FieldLinks.Add(new SPFieldLink
          (web.AvailableFields[new
           Guid("26169ab2-4bd2-4870-b077-10f49c8a5822")]));
        // Füge Feld Letzter Kundenkontakt hinzu
        kundenContentType.FieldLinks.Add(new SPFieldLink
          (web.Fields["Letzter Kundenkontakt"]));
        web.ContentTypes.Add(kundenContentType);
        kundenContentType.Update();
      }
    }
  }
}

Bei der deklarativen Erstellung wurde die Content-Type-ID automatisch vom Visual-Studio-Assistenten bestimmt, bei der programmatischen Erstellung erfolgt dies manuell. Die erste Herausforderung dabei ist die ID-Ermittlung des übergeordneten Inhaltstypen. Tabelle 1 zeigt einen kleinen Ausschnitt der eingebauten Inhaltstypen inklusive zugehöriger ID. Wurde die ID des übergeordneten Inhaltstypen ermittelt, muss ein neuer GUID erstellt werden. Dies kann direkt aus Visual Studio heraus über das Menü Tools und die Auswahl des Menüpunkts Create GUID erfolgen. Der Menüpunkt öffnet einen kleinen Dialog, über den neue Guids in unterschiedlichen Formaten erstellbar sind. Für die ID eines Inhaltstypen wird das letzte Format „Registry Format“ benötigt. Über die Schaltfläche New GUID wird ein neuer GUID erstellt, der per Copy and Paste in die Zwischenablage kopiert und an der benötigten Stelle wieder eingefügt werden kann. Für die Content-Type-ID werden nur die hexadezimalen Werte benötigt, d. h., die Klammern und Bindestriche müssen entfernt werden.

Tabelle 1: Eingebaute SharePoint-Inhaltstypen und ihre ID

Nachdem die ID des Inhaltstypen feststeht, wird ein neues vom Inhaltstypen benötigtes Feld über das Objektmodell erstellt, Zunächst wird geprüft, ob das Feld bereits vorhanden ist – wenn nicht, wird es angelegt. Dazu wird es der Feldauflistung über die Methode Add hinzugefügt. Beim Aufruf werden der Name und der Datentyp übergeben. Der letzte Parameter legt fest, ob es sich um ein Pflichtfeld handelt (true) oder nicht (false). Anschließend wird die Gruppe angegeben und die Änderungen werden per Updateaufruf gespeichert.

Danach erfolgt die programmatische Anlage des Inhaltstypen. Auch hier wird zunächst geprüft, ob dieser bereits vorhanden ist. Wenn nicht, wird eine neue Instanz der Klasse SPContentType erstellt. Dem Konstruktor wird die definierte ID (SPContentTypeId), die Web-Content-Type-Auflistung sowie die Bezeichnung übergeben. Zusätzlich werden die Werte für Group und Description festgelegt. Ist die ContentType-Instanz soweit vorbereitet, werden die Felder konfiguriert. Wie auch im deklarativen Beispiel werden drei geerbte Felder des übergeordneten Inhaltstypen entfernt und drei neue hinzugefügt. Bevor dann die Methode Update aufgerufen werden kann, wird die Content-Type-Instanz der Auflistung ContentTypes über Add hinzugefügt. Der so vorbereitete Code kann innerhalb einer einfachen Konsolenanwendung ausgeführt werden.

Der entsprechenden Site wird dabei der definierte Inhaltstyp hinzugefügt. Wenn der Vorgang erfolgreich war, befindet sich der neue Inhaltstyp innerhalb der SharePoint-Galerie „Websiteinhaltstyp“.

Einmal erstellte Inhaltstypen sind nicht statisch und können bei Bedarf später noch modifiziert werden. Listing 4 zeigt beispielhaft, wie nachträglich ein vorhandenes Feld entfernt und ein neues hinzugefügt werden kann. Zunächst wird erneut ein Zugriff auf eine SPWeb-Instanz benötigt. Über die dortige Eigenschaft ContentTypes wird der zu ändernde Content Type über die ID des Inhaltstypen abgerufen. Ist der Inhaltstyp vorhanden, wird ein neues Feld hinzugefügt und ein Feld entfernt. Anschließend werden die Änderungen per Updateaufruf gespeichert.

 public static void ChangeContentType()
{
  using (SPSite container = new SPSite("..."))
  {
    using (SPWeb web = container.OpenWeb())
    {
      SPContentType ct = web.ContentTypes[ctid];
      if (ct != null)
      {
        ct.FieldLinks.Add(new SPFieldLink(web.AvailableFields
          [new Guid("a8eb573e-9e11-481a-a8c9-1104a54b2fbd")]));
        // Entferne Feld E-Mail2
        ct.FieldLinks.Delete(
          new Guid("e232d6c8-9f49-4be2-bb28-b90570bcf167"));
        ct.Update();
      }
    }
  }
}
 

Programmatische Listeninstanz

Ist der neue Inhaltstyp in SharePoint verfügbar, kann er innerhalb einer Bibliothek oder Liste verwendet werden. Weiter oben wurde bereits demonstriert, wie dies über den deklarativen Ansatz möglich ist. Auch die programmatische Anlage einer Liste mit einem bestimmten Inhaltstypen ist über das SharePoint-API möglich. Dazu genügen bereits wenige Codezeilen (Listing 5). Der Einstiegspunkt für die Anlage einer neuen Liste bildet die Listenauflistung eines SharePoint-Webs. Über die Methode Add wird eine neue Liste erstellt. Dabei müssen der Titel, die Beschreibung sowie eine Listenvorlage angegeben werden. Nach dem Aufruf gibt die Methode den eindeutigen GUID an die neu angelegte Liste zurück. Mithilfe des GUIDs kann die neue Listeninstanz für weitere Einstellungen abgerufen werden. Zuletzt erfolgt die Konfiguration der Inhaltstypen. Hier wird der Standardinhaltstyp „Item“ entfernt und anschließend der zuvor erstellte Inhaltstyp „Kundendaten“ der Liste hinzugefügt. Schlussendlich werden alle Einstellungen per Update übernommen. Nach der Ausführung dieser Codezeilen befindet sich im adressierten SharePoint-Web eine neue Liste mit dem Titel „Kunden“. Bei der weiter oben gezeigten deklarativen Erstellung einer Listeninstanz wurde zeitgleich eine Listendefinition bzw. Listenvorlage erstellt. Die Listenvorlage kann innerhalb von SharePoint verwendet werden, um zusätzliche Listen des gleichen Typs über die Oberfläche anzulegen. Die programmatische Anlage von Listendefinitionen ist allerdings nicht über das SharePoint-API möglich.

 public static void CreatListInstance()
{
  using (SPSite container = new SPSite("..."))
  {
    using (SPWeb web = container.OpenWeb())
    {
      Guid listId = web.Lists.Add("Kunden", 
        "Beschreibung der Liste", SPListTemplateType.GenericList);
      SPList newList = web.Lists[listId];
      newList.ContentTypesEnabled = true;
      newList.EnableAttachments = false;
      newList.OnQuickLaunch = true;
      newList.EnableVersioning = false;
      newList.ContentTypes.Add(web.ContentTypes["Kundendaten"]);
      newList.ContentTypes["Item"].Delete(); 
      newList.Update();
    }
  }
}
 

Zusammenfassung

In dieser Kolumne wurde demonstriert, wie eigene SharePoint-Felddefinitionen erstellt und innerhalb von Inhaltstypen verwendet werden können. Durch die zusätzliche Bereitstellung einer Listenvorlage und Listeninstanz ist es dem Anwender direkt möglich, den Inhaltstypen zu verwenden. Ebenfalls wurde gezeigt, wie eine Lösung auf Features aufgeteilt und wie Abhängigkeiten zwischen den Features definiert werden können. Anhand des letzten Beispiels wurde deutlich, dass Inhaltstypen auch nachträglich angepasst werden können.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -