Von Web Parts, Events, Templates und Application Pages

Stein auf Stein
Kommentare

Im zweiten Teil der Serie „SharePoint als Entwicklungsplattform“ werden, aufbauend auf den Grundlagenwissen des ersten Teils, Building Blocks erläutert, d. h. Bausteine, die man als Erweiterung für SharePoint entwickeln kann. Erfahren Sie in diesem Artikel, wie man Application Pages, Web Parts, Event Receiver und Templates für SharePoint implementiert.

Der Microsoft SharePoint Server 2010 ist eine erfolgreiche Entwicklungsplattform. Auch der Vorgänger SharePoint 2007 und dessen kostenlose Variante Windows SharePoint Services 3.0 sind immer noch häufig eingesetzte Plattformen für Anwendungsentwicklung. Im ersten Teil der Artikelserie „SharePoint 2010 als Entwicklungsplattform“ wurden die Entwicklungsumgebung, notwendige Voraussetzungen und das SharePoint-Objektmodell vorgestellt. Darauf aufbauend werden nun so genannte Building Blocks vorgestellt, also Bausteine, die man für SharePoint entwickeln kann. In der Regel benötigt man für seine individuelle SharePoint-Anwendung mehrere dieser Bausteine, also z. B. eine Application Page und Event Receiver für Listen oder man definiert sein Listen-Datenmodell in Form von Listen-Templates. Wie man diese zentralen Komponenten erstellt und anwendet, wird in den folgenden Abschnitten erläutert.

Artikelserie

Teil 1: Vielseitig und mächtig – SharePoint als Entwicklungsplattform

Teil 2: Stein auf Stein – Entwicklung von Erweiterungen<7p>

Teil 3: Hinterm Horizont – SharePoint + X

Site Pages vs. Application Pages

In SharePoint unterscheidet man grob zwei Arten von Webseiten. Zum einen die Site Pages, die dadurch charakterisiert sind, dass diese Webseiten komplett in der Inhaltsdatenbank von SharePoint existieren. Diese Site Pages sind in der Regel Web-Part-Seiten, Wiki-Seiten oder „normale“ Webseiten. Sie können i.d.R. über einen Edit-Button in SharePoint bearbeitet oder individuell personalisiert werden. Die persönlichen Einstellungen zu diesen Seiten, die Inhalte und der Aufbau werden vollständig in der Inhaltsdatenbank von SharePoint verwaltet.
Dahingegen zeichnen sich die Application Pages oder Anwendungsseiten dadurch aus, dass diese als physikalische Dateien auf den SharePoint-Servern im SharePoint Root (Installationsverzeichnis) liegen und nicht editiert werden können. Lediglich die Inhalte der Seiten werden entsprechend dem aktuellen Kontext dynamisch geladen. Bekannte Beispiele für Application Pages sind u. a. die Einstellungsseite einer Website (settings.aspx) oder die Webseite „Alle Websiteinhalte anzeigen“ (viewlsts.aspx). Application Pages erkennt man daran, dass sie über einen URL der Form http://hostname/sitename:Portnummer/_layouts/Unterverzeichnis/ApplicationPage.aspx aufgerufen werden. Das _layouts im URL wird im IIS-Webserver auf das Verzeichnis SharePointRootTEMPLATELAYOUTS gemappt. Der Hostname bzw. Pfad zur Website vor dem _layouts bestimmt den SharePoint-Kontext, den die Application Page verwendet.

Zum Beispiel zeigt die gleiche Application Page viewlsts.aspx bei diesen beiden URLs unterschiedliche Websiteinhalte an:

Da diese Webseiten nicht über die SharePoint-Oberfläche editiert werden können, heißen sie Application Pages. Solche Application Pages kann man auch selbst entwickeln. In Visual Studio kann man leicht in einem SharePoint-Projekt ein neues Item „Application Page“ hinzufügen. Die neu erstellte Application Page wird im Solution Explorer unter dem LayoutsProjektname-Ordner hinzugefügt und ähnelt einer ganz normalen ASP.NET-Webseite. Listing 1 zeigt den Markup-Code einer solchen Application Page.

<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ApplicationPage1.aspx.cs" Inherits="SharePointProject2.Layouts.SharePointProject2.ApplicationPage1" DynamicMasterPageFile="~masterurl/default.master" %>
<asp:Content ID="Main" ContentPlaceHolderID="PlaceHolderMain" runat="server">
  <asp:PlaceHolder ID="pchMain" runat="server" />
</asp:Content>

<asp:Content ID="PageTitle" ContentPlaceHolderID="PlaceHolderPageTitle" runat="server">
  Application Page
</asp:Content>

<asp:Content ID="PageTitleInTitleArea" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea" runat="server" >
  My Application Page
</asp:Content>


Dort werden zunächst die SharePoint-Assemblies und -Namensräume referenziert sowie die Master Page. Master Pages in ASP.NET, das die technische Grundlage für SharePoint-Webseiten bildet, definieren die Struktur von Webseiten, indem verschiedene Platzhalter Bereiche definieren, in denen zur Laufzeit die konkreten Inhalte der Application Pages, welche die Master Page verwenden, geladen werden. In Listing1 sind drei Platzhalter auszugsweise implementiert, wobei der ContentPlaceHolder Main der wichtigste Platzhalter ist, da er den Hauptinhaltsbereich der Webseite befüllt. Schaut man in den Code behind der Webseite in Listing 2, sieht man, dass die Klasse der Application Page von der SharePoint-Klasse LayoutsPageBase erbt, die wiederum von der Klasse System.Web.Page erbt, die auch für einfache ASP.NET-Webseiten verwendet wird. Durch das Erben von LayoutsPageBase erhält man u. a. eine Eigenschaft this.Web, die den aktuellen Kontext in Form eines SPWeb-Objekts enthält. Dadurch erhält man sehr einfach Zugriff auf den aktuellen SharePoint-Kontext, d. h. aktueller Benutzer, Listen, Bibliotheken, Berechtigungen, usw. der Website. Im Beispiel von Listing 2 wird gezeigt, wie man mit wenigen Zeilen alle Listen und Bibliotheken, deren Typ und Anzahl der Listeneinträge auf der Application Page ausgibt. In der Page_Load-Methode werden alle Listen der aktuellen Website durchiteriert und im ContentPlaceHolder-Control ausgegeben. Natürlich kann man solche Applications Pages enorm ausbauen, sodass man z. B. einen Konfigurations-Wizard wie in Abbildung 1 in einer solchen Application Page implementiert.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

namespace SharePointProject2.Layouts.SharePointProject2
{
  public partial class ApplicationPage1 : LayoutsPageBase
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      foreach (SPList list in this.Web.Lists)
      {
        this.pchMain.Controls.Add(new Label() { Text = list.Title + " - " + list.BaseType.ToString() + " - Anzahl Items: " + list.ItemCount.ToString()+"
" }); } } } }

Abb. 1: Konfigurations-Wizard als Application Page

Sämtliche Einstellungen zu Listen, Dokumentenbibliotheken, Berechtigungen und Web Parts auf der Startseite lassen sich vereinfacht in diesem Konfigurations-Wizard vornehmen. Der Wizard ist als eine einzige Application Page implementiert, welche die Einstellungen und Konfigurationen über das SharePoint-Objektmodell umsetzt. Ähnlich wie Application Pages können auch Web Parts Informationen aufbereiten und Funktionen zur Verfügung stellen.

Aufmacherbild: Piled up pebbles on a brown background von Shutterstock / Urheberrecht: wavebreakmedia

[ header = Web Parts]

Web Parts – Zentrale Funktionsbausteine in SharePoint

Web Parts sind eine Kernkomponente von SharePoint-Portalen. Die konfigurierbaren Funktionsbausteine können flexibel eingesetzt, angepasst und personalisiert werden. Das Konzept der Web Parts kommt aus dem ASP.NET-Framework, wo es ebenfalls Web Parts gibt. In SharePoint haben Web Parts einige konfigurierbare Eigenschaften wie Darstellung, Größe und Personalisierungsoptionen gemeinsam, denn diese werden durch die Oberklasse System.Web.UI.WebControls.WebParts.WebPart definiert. Diese Web Parts können auf Web-Part-Seiten in so genannten Web-Part-Zonen organisiert werden. D. h. es gibt feste Zonen, in die man Web Parts hinzufügen kann. Das Konzept mit den Web-Part-Zonen hat den Vorteil, dass Anwender die Funktionsbausteine einfach hinzufügen und verteilen können, ohne sich mit HTML, Tabellen und Ähnlichem befassen zu müssen. Abbildung 2 zeigt eine Web-Part-Seite im Editiermodus, in dem man die Web-Part-Zonen und beinhaltete Web Parts sehen kann.

Abb. 2: Web-Part-Seite im Editiermodus

Das Entwickeln von Web Parts beschränkte sich in SharePoint 2007 auf das Implementieren einer nicht visuellen Klasse und das Erstellen einer Konfigurationsdatei. Mit Visual Studio 2010 und SharePoint 2010 ist das Entwickeln von Web Parts sehr viel komfortabler geworden. Zum einen unterstützt Visual Studio 2010 das Hinzufügen, Implementieren und Verwalten von Web Parts im Solution Explorer sehr viel besser und bietet zum anderen auch eine Vorlage für ein Visual Web Part, d. h. ein Web Part, bei dem man auch die Oberfläche designen kann. Der „Visual“-Aspekt bei dieser Art Web Part wird durch ein ASP.NET User Control realisiert. Das Web Part selbst ist im Grunde das gleiche wie ein normales Web Part, nur das es eben das „grafische“ User Control lädt.
In einem SharePoint-Projekt kann man im Visual Studio 2010 über das Menü Projekt | Add new Item ein Visual Web Part hinzufügen. Das Visual Studio 2010 legt dann im Solution Explorer die folgenden Inhalte an:

  • User Control: Wird vom Web Part zu Laufzeit geladen.
  • Feature: Ist der Transportcontainer, der das Web Part auf Websitesammlungsebene bereitstellt.
  • Codeslasse: Ist die Implementierung des Web Parts. Bei einem Visual Web Part wird hier initial das User Control über Page.LoadControl(string pfad) geladen.
  • Konfigurationsdatei: Die .webpart-Datei spezifiziert Titel, Beschreibung, Klasse und Assembly des Web Parts

Man kann nun sowohl im User Control als auch in der Codeklasse die Funktion und das Aussehen des Web Parts implementieren. Da das Web Part und das User Control von keiner SharePoint-Oberklasse erben, muss man zunächst den SharePoint-Kontext referenzieren:

SPWeb web = SPContext.Current.Web;

Anschließend kann man genau wie bei der Application Page über das SharePoint-Objektmodell auf SharePoint-Portal-Inhalte zugreifen und diese grafisch aufbereiten. Der Programmcode aus Listing 2 würde also auch in diesem Web Part problemlos funktionieren. Typische Aufgabengebiete von Web Parts sind:

  • Zusammenführen und Aufbereiten von Informationen und Daten
  • Bereitstellen von Funktionen/Operationen
  • Darstellen von SharePoint-Listen und -Bibliotheken

Dabei folgen, wie bereits oben erwähnt, einem einheitlichen Grundschema. Es besteht aus:

  • Datenquelle
  • Web-Part-Eigenschaften
  • Grafische Ausgabe

Dabei unterscheidet man grob zwei Arten von Web Parts. Zum einen die Listen- und Bibliotheks-Web-Parts, welche die Listen und Bibliotheksansichten einer SharePoint-Site wiedergeben, und zum anderen Funktions-Web-Parts, die eine bestimmte Funktion bereitstellen oder erfüllen. Zu den bekanntesten Web Parts gehören das Inhaltseditor-Web-Part, das einen RichText Editor zum Bearbeiten bzw. Anzeigen von RichText bereitstellt oder das Chart-WebPart, das Charts und Diagramme aus Daten verschiedener Datenquellen grafisch anzeigt.
Möchte man nun das eigene Visual Web Part implementieren, richtet man sich nach diesem Grundschema. Listing 3 zeigt ein einfaches User Control, das von einem Visual Web Part geladen wird. Nach dem Deployment befindet sich das Web Part in der Web-Part-Galerie der Websitesammlung. Die der SharePoint Solution zugehörige Web-Part-Konfigurationsdatei spezifiziert neben Titel und Beschreibung auch die Klasse und die Assembly des Web Parts. Diese Konfigurationsdatei wird in der Web-Part-Galerie gespeichert. Im Programmcode enthält das vom Visual Web Part geladene User Control nur ein einziges Repeater Control, welches die grafische Ausgabe der Daten übernimmt. Beim Laden des User Controls wird zunächst die Datenquelle über das SharePoint-Objektmodell erzeugt. Aus der Liste „Gemeindeverzeichnis“ werden 10 Einträge als neue Datenquelle an den Repeater gebunden, der daraus eine HTML-Tabelle rendert.

//MarkUp Code des User Controls
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="VisualWebPart1UserControl.ascx.cs"
    Inherits="SharePointProject2.VisualWebPart1.VisualWebPart1UserControl" %>
<asp:Repeater runat="server" ID="rptListData">
  <HeaderTemplate>
    <table>
  </HeaderTemplate>
  <FooterTemplate>
    </table>
  </FooterTemplate>
  <ItemTemplate>
    <tr>
      <td>
        <%# Eval("Title") %>
      </td>
    </tr>
  </ItemTemplate>
</asp:Repeater>

//Auszug aus dem CodeBehind des User Controls
protected void Page_Load(object sender, EventArgs e)
{
  SPWeb web = SPContext.Current.Web;
  List<SPListItem> listItems = new List<SPListItem>();
  foreach (SPListItem item in web.Lists["Gemeindeverzeichnis"].Items)
  {
    listi.Add(item);
  }

  var result = from c in listItems
               select new
               {
                 Title = c.Title,
                 Description = c.ID
               };
  result = result.Take(10);
  rptListData.DataSource = result;
  rptListData.DataBind();
}

//Visual WebPart Code mit konfigurierbarer Eigenschaft maxItems
 [ToolboxItemAttribute(false)]
public class VisualWebPart1 : WebPart
{
  // Visual Studio might automatically update this path when you change the Visual Web Part project item. 
  private const string _ascxPath = @"~/_CONTROLTEMPLATES/SharePointProject2/VisualWebPart1/VisualWebPart1UserControl.ascx";
 [WebBrowsable]
  [WebDisplayName("MaxItems")]
  [WebDescription("MaximumItems")]
  [Category("Items")]
  [Personalizable(PersonalizationScope.User)]
  public int maxItems;

  protected override void CreateChildControls()
  {
    Control control = Page.LoadControl(_ascxPath);
    Controls.Add(control);
  }
}

Um das Web Part und dessen Funktion über die Oberfläche konfigurierbar und personalisierbar zu machen, können Eigenschaften definiert werden, die über Attribute gekennzeichnet werden. Am Ende von Listing 3 ist eine solche Eigenschaft MaxItems definiert. Sie stehen dann in der SharePoint-Weboberfläche in den Web-Part-Eigenschaften zur Verfügung. Web Parts können noch sehr viel mehr erweitert werden, z. B. durch die Implementierung komplett eigener Eigenschaftsabschnitte, so genannter ToolParts, kontextsensitive Ribbon-Leisten oder verbundene Web Parts, die das Provider-Consumer-Pattern implementieren.

[ header = Event Receiver ]

Event Receiver

Der dritte Building Block sind Event Receiver, also automatische Ereignisbehandlungsmethoden. Diese Event Receiver sind vielseitig und können in SharePoint mit verschiedenen Objekten verknüpft werden:

  • Listeneinträge
  • Listen-Workflows
  • Listen-E-Mail-Ereignisse
  • Websites

Je nach Typ des Event Receivers und ggf. Art der Liste gibt es unterschiedliche Ereignisse, auf die man reagieren kann. Dazu gehören unter anderem:

  • Ein Listeneintrag wird/wurde hinzugefügt
  • Ein Listeneintrag wird/wurde geändert
  • Eine Website wird/wurde angelegt
  • Eine E-Mail wurde empfangen
  • Ein Workflow wird/wurde gestartet oder gestoppt
  • Usw.

Anhand der aufgeführten Beispielereignisse kann man schon erkennen, dass es zwei Arten von Event Receivern gibt: synchrone und asynchrone Event Receiver. Während die asynchronen Ereignisbehandlungsmethoden erst nach dem Ereignis ausgeführt werden z. B. wenn ein neuer Listeneintrag angelegt wurde, werden die synchronen Ereignisbehandlungsmethoden während des Auftretens des Ereignisses ausgeführt und bieten die Gelegenheit die Ereignisbehandlung abzubrechen oder zu verändern. Dank des Visual Studio 2010 sind diese Event Receiver sehr einfach zu implementierten. Über das Kontextmenüs eines SharePoint-2010-Projektes auf ADD NEW ITEM gehen und EVENT RECEIVER auswählen. In dem nachfolgenden Dialog konfiguriert man, welchen Typ und welches Ereignis man behandeln möchte und erhält anschließend eine generierte Klasse, die z. B. bei Listen Event Receiver von SPItemEventReceiver erbt. Die Klasse überschreibt die ausgewählten synchronen oder asynchronen Ereignisse bzw. man muss dann seinen eigenen Programmcode ergänzen. Listing 4 zeigt einen Event Receiver, der das asynchrone Ereignis ItemAdded implementiert sowie das synchrone Ereignis ItemUpdating.

public class MyEventReceiver : SPItemEventReceiver
{
  // An item is being updated. 
  public override void ItemUpdating(SPItemEventProperties properties)
  {
    if ((properties.AfterProperties["Title"] as String).Contains("Test"))
    {
      properties.ErrorMessage = "Title Attribute contains "Test"";
      properties.Cancel = true;
    }
  }

  // An item was added. 
  public override void ItemAdded(SPItemEventProperties properties)
  {
    EventFiringEnabled = false;
    var title = properties.ListItem.Title;
    title += " - Added by Event Receiver";
    properties.ListItem["Title"] = title;
    properties.ListItem.Update();
    EventFiringEnabled = true;
  }

}

Damit selbstimplementierte Event Receiver wirksam werden, muss man sie für die jeweiligen Listen oder Websites registrieren. Entweder deklarativ mit XML in einem Feature wie in Listing 5 oder programmatisch über die Eigenschaft EventReceiver einer Liste oder einer Website:

mySPList.EventReceivers.Add(SPEventReceiverType.ItemAdded, "MeineAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=65e9bceba4e9426f", "SharePointProject.EventReceiver"); 

In beiden Varianten werden die spezifizierten Klassen in den genannten Assemblies zu den Listen hinzugefügt. In Listing 5 an alle benutzerdefinierten Listen (Template Type 100) und in der programmatischen Zeile nur bei der Liste mySPList. Die registrierten Ereignistypen sprechen für sich und finden sich in der zugehörigen Klasse als überschriebene Methoden wieder.
Event Receiver sind ein effizientes Werkzeug, um Funktionen und Abläufe in SharePoint zu automatisieren, daher sind sie für die folgenden Einsatzzwecke sinnvoll:

  • Berechnen und Setzen von Feldwerten
  • Prüfen, Ändern und Rückgängigmachen von Metadaten in Listeneinträgen
  • Anlegen von Websites

Für die folgenden Einsatzzwecke sind Event Receiver eher ungeeignet und sollten durch andere Lösungen wie z. B. Workflows ersetzt werden:

  • Automatisierung komplexer Prozesse
  • Interaktion mit Menschen z. B. Genehmigungen
  • Transaktionsorientierte Prozesse

Zuletzt gibt es noch einige Besonderheiten, die es zu beachten gilt, wenn man Event Receiver entwickelt:

  • Event Receiver können sich gegenseitig auslösen, daher gibt es eine Eigenschaft EventFiringEnabled in der EventReceiver-Klasse, um Schleifen und Kettenreaktionen zu unterbinden.
  • Event Receiver werden nicht vom Systemkonto ausgelöst.
  • Sind mehrere Event Receiver an einer Liste oder Website registriert, entscheidet das Sequence-Attribut über die Reihenfolge der der Abarbeitung.
  • In Event Receivern steht kein HTTP-Kontext zur Verfügung, weil die Ereignisse im Hintergrund und nicht in einer Webseite behandelt werden.
  • Es gibt in der SharePoint-Oberfläche keine Übersicht, welche Event Receiver wo registriert sind, daher muss man ggf. eigene Application Pages zur Übersicht und Verwaltung der Event Receiver implementieren.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListTemplateId="100">
    <Receiver>
      <Name>EventReceiverItemUpdating</Name>
      <Type>ItemUpdating</Type>
      <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
      <Class>SharePointProject2.EventReceiver.EventReceiver</Class>
      <SequenceNumber>10000</SequenceNumber>
    </Receiver>
    <Receiver>
      <Name>EventReceiverItemAdded</Name>
      <Type>ItemAdded</Type>
      <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
      <Class>SharePointProject2.EventReceiver.EventReceiver</Class>
      <SequenceNumber>10000</SequenceNumber>
    </Receiver>
  </Receivers>
</Elements>

[header = Templates und Side Colums]

Templates

Templates gehören ebenfalls zu den Grundbausteinen von SharePoint-Anwendungen. Sie können in SharePoint auf verschiedenen Ebenen eingesetzt werden und erhöhen durch den Grad der Wiederverwendung erheblich einheitliche Strukturen und Standards in SharePoint-Portalen. Es gibt die folgenden drei Arten von Vorlagen in SharePoint:

  • Site Columns/Content Types: Vorlage für eine Metadatenspalte bzw. eine spezifizierte Menge von Spalten
  • List Definitions: Vorlagen für Listen oder Bibliotheken
  • Site Definitions: Vorlagen für Websites

Definitions vs. Templates

In SharePoint gibt es zwei Begrifflichkeiten und zugehörige Möglichkeiten, um Vorlagen zu erzeugen. Entweder man generiert aus einer bestehenden Liste oder Website eine Vorlage über die SharePoint-Oberfläche (Template) oder man spezifiziert eine Listenvorlage oder Websitevorlage in XML im Visual Studio (Definition). In diesem Artikel wird die zweite Variante betrachtet, weil das Generieren einer Vorlage aus einer bestehenden Listeninstanz oder Website erhebliche Nachteile hat, u. a. festverdrahtete GUIDs, Sprache, verwendete Features, Lookups usw. Diese Templates, die sich in den entsprechenden Galerien befinden, können nur bedingt in anderen SharePoint-Umgebungen wiederverwendet werden und sind daher für SharePoint-Lösungen, die das aus dem ersten Artikel dieser Artikelserie vorgestellte Deployment-Konzept berücksichtigen, ungeeignet.

Site Columns

Metadatenspalten lassen sich in einem Feature in XML spezifizieren. Im Grunde spezifiziert man das, was man auch im „Create Column“-Dialog in der SharePoint-Oberfläche konfiguriert. Listing 6 zeigt die Definition von zwei Spalten sowie eines Content Types (z. dt. Inhaltstyp), der eine vorgefertigte Zusammenfassung von Metadatenspalten ist und in beliebigen Listen und Bibliotheken wiederverwendet werden kann. Die zugehörigen Attribute, die die Spalten und den Inhaltstyp spezifizieren, erklären sich von selbst.

 

 <Field ID="{918C0134-8227-4E50-BD30-7A1E652D5DF8}"
       Name="Bemerkung"
       SourceID="http://schemas.microsoft.com/sharepoint/v3"
       StaticName="Bemerkung"
       Group="SharePoint"
       Type="Text"
       DisplayName="Bemerkung" /gt;
 <Field ID="{42BAE5A3-15F6-40DF-AF76-EA8F8C59FF7A}"
       Name="Erledigt"
       SourceID="http://schemas.microsoft.com/sharepoint/v3"
       StaticName="Erledigt"
       Group="SharePoint"
       Type="Boolean"
       DisplayName="Erledigt" /gt;
 <ContentType ID="0x01000D" Name="SharePoint Dokument Inhaltstyp" Group="SharePoint" Description="Erstellt ein SharePoint Dokument mit Metadaten." Version="0" xmlns="http://schemas.microsoft.com/sharepoint/" Hidden="False" ReadOnly="False" ResourceFolder="Dokument" Sealed="False"gt;
   <Folder TargetName="_cts/Dokument" /gt;
   <FieldRefsgt;
     <FieldRef ID="{c042a256-787d-4a6f-8a8a-cf6ab767f12d}" Name="ContentType" /gt;
     <FieldRef ID="{5f47e085-2150-41dc-b661-442f3027f552}" Name="SelectFilename" /gt;
     <FieldRef ID="{8553196d-ec8d-4564-9861-3dbe931050c8}" Name="FileLeafRef" Required="TRUE" /gt;
     <FieldRef ID="{8c06beca-0777-48f7-91c7-6da68bc07b69}" Name="Created" Hidden="TRUE" /gt;
     <FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" Required="FALSE" ShowInNewForm="FALSE" ShowInEditForm="TRUE" /gt;
     <FieldRef ID="{28cf69c5-fa48-462a-b5cd-27b6f9d2bd5f}" Name="Modified" Hidden="TRUE" /gt;
     <FieldRef ID="{822c78e3-1ea9-4943-b449-57863ad33ca9}" Name="Modified_x0020_By" Hidden="FALSE" /gt;
     <FieldRef ID="{4dd7e525-8d6b-4cb4-9d3e-44ee25f973eb}" Name="Created_x0020_By" Hidden="FALSE" /gt;
     <FieldRef ID="{918C0134-8227-4E50-BD30-7A1E652D5DF8}" Name="Bemerkung" Hidden="FALSE" ShowInDisplayForm="TRUE" ShowInNewForm="FALSE" ShowInEditForm="TRUE"/gt;
     <FieldRef ID="{42BAE5A3-15F6-40DF-AF76-EA8F8C59FF7A}" Name="Erledigt" Hidden="FALSE" ShowInDisplayForm="TRUE" ShowInNewForm="FALSE" ShowInEditForm="TRUE"/gt;

   </FieldRefsgt;
 </ContentType>

[ header = List Definitions]

List Definitions

Vorlagen für Listen bestehen im einfachsten Fall aus einer XML-Konfigurationsdatei, die schema.xml heißt, und einem Feature, das die Listenvorlage zur Verfügung stellt. Erstellen kann man eine List Definition über das Visual Studio 2010 über Projekt-Kontextmenü ADD NEW ITEM- LISTDEFINITION. Der Wizard-Assistent fragt nach dem Basistyp der Listenvorlage, z. B. Dokumentenbibliothek oder benutzerdefinierte Liste, sowie ob beim Aktivieren des Features auch eine Listeninstanz dieses Typs mit angelegt werden soll. Anschließend befindet sich in der SharePoint Solution ein Objekt für die List Definition mit einer Datei elements.xml und einer schema.xml-Datei sowie ggf. der Listeninstanz. Die erste Datei gehört zum Feature und registriert die Vorlage, sodass diese verwendbar ist. Wichtig hier sind eindeutige Namen und Type IDs. Die übrigen Parameter beschreiben den Basistyp der Liste, Anzeigename, Icon und Beschreibung, sowie Zugriffsrechte über das Attribut SecurityBits. In der Datei schema.xml wird die eigentliche Vorlage spezifiziert. Die XML-Datei ist grob in vier Abschnitte aufgeteilt:

  • ContentTypes: Referenzierung bzw. Spezifikation von Content Types
  • Fields: Spezifikation von Metadatenfeldern
  • Views: Spezifikation von Ansichten, d. h. Menge von angezeigten Metadatenspalten, Filter, Sortierungen usw.
  • Forms: Neu-, Bearbeiten- und Ansichtsformular spezifizieren

Im Abschnitt Content Types kann man entweder einen eigenen Listen-Content-Type definieren oder einen vorhandenen Content Type referenzieren. Erstellt man die Vorlage über den Wizard, wird der Content Type mit der ID „0x01“ referenziert, was für ein Standard-Item mit Title-Spalte steht, sowie „0x0120“ für einen Ordner. Alternativ kann man einen eigenen Content Type definieren, indem man mit dem Element FieldRef über die zugehörigen, eindeutigen GUID vorhandene Metadatenspalten referenziert. Im Abschnitt Fields kann man solche Metadatenspalten definieren. Je nach Typ der Metadatenspalte muss man mal mehr und mal weniger Attribute definieren. Ein einfaches Ja/Nein-Feld definiert man mit der folgenden Zeile:

<Field Type="Boolean" Description="Automatikgetriebe" DisplayName="Automatikgetriebe" ID="{F45D607B-4DAE-4169-81A0-8D19F1C4ED63}"  StaticName="Automatikgetriebe" Name="Automatikgetriebe"  RowOrdinal="0">
  <Default>0</Default>
</Field>

Der letzte wichtige Bereich sind die Views bzw. Ansichten. Über diese Views definiert man vorgefertigte Sichten auf die Liste bzw. Bibliothek mit Sortierung, Filter und Gruppierungen. Analog zu den Möglichkeiten der SharePoint-Weboberfläche kann man alle Einstellungen auch im XML-Format spezifizieren. In einer View definiert man neben dem Namen und dem URL der View die folgenden Inhalte:

  • Angezeigte Metadatenspalten
  • Sortierung
  • Filter
  • Gruppierung
  • Joins
  • Anzeigeformat

Im Bereich Forms kann man die Neu-, Bearbeiten- und Ansichtsformulare definieren. Standardmäßig werden diese von einer Vorlage über das Attribut SetupPath generiert. Allerdings kann man an dieser Stelle auch die Standardformulare durch eigene ersetzten, wenn man möchte. Das Erstellen einer List Definition ist relativ schwierig und fehleranfällig. Trotz IntelliSense und spärlicher Syntaxprüfung fallen Fehler oftmals erst zur Laufzeit auf, daher sollte man prüfen, ob man wirklich wiederverwendbare Vorlagen benötigt oder nur einzelne Listen, die man auch per Objektmodell (SPList) erstellen kann. Um die Datei schema.xml besser zu verstehen, eignet sich der zugehörige Artikel in der MSDN .

Site Definitions

Ähnlich wie List Definitions lassen sich auch Site Definitions erstellen. Diese Vorlagen für SharePoint-Sites werden von SharePoint selbst genutzt, z. B. für die Standard-Teamsite, leere Website oder BlogSite. Genau wie List Definitions werden auch die Site Definitions per XML spezifiziert und können über eine Visual Studio-2010-Projektvorlage erstellt werden. D. h., man kann im Visual Studio 2010 nur eine Site Definition über ein neues SharePoint-Projekt erstellen, keine Site Definition zu einem bestehenden Projekt hinzufügen. Mit Erweiterungen wie z. B. CKSDEV Extensions, geht das aber trotzdem. Eine Site Definition besteht aus den folgenden drei Komponenten:

  • Default.aspx: Startseite der neuen SharePoint-Site
  • Onet.xml: Konfigurationsdatei einer oder mehrerer SharePoint-Site-Vorlagenkonfigurationen
  • Webtemp_xxx.xml: Stellt die Site Definition im entsprechenden Erstellungsdialog zur Verfügung

 

Die Datei Default.aspx spezifiziert die Startseite einer von der Site Definition instanziierten Website. Initial enthält sie nur den Verweis auf die Standard-Master-Page sowie mehrere SharePoint-Assemblies und -Namenräume. Der eigentliche Inhaltsbereich im ContentPlaceHolderMain enthält initial lediglich einen simplen Text. Die default.aspx-Seite kann nach Belieben erweitert werden, z. B. durch Web- Part-Zonen, Web Parts und sonstige Inhalte.

Die Webtemp_xxx.xml-Datei wird pro Sprache mitgeliefert, da sie sich im sprachspezifischen Unterordner im SharePoint Root befindet. In dieser Datei wird ein Template referenziert und eine oder mehrere von in der onet.xml spezifizierten Websitekonfigurationen publiziert. Diese Konfigurationen können dann im Erstellungsdialog für eine Website ausgewählt werden. Wichtig zu beachten ist, dass die ID des Templates eindeutig spezifiziert ist und man vorsichtig mit Umbenennungen umgeht, denn die Site Definition (onet.xml) muss auf dem Webserver in einem gleichnamigen Unterverzeichnis von SharePointRootSiteTemplates abgelegt werden. Ebenso muss die Datei webtemp_xxx.xml zwingend mit dem Präfix webtemp beginnen, da die Datei sonst nicht gefunden wird. Die drei wichtigsten Komponenten in der Datei Onet.xml sind NavBars (spezifiziert Topnavigation und Quicklaunch-Leiste), Configurations (eine Menge von Listen, Features und Modulen) sowie Modules (Module, die in den Konfigurationen verwendet werden. Module können Webseiteninhalte oder Dateien sein).

Im Abschnitt NavBars definiert man Navigationseinträge der Topnavigation und der Quicklaunch-Leiste auf der linken Seite. Es wird unterschieden zwischen den Elementen NavBar und NavBarLink, mit denen man eine zweistufige Navigationshierarchie abbilden kann. Listing 7 zeigt eine Beispielnavigation. Das Attribut ID des NavBar-Elements ist besonders wichtig, denn darüber steuert man, wo die Navigationseinträge erscheinen. Die ID 1002 ist fest vergeben für die Topnavigation. Alle darüber liegenden IDs bzw. NavBars werden auf der Quicklaunch-Leiste einsortiert. Das nachträgliche Ändern von Navigationseinträgen ist auch programmatisch möglich über SPNavigationNode-Objekte. In einer Site Definition können mehrere Konfigurationen hinterlegt werden. In den Konfigurationen wird spezifiziert, welche Listen und Bibliotheken angelegt werden, welche Features in der Website bzw. Websitesammlung aktiviert werden und welche Module verwendet werden. Listing 7 zeigt eine Site Definition (onet.xml), die eine Konfiguration enthält. In dieser werden eine Dokumentenbibliothek und eine Aufgabenliste spezifiziert sowie das Feature für Teamzusammenarbeitslisten, die Standardlisten für die Website bereitstellt. Ferner wird ein Modul verwendet, das die default.aspx-Seite als Startseite deployt. Welche Site Definition und wie viele Konfigurationen verwendet werden können, wird durch die Datei webtemp_xxx.xml definiert.

Obwohl auch hier die XML-Definition der Websitevorlagen sehr fehleranfällig sind und man häufig durch try and error das Ergebnis überprüfen muss, sind Site Definitions insgesamt eine sehr viel präzisere Variante für Websitevorlagen als die generierten Vorlagen über die SharePoint-Weboberfläche. Eine gute Erklärung der Elemente und Attribute in der onet.xml-Datei findet man hier.

 <?xml version="1.0" encoding="utf-8"?>
 <Project Title="SharePointPortalSite" Revision="2" ListDir="$Resources:core,lists_Folder;" xmlns:ows="Microsoft SharePoint">
   <NavBars>
     <NavBar Name="$Resources:core,category_Top;" Separator="&nbsp;&nbsp;&nbsp;" Body="<a ID='onettopnavbar#LABEL_ID#' href='#URL#' accesskey='J'>#LABEL#</a>" ID="1002" />

     <NavBar ID="1040" Name="Allgemein" Url="/default.aspx">
       <NavBarLink Name="Personen" Url="/Lists/Person/Personen.aspx"/>
       <NavBarLink Name="Ausweise" Url="/Lists/Ausweis/Ausweise.aspx"/>
     </NavBar>
   </NavBars>
   <Configurations>
     <Configuration ID="0" Name="Default">
       <Lists>
         <List Title="Vorlagen" Url="Vorlagen" Type="101" FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101"/>
         <List Title="Aufgaben" Type="107" Url="$Resources:core,lists_Folder;/Aufgaben" FeatureId="00BFEA71-A83E-497E-9BA0-7A5C597D0107" VersioningEnabled="TRUE" />
       </Lists>
       <Modules>
         <Module Name="DefaultBlank" />
       </Modules>
       <SiteFeatures>
         <!-- BasicWebParts Feature -->
         <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />
       </SiteFeatures>
       <WebFeatures>
         <!—TeamCollab Listen Feature -->
         <Feature ID="00BFEA71-4EA5-48D4-A4AD-7EA5C011ABE5" />
       </WebFeatures>
     </Configuration>
   </Configurations>
   <Modules>
     <Module Name="DefaultBlank" Url="" Path="">
       <File Url="default.aspx">
       </File>
     </Module>
   </Modules>
 </Project>

Zusammenfassung

Die vorgestellten Building Blocks lassen erahnen, welches Potenzial in der Entwicklungsplattform SharePoint stecken. Durch Kombination mehrerer dieser Bausteine lassen sich ganze Anwendungen auf Grundlage der SharePoint-Plattform implementieren. Da SharePoint-Entwicklung nicht trivial ist, sollte man unbedingt vertiefende Literatur wie [1] begleitend lesen. Erfahren Sie im letzten Teil der SharePoint-Entwicklungsserie, wie man diese Bausteine über Ribbons nahtlos in die SharePoint-Oberfläche integriert, Datenzugriffe über Clientanwendungen realisiert und programmatisch mit dem Benutzer- und Rechtemodell umgeht.

Literatur

[1] Bernd Pehlke, Jörg Krause, Christian Langhirt, Alexander Sterff, Martin Döring: „SharePoint 2010 as a Development Platform“, Apress, 2010

Aufmacherbild: Piled up pebbles on a brown background von Shutterstock / Urheberrecht: wavebreakmedia

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -