Webparts - Microsoft Press

Transcription

Webparts - Microsoft Press
Kapitel 4
Webparts
In diesem Kapitel:
쮿 Sie lernen den Unterschied zwischen der herkömmlichen ASP.NET-Entwicklung und der SharePointEntwicklung mit Webparts kennen.
쮿 Sie beschäftigen sich mit den Grundlagen der Webpartentwicklung, der Fehlersuche und Bereitstellung
für WSS.
쮿 Sie erfahren, wie persönliche Einstellungen und Anpassungen in Webparts erfolgen.
쮿 Sie erstellen verbindungsfähige Webparts.
쮿 Sie arbeiten im SharePoint-Websiteobjektmodell mit Webparts.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
113
114
Kapitel 4: Webparts
Webparts
Die Hauptaufgabe eines SharePoint-Entwicklers ist die Entwicklung von wiederverwendbaren Komponenten für Geschäftskunden. Die Geschäftskunden wiederum verwenden diese Komponenten zur Erstellung von Anwendungen, zur Anpassung der Anwendung an spezielle Aufgaben und zur Einstellung der
Anwendungen nach ihren persönlichen Vorlieben und Arbeitsweisen. Diese Vorgehensweise steht im
Gegensatz zur Entwicklung der typischen Windows- oder Websoftware, die normalerweise als geschlossene Einheit bereitgestellt wird. Mit der WSS-Technologie entwickelt sich eine Anwendung weiter, wenn
Geschäftskunden mit den bereitgestellten Komponenten ihre eigenen Anwendungen und Arbeitsbereiche
zusammenstellen. Webparts werden in der Website zur Verbesserung der Zusammenarbeit und der Integration der Anwendungen verwendet.
Webparts sind wichtige Grundbausteine der SharePoint-Benutzeroberfläche. Mit ihnen lassen sich viele
verschiedene Anwendungsarten erstellen. Die bereits vorhandenen Webparts können Ihnen als Beispiele
für die Entwicklung eigener Webparts dienen. Das DataViewWebpart lässt sich zum Beispiel so einstellen,
dass es Daten aus einer beliebigen geeigneten Datenquelle auf verschiedene Arten anzeigt. Die Webparts
aus dem Lieferumfang von WSS sind allgemein gehalten und für die Wiederverwendung vorgesehen.
Auch wenn Sie mit Webparts sehr spezielle Anwendungen erstellen, empfiehlt es sich, die Webparts so
allgemein anwendbar wie möglich zu halten, um Kunden, die Webparts für eine spezielle Aufgabe verwenden, die größtmögliche Flexibilität zu bieten.
Integrierte Webparts
WSS wird mit einer ganzen Reihe von Webparts geliefert, die Ihre Anforderungen vielleicht schon erfüllen können. Die Webpartausstattung von Microsoft Office SharePoint Server ist noch umfangreicher.
Um Ihre Anwendung in SharePoint-Websites zu integrieren, ist es nicht immer erforderlich, Programmcode zu schreiben. Das gilt besonders für Geschäftsdaten. Es gibt viele Microsoft-Webparts, die sich
unter Verwendung der Webpartdateien bereitstellen und anpassen oder in anderen Webparts als Websteuerelemente (WebControls) einsetzen lassen. Die folgenden Webparts stellen nur eine Auswahl dar:
Inhalts-Editor-Webpart Verwenden Sie dieses Webpart zur Anzeige von statischen HTML-Inhalten
mit einem WYSIWYG-Editor oder zur Darstellung einer Textdatei.
DataViewWebpart Zur Anzeige von Datenbanken, XML oder SharePoint-Listendaten mit umfangreicher Designunterstützung durch den Microsoft SharePoint Designer.
Listen-Viewer-Webpart Zur Anzeige von Listendaten aus allen Listen der SharePoint-Website.
Bildwebpart Verwenden Sie dieses Webpart zur Anzeige eines Bilds.
Websitebenutzer-Webpart Verwenden Sie dieses Webpart zur Anzeige der Mitglieder einer Website.
Seiten-Viewer-Webpart Verwenden Sie dieses Webpart zur Anzeige einer vorhandenen Webseite in
einem IFrame.
Grundlagen der Webparts
Ein Webpart ist eine Klasse, die von der im Namespace System.Web.UI.WebControls.WebParts definierten
Klasse WebPart aus der Assembly System.Web abgeleitet wird. Das Webpart ist eine spezielle Art von
Websteuerelement, das innerhalb eines Webpartzonensteuerelements verwendet werden kann, nachdem
die betreffende Seite erstellt und bereitgestellt wurde. Ein Webpart ist lose mit der Seite verbunden, auf
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
115
Webparts
der es verwendet wird, sofern die Webpartinfrastruktur installiert und funktionsfähig ist. (Informationen
über die Erstellung von benutzerdefinierten Webpartseiten finden Sie in Kapitel 3, »Seiten und Design«.)
Webparts arbeiten mit einem WebPartManager-Steuerelement zusammen, das die Webpartinstanzen
entweder beim Entwurf der Seite oder zur Laufzeit zu den Webpartzonen hinzufügt und verwaltet. Der
Webpartmanager verwaltet die Seite und fügt bei der Initialisierung der Seite Webparts aus der Personalisierungsdatenbank zu den Webpartzonen hinzu. Sie können auch außerhalb von SharePoint in herkömmlichen ASP.NET-Anwendungen Webparts erstellen, aber das Webpartframework von WSS 3.0
bietet umfangreiche zusätzliche Funktionen, wie zum Beispiel ein dynamisches SharePoint-Websitemodell, ein Templateframework, ein Sicherheitsframework und die Webpartverwaltung in der WSSWebpartgalerie. Abbildung 4.1 stellt die Vererbung zwischen den Webpartzonen- und Webpartmanagersteuerelementen von SharePoint und den Webpartframeworkklassen von ASP.NET dar. Beachten Sie
bitte, dass Sie die Webpartklassen von ASP.NET als Basisklassen für Ihre Webpartanwendungen verwenden, obwohl SharePoint ebenfalls Implementierungen der Webpartzone und des Webpartmanagers enthält.
Abbildung 4.1
Die SharePoint-Implementierung des Webpartframeworks
SharePoint verwendet die Webpartmanagerklasse SPWebPartManager, die man sich als Brücke zwischen
den Webpartzonenobjekten der Seite und der Inhaltsdatenbank vorstellen kann. Wenn Sie ein Webpart
zu einer Seite hinzufügen, dann fügen Sie eine serialisierte Instanz des Webparts zur Inhaltsdatenbank
hinzu. Sie können in Modulen von Features auch Standardwebparts deklarieren und zu Seiten hinzufügen, wie im vorigen Kapitel gezeigt. Um ein einfaches Webpart zu entwickeln, leiten Sie von System.Web.
UI.WebControls.WebParts.WebPart eine neue Klasse ab. Wenn Sie in einer Seite Text oder HTML anzeigen möchten, überschreiben Sie einfach die Methode RenderContents. Dabei verwenden Sie dieselbe
Syntax, die Sie bei der Erstellung eines einfachen Websteuerelements für eine ASP.NET-Anwendung
verwenden.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
116
Listing 4.1
Kapitel 4: Webparts
Ein sehr einfaches Webpart
namespace LitwareWebParts {
// Ein sehr einfaches Webpart
public class HelloWebPart : System.Web.UI.WebControls.WebParts.WebPart {
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer) {
writer.Write(string.Format("Hallo, {0}!", this.Page.User.Identity.Name));
}
}
}
Webparts werden in einem Anzeigerahmen angezeigt, der auch Chrome genannt wird. Damit sind die
allgemeinen Benutzeroberflächenelemente gemeint, wie eine formatierte Titelleiste und die Rahmen um
den Körper des Webparts, den das Framework zu Steuerelementen hinzufügt. Dieser Anzeigerahmen
gibt Ihrem Webpart ein gewisses Format, das zur restlichen Benutzeroberfläche der Anwendung passt.
Die Anzeige des Rahmens wird vom Anwendungsframework übernommen. Wenn dieses Webpart in
WSS bereitgestellt wird, erfolgt die Anzeige mit dem Titel des Webparts und einem Dropdownmenü mit
Anpassungsoptionen. Der Webpartrahmen ist für die Anzeige der allgemeinen Eigenschaften und Stilvorgaben, des Menüs und der Verwaltungsoberflächenelemente zuständig. Abbildung 4.2 zeigt, wie der
Anzeigerahmen für das HelloWebPart-Beispiel aussieht. Beachten Sie bitte, dass der Anzeigerahmen nur
dann vom Webpartframework angezeigt wird, wenn Webparts in Webpartzonen bereitgestellt werden. Er
wird nicht angezeigt, wenn das Webpart deklarativ als Websteuerelement bereitgestellt wird.
Abbildung 4.2
Auch das einfachste Webpart wird mit einem Anzeigerahmen (auch Chrome genannt) angezeigt
Da der Anzeigerahmen vom Anwendungsframework angezeigt wird (in unserem Fall also von WSS),
lassen sich Anwendungen, die aus mehreren Webparts zusammengestellt werden, leicht und ohne zusätzliche Trainingskosten oder Lernkurven von Benutzern des Portals warten. Sobald die Benutzer gelernt
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
117
Webparts
haben, wie man Webparts mit dem Toolbereich von SharePoint hinzufügt oder entfernt, können sie auch
Anwendungen verwenden, die als Webparts für sie bereitgestellt werden.
Grundlagen der Websteuerelemente
Da es sich bei Webparts um WebControl-Klassen handelt, ist für die Programmierung von Webparts ein
gewisses Grundlagenwissen über Websteuerelemente erforderlich. Websteuerelemente gehören ebenfalls
zu den Komponenten der Benutzeroberfläche, die Sie in Ihren Webpartlösungen verwenden können, ob
Sie nun eigene Websteuerelemente schreiben oder die Standardelemente von ASP.NET oder von SharePoint verwenden, wie zum Beispiel das SPGridView-Steuerelement. Abbildung 4.3 zeigt das Webpartklassenmodell. Die Klasse WebPart wird vom Panel-Websteuerelement abgeleitet und implementiert die
Schnittstelle IWebEditable, die eine Bereitstellung und Anpassung im Webpartframework ermöglicht. Sie
können in Ihrem eigenen benutzerdefinierten Webpart auch Webparts als Steuerelemente einsetzen,
einschließlich der WSS-Webparts von Microsoft.
Abbildung 4.3
von ASP.NET
Das WebPartklassenmodell
HINWEIS
Webparts für die SharePoint-Bereitstellung werden von der Klasse System.Web.UI.WebControls.WebParts.
WebPart abgeleitet. Sie können in ASP.NET 2.0 zwar ein Benutzersteuerelement (.ascx-Datei) als Webpart verwenden (mit
GenericWebPart als Verpackung), aber das GenericWebPart ist in SharePoint nicht zur Bereitstellung geeignet. SharePoint ist
restriktiver als ASP.NET 2.0, weil Sie keine Benutzersteuerelemente direkt als Webparts verwenden können. Stattdessen
müssen Sie eine indirekte Methode verwenden, bei der Sie eine Art Verpackungswebparts (wrapper web parts) schreiben,
die dynamisch Benutzerelemente laden und aufnehmen. Wenn Sie herausfinden möchten, wie weit Sie diese Idee weiterentwickeln können, lesen Sie die Informationen über das Smart Part (http://www.SmartPart.info), das von Jan Tielens
berühmt gemacht wurde.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
118
Kapitel 4: Webparts
Es gibt einige Methoden, die für die Lebensdauer eines Steuerelements im Speicher des Computers entscheidend sind. OnLoad dient zwar zur Initialisierung des Steuerelements, ist aber nicht dafür vorgesehen, Daten zu laden oder andere Funktionen zu übernehmen. OnPreRender wird zur Einleitung von
Vorgängen verwendet, die etwas länger dauern, wie zum Beispiel Datenbankabfragen oder asynchrone
Aufrufe von Webdiensten. Die Page-Klasse meldet zudem ein PreRenderComplete-Ereignis, wenn alle
Anzeigevorarbeiten der Seite abgeschlossen sind. Wenn Sie für die Anzeige Steuerelemente verwenden,
ist CreateChildControls die einzige Methode, die Sie für die Benutzeroberflächenkomponenten zu implementieren brauchen. Die Anzeige der Steuerelemente aus der Steuerelementsammlung des Websteuerelements wird vom Framework gesteuert. Normalerweise brauchen Sie also keine Ausgabemethoden zu
überschreiben, sofern Sie nicht direkt mit der HtmlTextWriter arbeiten müssen. Wenn Sie Ihre eigenen
Steuerelemente selbst anzeigen müssen, können Sie das in der Methode RenderContents tun. Die Anzeige
erfolgt dann im Anzeigerahmen (Chrome) des Websteuerelements. Vielleicht möchten Sie Ihre Steuerelemente auch wegen spezieller Anforderungen selbst anzeigen, beispielsweise zur Anzeige in einer Tabelle
oder in einem anderen HTML-Layout. Um Postbackdaten aus einem enthaltenen Steuerelement annehmen zu können, müssen Sie einen privaten Verweis auf Ihr Steuerelement erstellen und es in der Methode
CreateChildControls erstellen. Vor dem Zugriff auf das Steuerelement können Sie mit dem Aufruf der
Methode EnsureChildControls dafür sorgen, dass es existiert. Tabelle 4.1 beschreibt den Lebenszyklus
eines Webparts in Form des Ablaufs der Methodenaufrufe, wobei auch die Standardmethoden und Ereignisse bei der Erstellung von Webparts aufgeführt sind. Allerdings gibt es noch einige Methoden, deren
Aufruf sich nicht in einen genau definierten Ablauf einordnen lässt. Dazu gehören CreateChildControls,
EnsureChildControls und Methoden, die mit den Attributen ConnectionConsumer und ConnectionProvider
gekennzeichnet sind. Bevor Sie auf die Eigenschaften zusammengesetzter Steuerelemente zugreifen, muss
die Methode EnsureChildControls aufgerufen werden, um Ausnahmen durch Nullverweise zu vermeiden.
Tabelle 4.1
Der Lebenszyklus eines Webparts
Methode/Ereignis
Beschreibung
OnInit
Übernimmt die Initialisierung des Steuerelements.
OnLoad
Wird beim Load-Ereignis aufgerufen.
CreateChildControls
Erstellt alle untergeordneten Steuerelemente, die zu den Bestandteilen eines zusammengesetzten Steuerelements gehören.
EnsureChildControls
Sorgt dafür, dass CreateChildControls ausgeführt wurde. Verwenden Sie diese Methode, um vor dem Zugriff auf die Daten eines Steuerelements sicherzustellen, dass das Steuerelement existiert.
OnPreRender
Führt Arbeiten durch oder leitet sie ein, die vor der Anzeige eines Steuerelements erledigt werden müssen,
wie zum Beispiel das Laden von Daten. Asynchrone Arbeiten an der Seite sollten in dieser Methode eingeleitet werden.
Page.PreRenderComplete Die Seite meldet das Ereignis PreRenderComplete, sobald alle Steuerelemente ihre OnPreRender-Methoden
abgeschlossen haben und die Seite alle asynchronen Arbeiten abgeschlossen hat.
Render
Zeigt das gesamte Steuerelement an, einschließlich äußerer Tags und Anzeigerahmen (Chrome).
RenderContents
Zeigt nur den Inhalt des Steuerelements an, innerhalb der äußeren Tags und Style-Eigenschaften.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
Webparts
119
SharePoint- und ASP.NET-Entwicklung im Vergleich
Da SharePoint-Anwendungen in einem virtualisierten Websitekontext ausgeführt werden, in dem auch
die Inhaltsdatenbank eine wichtige Aufgabe hat, ergeben sich einige wichtige Unterschiede zur herkömmlichen ASP.NET-Entwicklung und einige Anforderungen an das ASP.NET-Framework, die vielleicht nicht
offensichtlich sind. Webparts, die innerhalb von Webpartzonen zu Seiten hinzugefügt werden, existieren
vollständig in der Inhaltsdatenbank. Das bedeutet, dass sie vom SharePoint-Parser für den sicheren Modus
bearbeitet werden. Außerdem werden Webparts im Lebenszyklus einer Seite später als deklarative Steuerelemente zur Seite hinzugefügt. Webpartanwendungen für WSS sollten vollständig in einer kompilierten
Assembly vorliegen, ohne zusätzliche dynamisch kompilierten Codedateien im app_code-Ordner, wie es
herkömmlichen ASP.NET 2.0-Anwendungen zulassen. Webpartanwendungen sollten so eigenständig wie
möglich sein. Die erforderlichen Ressourcen wie Bilder und Skripts sollten als Ressourcen in die Assembly
kompiliert und mit dem Clientskriptmanager (Client Script Manager) eingefügt werden. Außerdem werden Webpartanwendungen für WSS unter bestimmten Sicherheitseinstellungen ausgeführt und sollten
durch Lösungspakete bereitgestellt werden, damit die korrekten Vertrauenseinstellungen vorgenommen
werden. Während der Entwicklung müssen Sie die Vertrauenseinstellung (trust level) in der web.configDatei der Website vermutlich auf WSS_Medium oder Full erhöhen. Vertrauenseinstellungen und Sicherheitsrichtlinien werden in Kapitel 9, »Projekte und Bereitstellung«, ausführlicher besprochen.
TIPP
Sicherheitsausnahmen durch die Ausführung des Codes mit einer zu restriktiven Codezugriffssicherheitseinstellung (Code Access Security) sind in Webpartanwendungen eine häufige Fehlerursache.
Der Parser für den sicheren Modus
Die Codebereitstellung aus der Inhaltsdatenbank erfolgt durch den Parser für den sicheren Modus (Safe
Mode Parser). Der Parser für den sicheren Modus sorgt dafür, dass nur Code, der als vertrauenswürdig
konfiguriert wurde, dynamisch auf dem SharePoint-Server bereitgestellt werden kann. Ohne den Parser
für den sicheren Modus könnten Benutzer in dynamischen Webseiten, die als Dokumente erstellt werden, bösartigen Code einfügen und dadurch die Datenintegrität und Sicherheit der SharePoint-Website
gefährden. Die Bereitstellung von Code, der nicht vom Parser für den sicheren Modus überprüft wird,
erfordert physischen Zugang zum Dateisystem des Webservers, wie bei der in Kapitel 2 beschriebenen
Bereitstellung von benutzerdefinierten Anwendungsseiten. Der Parser für den sicheren Modus garantiert, dass der Code, der in der SharePoint-Anwendung ausgeführt wird, vom Serveradministrator genehmigt wurde.
Webparts wurden erstmals in WSS 2.0 als nächste Version der Microsofts Dashboard-Technologie eingeführt. ASP.NET 2.0 enthält eine neue Version des Webpartframeworks, die außerhalb von WSS mit
ASP.NET-Standardkomponenten benutzt werden kann. Das Webpartframework von WSS 3.0 setzt auf
demselben Webpartframework auf. Um ein Webpart für SharePoint zu entwickeln, leiten Sie von der
ASP.NET-Webpartklasse System.Web.UI.WebControls.WebParts.WebPart eine neue Klasse ab. Aus Gründen der Abwärtskompatibilität gibt es in WSS 3.0 auch noch die Webpartklasse Microsoft.SharePoint.WebPartPages. Diese Klasse sollte nur bei der Umstellung von vorhandenem WSS 2.0-Code auf WSS 3.0 verwendet werden. Diese Klasse wird von der ASP.NET-Klasse WebPart abgeleitet und enthält mehrere
Kompatibilitätsschichten, um die Codeübernahme zu erleichtern. Sie ist nicht für Neuentwicklungen
vorgesehen. Tabelle 4.2 beschreibt Eigenschaften, Methoden und Komponenten der ASP.NET-Webparts
sowie die entsprechende abwärtskompatible Eigenschaft, Methode oder Komponente aus dem Namespace.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
120
Kapitel 4: Webparts
SharePoint.WebPartPages. Ein weiterer wichtiger Unterschied ist, dass ASP.NET-Webparts und abwärtskompatible SharePoint-Webparts unterschiedliche Serialisierungsformate verwenden. Eine Änderung in
der Basisklasse kann also dazu führen, dass bereitgestellte Webparts nicht mehr richtig funktionieren.
Tabelle 4.2
Vergleichstabelle zur WSS-Abwärtskompatibilität
ASP.NET-Webparts
SharePoint-Abwärtskompatibilität
WebBrowsableAttribute
BrowsableAttribute
WebDisplayName
FriendlyName
WebDescription
Description
Personalizable
WebPartStorage
PersonalizationScope
Storage
EditorPart
ToolPart
EditorPartCollection
ToolPart[]
CreateEditorParts()
GetToolParts()
RenderContents()
RenderWebPart()
SetPersonalizationDirty() SaveProperties
Entwickeln von Webparts für WSS 3.0
Bei der Entwicklung einer Webpartanwendung für WSS beginnen Sie in Visual Studio 2005 eine neue
Klassenbibliothek und nehmen einen Verweis auf System.Web auf. Um das SharePoint-Websiteobjektmodell verwenden zu können, nehmen Sie Verweise auf die primäre WSS-Assembly Microsoft.SharePoint.dll und auf Microsoft.SharePoint.Security.dll ins Projekt auf. Um die Webpartassembly im Ordner
bin mit einem starken Namen bereitstellen zu können, müssen Sie auch das Assemblyattribut AllowPartiallyTrustedCallers verwenden. Dieses Attribut muss einmal in die Assembly aufgenommen werden und
wird gewöhnlich in der Codedatei AssemblyInfo angegeben.
[assembly: System.Security.AllowPartiallyTrustedCallers]
Erstellen Sie nun Ihr erstes Webpart, indem Sie von WebPart eine Klasse ableiten und die Methode CreateChildControls überschreiben. Weil das ASP.NET-Framework automatisch die Anzeige der Steuerelemente
aus der Sammlung übernimmt, brauchen Sie gewöhnlich nur in dieser Methode Steuerelemente und
Handler hinzuzufügen, um die gewünschte Benutzeroberfläche zusammenzustellen. In den folgenden
Beispielen erstellen Sie ein einfaches RSS-Anzeigewebpart, ein Webpart zur Auswahl eines RSS-Feeds
und ein Editorwebpart. Der Code aus Listing 4.2 zeigt das übliche simple »HelloWorld«-Beispiel, das Sie
zum RSS-Anzeigewebpart umbauen. Das resultierende Webpart ist relativ komplex. Daher ist es wichtig
und sinnvoll, das Webpart schon während der Entwicklung zu testen. Dazu beginnt man am besten mit
einem ganz einfachen Grundgerüst.
Zur Bereitstellung des Webparts in Ihrer WSS-Website müssen Sie das Steuerelement im Knoten SafeControls der Datei web.config als sicheres Steuerelement registrieren, wie in Kapitel 3 beschrieben. Wenn
das Projekt LitwareWebParts heißt, wird die Assembly und der Namespace durch folgenden SafeControlKnoten in web.config als sicher registriert:
<SafeControl Assembly="LitwareWebParts" Namespace="LitwareWebParts" TypeName="*" Safe="True" />
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
121
Webparts
Listing 4.2
Die ersten Schritte in der Webpartentwicklung
Es geht los: ein RSS-Webpart
using
using
using
using
using
System;
System.Web;
System.Web.UI;
System.Web.UI.WebControls;
System.Web.UI.WebControls.WebParts;
namespace LitwareWebParts {
public class RssViewWebPart : WebPart {
protected override void CreateChildControls() {
base.CreateChildControls();
this.Controls.Add(new LiteralControl("Hello, world!"));
}
}
}
Beachten Sie bitte, dass wir der Assembly in diesem Beispiel keinen starken Namen geben und daher den
einfachen Assemblynamen verwenden können. Wenn Sie der Assembly einen starken Namen geben,
müssen Sie im SafeControl-Eintrag den vollständigen vierteiligen Assemblynamen angeben.
Dann kompilieren Sie das Projekt zur Assembly-DLL (Dynamic Link Library) und kopieren die DLL ins
bin-Verzeichnis Ihrer SharePoint-Webanwendung. Viele Entwickler tun dies beim Postbuildereignis von
Visual Studio oder als benutzerdefinierte MSBuild-Aufgabe, wie im folgenden Beispiel:
xcopy /Y *.* C:\Inetpub\LitwareWebApp\bin\*.*
Im nächsten Schritt nach dem Hinzufügen des SafeControl-Eintrags testen Sie das Webpart, indem Sie es
in den Katalog aufnehmen und zu einer Webpartseite hinzufügen. Zur Bereitstellung eines Webparts
bieten sich viele Wege an, aber während der Entwicklung werden Sie dies meistens manuell tun. Um das
Webpart in den Katalog aufzunehmen, wechseln Sie in Ihrer Website zu folgendem URL: http://localhost/
_catalogs/wp. Dieser Katalog ist auch über die Seite Websiteeinstellungen der Website auf der obersten
Ebene zugänglich. Wechseln Sie von dieser Seite aus durch einen Klick auf die Schaltfläche Neu zur Seite
http://localhost/_layouts/NewDwp.aspx. Auf dieser Seite werden alle Webparts aufgelistet, die im binVerzeichnis oder im globalen Assemblycache verfügbar sind und im SafeControls-Abschnitt der Webanwendung registriert wurden. Falls Sie Ihr Webpart nicht auf dieser Seite vorfinden, wird es Zeit für die
Fehlersuche. Überprüfen Sie zum Beispiel, ob Ihr Webpart öffentlich (public) ist, von der Klasse WebPart
abgeleitet wird, mit dem vollständigen Namespace und dem richtigen Assemblynamen als sicher registriert ist und im richtigen Ordner bereitgestellt wird. Wenn Ihre Webpartassembly signiert ist, sorgen Sie
dafür, dass im SafeControls-Eintrag der korrekte starke Name angegeben wird. Abbildung 4.4 zeigt die
Seite Neue Webparts, in der Sie mit der Webschnittstelle neue Webpartkatalogeinträge vornehmen können.
TIPP
Der Webpartkatalog (eine andere Bezeichnung ist Webpartgalerie) ist eine spezielle Dokumentbibliothek, die
XML-Dateien mit serialisierten Webparts enthält. Die Namenserweiterung der Webparts, die im neuen ASP.NET-Format
serialisiert wurden, lautet .webpart, während abwärtskompatible Webparts im älteren WSS 2.0-Format serialisiert werden
und die Dateinamenserweiterung .dwp tragen.
Wenn Sie auf der Seite Neue Webparts ein Webpart auswählen und auf die Schaltfläche Katalog auffüllen
klicken, nimmt WSS im Webpartkatalog der Websitesammlung einen neuen Eintrag vor. Anschließend
ist das Webpart auf allen Seiten verfügbar und lässt sich nach dem Menübefehl Seite bearbeiten mit der
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
122
Kapitel 4: Webparts
Option Webpart hinzufügen zur Webpartseite hinzufügen. Nachdem das Webpart zur Seite hinzugefügt
wurde, können Sie es als XML-Webpartdatei (.webpart) exportieren. Das ist besonders nützlich, wenn Sie
vor der Bereitstellung Standardeigenschaften festlegen möchten. Dieser XML-Inhalt ist es, den Sie verwenden können, wenn Sie Ihr Webpart zu einer Website oder zu Featuredefinitionsseiten hinzufügen.
Oder Sie verwenden den XML-Code, mit dem Ihr Webpart in die Inhaltsdatenbank serialisiert wird.
Außerdem können Sie diese XML-Datei in Ihr Visual Studio-Projekt und in die Quellcodeverwaltung
aufnehmen, damit Sie ein Feature erstellen können, das die Webpartkatalogeinträge automatisch importiert. Listing 4.3 zeigt eine (gekürzte) Webpartbeispieldatei, die aus unserem einfachen RSS-Anzeigewebpartgerüst generiert wurde.
Abbildung 4.4 Die Seite Neue Webparts zeigt Webparts an, die als sicher gekennzeichnet wurden; auf ihr können Webparts zum
Webpartkatalog der aktuellen Websitesammlung hinzugefügt werden
Listing 4.3
Ein Beispiel für eine Webpartbeschreibungsdatei
Eine Webpartbeispieldatei
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="LitwareWebParts.RssViewWebPart" />
<importErrorMessage>Fehler beim Import des Litware-Webparts.</importErrorMessage>
</metaData>
<data>
<properties>
<!-- Webpart-Standardeigenschaften -->
<property name="ChromeType" type="chrometype">Default</property>
<property name="Title" type="string">Litware-RSS-Anzeigewebpart</property>
<property name="Description" type="string">Zur Erstellung von RSS-Feeds für jede Quelle</property>
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
123
Webparts
<property name="CatalogIconImageUrl" type="string">
/_layouts/images/msxmll.gif
</property>
<property name="AllowConnect" type="bool">True</property>
<property name="ExportMode" type="exportmode">All</property>
<!-- Benutzerdefinierte Webparteigenschaften -->
<property name="XmlUrl" type="string">
http://blogs.msdn.com/MainFeed.aspx?Type=AllBlogs
</property>
</properties>
</data>
</webPart>
</webParts>
Erstellen eines Features für den Import von Webparts
Wenn Sie Webparts für den Vertrieb vorbereiten, empfehlen wir, ein Feature zu erstellen, mit dem sich
Ihre .webpart-Dateien in den Webpartkatalog importieren lassen. Da es in jeder Websitesammlung nur
einen Webpartkatalog gibt, sollte ein Feature für den Import von .webpart-Dateien auf der Ebene der
Websitesammlung erstellt werden, also nicht nur für eine bestimmte Website gelten. Das folgende Beispiel
zeigt eine feature.xml-Datei für ein Feature namens LitwareWebParts, das Sie auch im Visual Studio-Beispielprojekt dieses Kapitels finden.
<Feature
Id="FE016E00-8639-4839-925D-B40F659458A9"
Title="Kapitel 4: Ein Beispielfeature für die Bereitstellung von Litware-Webparts"
Description="Demo aus Windows SharePoint Services 3.0-Programmierung (Pattison/Larson)"
Hidden="FALSE"
Scope="Site"
ImageUrl="actionssettings.gif"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
</ElementManifests>
</Feature>
Wenn ein Feature für den Import von Webparts bereitgestellt werden soll, müssen die eigentlichen .webpart-Dateien auf das Dateisystem des Frontend-Webservers kopiert werden. Dabei sollten Sie Ihre .webpart-Dateien in den Featureordner kopieren. Im Feature LitwareWebParts haben wir uns an eine MicrosoftKonvention gehalten und unsere .webpart-Dateien in einem Unterordner namens DWP des Featureordners
gespeichert.
Nachdem Sie Ihre .webpart-Dateien in den Featureordner kopiert haben, aktualisieren Sie die Datei Elements.xml, indem Sie in einem Module-Element die erforderlichen File-Elemente angeben, wie im folgenden Beispiel. Dadurch werden die Dateien bei der Aktivierung des Features in den Webpartkatalog
der aktuellen Websitesammlung kopiert. Beachten Sie bitte, dass ein Module-Element, das für einen Webpartkatalog vorgesehen ist, mit dem Listentyp 113, dem Url-Wert »_catalogs/wp« und der RootWebOnlyEinstellung true definiert werden muss.
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="LitwareWebParts" Path="dwp"
List="113" Url="_catalogs/wp" RootWebOnly="true">
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
124
Kapitel 4: Webparts
<File Url="HelloWebPart.webpart" Type="GhostableInLibrary" >
<Property Name="Group" Value="Litware-Webparts" />
</File>
<File Url="RssViewWebPart.webpart" Type="GhostableInLibrary" >
<Property Name="Group" Value="Litware-Webparts" />
</File>
<File Url="FeedListWebPart.webpart" Type="GhostableInLibrary" >
<Property Name="Group" Value="Litware-Webparts" />
</File>
</Module>
</Elements>
Beachten Sie bitte in diesem Listing der Datei elements.xml, dass jedes File-Element für eine .webpartDatei über ein inneres Property-Element verfügt, das eine Group-Eigenschaft mit dem Wert »LitwareWebparts« hinzufügt. Der Wert der Eigenschaft Group muss in dieser Weise innerhalb des File-Elements
festgelegt werden. Das ist anfangs ein wenig verwirrend, weil man die Group-Eigenschaft nicht wie andere
Webparteigenschaften in der .webpart-Datei festlegen kann, wie zum Beispiel Title oder Description.
Allerdings ist die Group-Eigenschaft für Benutzer eine Orientierungshilfe, weil Ihre Webparts dann im
WSS-Standarddialog Webparts hinzufügen zu benutzerdefinierten Gruppen zusammengefasst werden
(Abbildung 4.5).
Abbildung 4.5 Wenn Sie ein Feature für
den Import eines Webparts zum Webpartkatalog vorgesehen haben, kann ein Benutzer das Webpart leicht zu Webpartseiten
hinzufügen
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
Webparts
125
Sie haben zwar gerade gesehen, wie man ein Feature für den Import von .webpart-Dateien in den Webpartkatalog erstellt, aber damit ist die Bereitstellung von Webparts in einer Produktivumgebung noch
nicht abgeschlossen. Allerdings müssen Sie noch bis Kapitel 9 warten, um mehr zu erfahren, wenn wir
Lösungspakete vorstellen und die noch fehlenden Teile einfügen. Wie Sie dann sehen, kann ein Lösungspaket automatisch Webpart-Assembly-DLLs und dazugehörige Features bereitstellen, um die .webpartDateien zu importieren. Ein Lösungspaket kann auch zur Bereitstellung anderer Webpartdateien
verwendet werden, wie zum Beispiel Benutzersteuerelemente, und um die erforderlichen SafeControlEinträge in den web.config-Dateien der verschiedenen Frontend-Webserver einer Farm vorzunehmen.
Außerdem verwenden wir das Lösungspaket in Kapitel 9, um die erforderlichen Codezugriffsicherheitsrichtlinien und Konfigurationen festzulegen, damit unsere Webparts in Umgebungen verwendet werden
können, die zumindest zum Teil vertrauenswürdig sind. Weitere Änderungen an der web.config-Datei
können mit Featureempfängern durchgeführt werden, die mit der Klasse SPWebConfigModification im
Projekt bereitgestellt werden.
Debuggen von Webparts
Das Debuggen von Webparts ist eine wichtige Fertigkeit. Zum Glück unterscheidet es sich nicht sehr
vom Debuggen herkömmlicher ASP.NET-Anwendungen. Der wichtigste Unterschied besteht darin, dass
Sie in Visual Studio nicht F5 drücken, sondern eine Verbindung mit dem w3wp.exe-Prozess auf dem
Windows-Server herstellen. Um in Visual Studio 2005 eine Verbindung mit dem Prozess herzustellen,
drücken Sie STRG+ALT+P oder wählen im Menü Debuggen den Befehl An den Prozess anhängen. Bei
der Entwicklung von Webparts für WSS ist es wichtig, auf dem Entwicklungscomputer, auf dem Visual
Studio installiert ist, Windows Server zu verwenden und WSS zu installieren. Um die .dll- und .pdbDateien ins bin-Verzeichnis zu kopieren, können Sie ein Postbuildereignis verwenden. Anschließend
können Sie den Debugger an den Zielprozess anhängen. In einer Webpartanwendung für SharePoint
können viele Dinge schiefgehen. Die Codeausführung Schritt für Schritt zu überprüfen gehört daher
zum Programmiereralltag.
TIPP
Wenn Sie als Desktopbetriebssystem keine Serverumgebung zur Verfügung haben, können Microsoft Virtual PC
oder Microsoft Virtual Server eine brauchbare Alternative für die Entwicklung sein, allerdings zum Preis einer deutlich spürbaren Leistungseinbuße.
Anpassung und Personalisierung
Durch die Möglichkeit zur Anpassung und Personalisierung von Webparts lassen sich Webparts in vielen
Anwendungen wiederverwenden. Mit Anpassung sind Änderungen gemeint, die für alle Benutzer der
Webpartinstanz gelten, während mit Personalisierung die persönlichen Einstellungen gemeint sind, die
ein Benutzer an einem Webpart vornimmt und die nur für diesen Benutzer gelten. Der Besitzer einer
Website könnte zum Beispiel festlegen, dass auf der Stammseite der Website ein bestimmter Newsfeed
angezeigt werden soll. Das wäre eine Anpassung, weil diese Änderung für alle Benutzer der Website
sichtbar wird. Einzelne Benutzer der Websites stellen vielleicht andere Anzeigeformate ein, die sie bevorzugen. Das wäre ein Beispiel für eine Personalisierung. Personalisierungen gelten für einzelne Benutzer
und werden auf Benutzerbasis gespeichert.
TIPP
Der Leistungsbedarf einer Anwendung ist für Personalisierungen höher als für Anpassungen und sollte in der
Planung entsprechend berücksichtigt werden.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
126
Kapitel 4: Webparts
Um eine neue Eigenschaft hinzuzufügen, fügen Sie eine öffentliche Eigenschaft ein und geben das Attribut Personalizable an. Auch die Attribute WebBrowsable, WebDisplayName, WebDescription und Category
sind zur Verwaltung der Eigenschaft im Editorpart des Webparts von Nutzen. Diese Attribute werden in
den Namespaces System.Web.UI.WebControls.WebParts und System.ComponentModel definiert.
Wenn Sie eine Eigenschaft definieren und das Attribut WebBrowsable angeben, zeigt das Webpartframework diese Eigenschaft automatisch in einem allgemeinen Standardeditorpart an, wenn der Benutzer den
Befehl Webpart bearbeiten wählt. Ein Editorpart ist ein spezielles Steuerelement, das zur Bearbeitung von
Webparteigenschaften verwendet wird, die anpassbar und personalisierbar sind. Das folgende Beispiel
fügt eine Webparteigenschaft namens XmlUrl hinzu.
private string xmlUrl;
[ Personalizable(PersonalizationScope.Shared),
WebBrowsable(true),
WebDisplayName("Feed-Url"),
WebDescription("Geben Sie hier die XML-URL Ihres RSS-Feeds an!"),
Category("Konfiguration")]
public string XmlUrl {
get { return xmlUrl; }
set { xmlUrl = value; }
}
Das Attribut Personalizable weist den Webpartmanager an, den Wert der Eigenschaft XmlUrl im Webpartframework zu speichern. In WSS wird der Wert in der Inhaltsdatenbank gespeichert. Da der Gültigkeitsbereich der Personalisierung auf Shared eingestellt wird, unterstützt die XmlUrl-Eigenschaft Anpassungen auf Websitebasis durch den Websitebesitzer, aber keine benutzerspezifischen Personalisierungen.
Die anderen Attribute der Eigenschaft bedeuten, dass die Eigenschaft im Editorpart mit einem bestimmten Anzeigenamen angezeigt wird, über eine Beschreibung für ein QuickInfo verfügt und einer Kategorie
zugeordnet wird. Ohne zusätzlichen Code wird die XmlUrl-Eigenschaft im SharePoint-Arbeitsbereich
von einem Standardeditorpart angezeigt.
Erstellen wir nun eine zweite Eigenschaft namens HeadlineMode, die eine Personalisierung zulässt. Das
erreichen wir durch die Angabe des PersonalizationScope-Werts User statt Shared. Dadurch ist jeder Benutzer unseres Webparts in der Lage, zwischen zwei unterstützten Anzeigemodi zu wechseln. Die Werte
der HeadlineMode-Eigenschaft werden durch die Werte der benutzerdefinierten Enumeration RenderMode
definiert:
public enum RenderMode {
Full,
Titles
}
Nachdem wir die Enumeration RenderMode definiert haben, können wir mit folgendem Code eine neue
personalisierbare Eigenschaft mit einer privaten Variablen definieren, in der ihr Wert gespeichert wird:
private RenderMode headlineMode = RenderMode.Full;
[Personalizable(PersonalizationScope.User),
WebBrowsable(true),
WebDisplayName("Schlagzeilenmodus"),
WebDescription("Sollen nur Schlagzeilen angezeigt werden?"),
Category("Konfiguration")]
public RenderMode HeadlineMode {
get { return headlineMode; }
set { headlineMode = value; }
}
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
127
Webparts
Beide Eigenschaften XmlUrl und HeadlineMode wurden mit dem Attribut WebBrowsable definiert. Daher
brauchen Sie kein benutzerdefiniertes Editorpart zu erstellen, weil WSS diese Eigenschaften automatisch
im allgemeinen Webparteditor anzeigt, damit Benutzer deren Werte ändern können. Gibt der Benutzer
zum Beispiel für sein Webpart den Befehl Freigegebenes Webpart bearbeiten, zeigt der Aufgabenbereich
diese beiden Eigenschaften im allgemeinen Editorpart an (Abbildung 4.6). Beachten Sie bitte, dass die
zulässigen Werte der Eigenschaft mit dem RenderMode-Enumerationstyp als Dropdownliste angezeigt
werden.
Abbildung 4.6 Mit dem Attribut WebBrowsable definierte Eigenschaften werden
automatisch im WSS-Standardeditorpart angezeigt
Vergessen Sie bitte nicht, dass die HeadlineMode-Eigenschaft mit der Personalisierungseinstellung User
definiert wird, während die Eigenschaft XmlUrl mit der Personalisierungseinstellung Shared definiert
wird. Wechselt ein Benutzer nun mit dem Menüpunkt Diese Seite personalisieren des oberen WillkommenMenüs in den Personalisierungsmodus, kann er die Eigenschaft XmlUrl weder sehen noch bearbeiten. Sie
wird nur im Freigabemodus angezeigt, nicht im Benutzermodus.
Erstellen von benutzerdefinierten Editorparts
Für manche Webparts wird es ausreichen, wenn Sie die beständigen (persistenten) Eigenschaften mit
dem Attribut WebBrowsable definieren, damit WSS die Eigenschaften zur Bearbeitung automatisch im
allgemeinen Editorpart anzeigt. Allerdings reicht das nicht immer aus. Gelegentlich werden Sie für den
Toolbereich eigene Editorparts erstellen wollen. Dieser Abschnitt beschreibt, wie Sie dann vorgehen.
Zur Erstellung eines benutzerdefinierten Editorparts leiten Sie von der Klasse EditorPart aus dem Namespace System.Web.UI.WebControls.WebParts eine neue Klasse ab. In unserem Beispiel erstellen wir eine
neue Klasse namens RssViewEditorPart, die von EditorPart abgeleitet wird und als benutzerdefinierter
Editorpart für die Klasse RssViewWebPart dient.
Beachten Sie bitte, dass wir nicht nur die RssViewEditorPart-Klasse erstellen, sondern auch einige Änderungen an der Klasse RssViewWebPart vornehmen müssen. Zuerst ändern wir die Personalizable-Eigenschaften, damit sie nicht im allgemeinen Editorpart erscheinen. Dazu reicht es aus, dem WebBrowsableAttribut den Wert false zu geben.
[Personalizable(PersonalizationScope.Shared),
WebBrowsable(false)]
public string XmlUrl {
get { return xmlUrl; }
set { xmlUrl = value; }
}
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
128
Kapitel 4: Webparts
Dann müssen Sie die in der Webpartklasse RssViewWebPart die Methode CreateEditorParts überschreiben, damit WSS statt oder zusätzlich zum Standardeditorpart, das normalerweise zur Anzeige von Webparts geladen wird, Ihr benutzerdefiniertes Webpart lädt.
Bei der Überschreibung von CreateEditorParts arbeiten Sie mit Sammlungs- oder Auflistungsobjekten
des Typs EditorPartCollection. Einmal erstellt, lässt sich ein EditorPartCollection-Objekt nicht mehr
ändern. Aber EditorPartCollection verfügt über einen Konstruktor, der ein vorhandenes EditorPartCollection-Objekt und eine ICollection-Schnittstelle für EditorPart-Objekte als Parameter hat. Daher können
Sie so vorgehen, dass Sie ein neues EditorPartCollection-Objekt erstellen, das neben Ihrem benutzerdefinierten Editorpart auch die Standardeditorparts enthält.
Wenn Sie ein EditorPart-Objekt erstellen und initialisieren, müssen Sie auch die ID-Eigenschaft festlegen.
Falls Sie das vergessen, kommt es zu einer Ausnahme, deren Beschreibung mehrdeutig ist und kaum
Informationen zum Debuggen liefert. Das folgende Beispiel zeigt die Syntax für die Überschreibung der
Methode CreateEditorParts und für die Bereitstellung eines benutzerdefinierten Editorparts, das zusammen mit den normalerweise verwendeten Standardeditorparts geladen wird:
public override EditorPartCollection CreateEditorParts() {
List<EditorPart> editorParts = new List<EditorPart>(1);
EditorPart part = new RssViewEditorPart();
part.ID = this.ID + "_rssViewEditor";
editorParts.Add(part);
EditorPartCollection baseParts = base.CreateEditorParts();
return new EditorPartCollection(baseParts, editorParts);
}
Wenden wir uns nun der Erstellung der Klasse RssViewEditorPart zu. Dabei handelt es sich um eine neue
öffentliche Klasse, die von der Klasse EditorParts abgeleitet wird. Wie bei der Erstellung einer Webpartklasse können Sie die Methode CreateChildControls überschreiben und in dieser Methode Steuerelemente
zu einem Editorpart hinzufügen. Bei der Initialisierung der Steuerelemente in einem Editorpart ist es
üblich, die aktuellen Werte der Webparteigenschaften zu verwenden. Das Webpart, das in Ihrem Webpart
bearbeitet wird, ist über eine Eigenschaft namens WebPartToEdit zugänglich.
In der Klasse EditorPart gibt es zwei wichtige abstrakte Methoden mit den Namen ApplyChanges und
SyncChanges. Diese Methoden legen Eigenschaften des Webparts oder des für das Webpart zuständigen
Editorparts fest. Die Methode ApplyChanges übernimmt Werte vom benutzerdefinierten Editorpart und
überträgt sie auf die Eigenschaften des Webparts. Die Methode SyncChanges übernimmt Werte aus dem
Webpart und überträgt sie auf die Eingabesteuerelemente des Editorparts. Wenn Sie das Editorpart laden,
ist es die Methode SyncChanges (also nicht OnLoad oder CreateChildControls), die das Editorpart mit
seinen Anfangswerten versorgt. Listing 4.4 zeigt ein einfaches benutzerdefiniertes RSS-Anzeigewebpart.
In größeren Anwendungen werden Sie sich bei der Erstellung von Editorparts wahrscheinlich an den
Benutzeroberflächen der gemeinsamen Webparteigenschaften orientieren. Beachten Sie bitte, dass Sie im
Editorpart die Personalisierungseinstellung überprüfen müssen, um die Einstellung der Werte entsprechend zu sperren oder zuzulassen. Der Benutzer bearbeitet entweder freigegebene Webparts oder er
nimmt eine persönliche Einstellung des Webparts vor. Im letzteren Fall wird die PersonalizationScopeEinstellung des Webpartmanagers PersonalizationScope.User lauten.
TIPP
Wenn Sie ein benutzerdefiniertes Webpart für eine Eigenschaft entwickeln, sollten Sie auch das Attribut WebBrowsable der Eigenschaft entfernen, damit die Eigenschaft nicht in den Standardwebparts angezeigt wird.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
129
Webparts
Listing 4.4
Ein benutzerdefiniertes Webpart für die Aktualisierung der RssViewWebPart-Eigenschaftswerte
Editorpartbeispiel: RssViewEditorPart
public class RssViewEditorPart : EditorPart {
TextBox txtXmlUrl;
RadioButtonList lstHeadlineMode;
protected override void CreateChildControls() {
Controls.Add(new LiteralControl("Feed-Url:<br/>"));
txtXmlUrl = new TextBox();
txtXmlUrl.Width = new Unit("100%");
txtXmlUrl.TextMode = TextBoxMode.MultiLine;
txtXmlUrl.Rows = 3;
// Im Personalisierumgsmodus darf XmlUrl nicht bearbeitet werden.
if (WebPartManager.Personalization.Scope == PersonalizationScope.User)
txtXmlUrl.Enabled = false;
this.Controls.Add(txtXmlUrl);
Controls.Add(new LiteralControl("Schlagzeilenanzeige:<br/>"));
lstHeadlineMode = new RadioButtonList();
lstHeadlineMode.Items.Add(RenderMode.Full.ToString());
lstHeadlineMode.Items.Add(RenderMode.Titles.ToString());
this.Controls.Add(lstHeadlineMode);
}
public override void SyncChanges() {
this.EnsureChildControls();
RssViewWebPart sourcePart = (RssViewWebPart)this.WebPartToEdit;
string SelectedMode = sourcePart.HeadlineMode.ToString();
lstHeadlineMode.Items.FindByText(SelectedMode).Selected = true;
txtXmlUrl.Text = sourcePart.XmlUrl;
}
public override bool ApplyChanges() {
this.EnsureChildControls();
RssViewWebPart targetPart = (RssViewWebPart)this.WebPartToEdit;
targetPart.XmlUrl = txtXmlUrl.Text;
if(lstHeadlineMode.SelectedValue.Equals("Full"))
targetPart.HeadlineMode = RenderMode.Full;
else
targetPart.HeadlineMode = RenderMode.Titles;
return true;
}
}
Abbildung 4.7 zeigt das benutzerdefinierte Editorpart, das dem Benutzer durch ein mehrzeiliges Textfeld
und ein RadioButtonList-Steuerelement eine umfassendere Bearbeitung ermöglicht. Beachten Sie bitte
auch, dass die Implementierung des benutzerdefinierten Editorparts zwischen der Personalisierungseinstellung Shared und User unterscheidet. Wenn das Editorpart ermittelt, dass der Benutzer das Webpart
mit der Personalisierungseinstellung User bearbeitet, stellt es die Enabled-Eigenschaft des Textfelds txtXmlUrl auf false, damit der Benutzer den Wert nicht ändern kann. Der entscheidende Punkt ist, dass Sie
bei der Entwicklung eines Editorparts wissen müssen, welche Eigenschaften angepasst, aber nicht personalisiert werden können. Und Sie müssen dafür sorgen, dass Benutzer diese Eigenschaften im Personalisierungsmodus User nicht ändern können.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
130
Kapitel 4: Webparts
Abbildung 4.7 Mit einem benutzerdefinierten Editorpart können Sie die Benutzeroberfläche
in dem Aufgabenbereich gestalten, in dem Benutzer die persistenten Webparteigenschaften
anpassen und personalisieren können
Asynchrone Webpartausführung
Gewöhnlich werden Webparts nicht einzeln, sondern zusammen mit einigen anderen Webparts auf den
Seiten eingesetzt. Sie wissen aber normalerweise nicht im Voraus, um wie viele und um welche Webparts
es sich handelt. Gelegentlich sind auf derselben Seite auch Webparts vorhanden, die sehr viel Rechenzeit
beanspruchen. Daher ist es wichtig, dass alle Webparts ihre Daten so effizient wie möglich bearbeiten.
Der Aufbau einer Seite kann zum Beispiel durch eine Datenbankabfrage, einen LDAP-Aufruf und mehrere
Webdienstaufrufe durch mehrere Webparts verlangsamt werden. Statt nun alle Vorgänge nacheinander
ablaufen zu lassen, wodurch sich die Ladezeit der Seite entsprechend verlängert, werden die Vorgänge
asynchron durchgeführt. Im Idealfall entspricht die Ladezeit der Seite dann ungefähr der Zeitdauer, die
der längste Vorgang beansprucht (oder der längste Vorgang, der eine vorgegebene Zeitgrenze überschreitet). Die asynchrone Ausführung von Aufgaben ist zwar keine reine Webparttechnologie, lässt sich aber
wegen des Aufbaus der Webpartseiten aus mehreren Webparts in fast allen Webpartanwendungen einsetzen.
Mit ASP.NET 2.0 kann die Page-Klasse asynchrone Aufgaben mit der Methode RegisterAsyncTask registrieren, damit mehrere Vorgänge gleichzeitig ablaufen können. Dadurch wird nicht nur die Ladezeit der
Seite verkürzt, sondern auch die Threads des IIS-Arbeitsprozesses, die auf Ihrem Server nur in beschränkter Anzahl zur Verfügung stehen, werden weniger stark beansprucht. Da die Zahl der Threads beschränkt
ist, sollte man Threads nicht so einsetzen, dass sie auf die Ergebnisse länger andauernder Vorgänge warten,
sondern sie nur zur Einleitung der Vorgänge verwenden und dann wieder in den Pool zurückgeben,
damit sie andere Arbeiten durchführen können. Sind auf einer Seite asynchrone Aufgaben zu erledigen,
wird der IIS-Arbeitsthread wieder in den Threadpool zurückgegeben, wo er bei Bedarf für andere Arbeiten abgerufen werden kann, während die Seite auf die Beendigung des asynchronen Vorgangs wartet. Im
Beispiel mit dem RSS-Anzeigewebpart kann die Beschaffung der XML-Remotedaten als asynchrone
Aufgabe durchgeführt werden. Dadurch wird der IIS-Arbeitsthread für andere Aufgaben verfügbar, während die Anwendung noch auf eine Antwort vom Remoteserver wartet. Außerdem ist es sinnvoll, vor der
Einleitung des Remoteaufrufs mit einer Abfrage der DisplayMode-Eigenschaft des Webpartmanagers zu
überprüfen, ob sich die Seite im Entwurfsmodus befindet. Klassen, die das IAsyncResult-Entwurfsmuster
(design pattern) implementieren, lassen sich gut mit asynchronen Aufgaben kombinieren und stellen für
Ihren Code aus der mittleren Schicht ein gutes Entwurfsmuster dar. Zu den Beispielen für solche Klassen
gehören ADO.NET-Datenbankklassen, Webabfragen und Webdienstproxys. Listing 4.5 stellt die asynchrone Aufgabe für die Beschaffung von Remotedaten mit der Klasse WebRequest dar. Listing 4.6 ist eine
einfache XSLT-Datei für eine RSS-Webpartanwendung, die die Ausgabe mit der Klasse XslCompiledTransform umformt. In diesem Beispiel wird die Datei als eingebettete Ressource kompiliert, wobei der vollTed Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
131
Webparts
ständige Name LitwareWebParts.Resources.RSS.xslt lautet. (Als Ressourcenstream ist sie mit der Hilfsklasse
WebPartResources aus Listing 4.13 verfügbar). Außerdem finden Sie im Beispielcode für dieses Kapitel
noch eine andere XSLT-Datei für die Umformung des Feeds in Titel, die im Anzeigemodus RenderMode.
Titles erfolgt.
Listing 4.5
Ein asynchrones RSS-Webpart verwendet Page.RegisterAsyncTask
RSS-Anzeiger mit Page.RegisterAsyncTask
using
using
using
using
using
using
using
using
using
using
using
using
System;
System.Collections.Generic;
System.IO;
System.Net;
System.Web;
System.Web.UI;
System.Web.UI.WebControls;
System.Web.UI.WebControls.WebParts;
System.Xml;
System.Xml.XPath;
System.Xml.Xsl;
System.Reflection;
namespace LitwareWebParts {
public class RssViewWebPart : WebPart, IWebEditable {
// Die Eigenschaften xmlUrl und RenderMode wurden der besseren Übersicht halber weggelassen.
private Stream xmlResponseStream = null;
private WebRequest xmlReq;
// Führe alle Arbeiten durch, die vor der Anzeige erfolgen.
// Dazu gehört auch die Einleitung asynchroner Vorgänge.
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (string.IsNullOrEmpty(this.xmlUrl))
return;
// Überprüfe, ob sich die Seite im Entwurfsmodus befindet.
// Überspringe in diesem Fall die Abfrage.
if (this.WebPartManager.DisplayMode.AllowPageDesign) {
this.Controls.Add(new LiteralControl("Keine Anzeige im Entwurfsmodus."));
return;
}
try {
Uri xmlUri = new Uri(this.xmlUrl);
xmlReq = WebRequest.CreateDefault(xmlUri);
xmlReq.Credentials = CredentialCache.DefaultCredentials;
xmlReq.Timeout = 10000; // 10 Sekunden maximal
this.Page.RegisterAsyncTask(
new PageAsyncTask(new BeginEventHandler(BeginXmlRequest),
new EndEventHandler(EndXmlRequest),
new EndEventHandler(XmlRequestTimeout),
null, true)
);
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
132
Kapitel 4: Webparts
} catch (System.Security.SecurityException) {
this.Controls.Add(
new LiteralControl("Zugriff verweigert - stellen Sie die Vertrauensebene auf WSS_Medium."));
}
}
IAsyncResult BeginXmlRequest(object src, EventArgs args,
AsyncCallback callback, object state) {
return this.xmlReq.BeginGetResponse(callback, state);
}
void XmlRequestTimeout(IAsyncResult ar) {
Label timeoutLabel = new Label();
timeoutLabel.Text = string.Format(
"Frist abgelaufen beim Warten auf {0}.", this.XmlUrl);
this.Controls.Add(timeoutLabel);
}
void EndXmlRequest(IAsyncResult ar) {
WebResponse response = this.xmlReq.EndGetResponse(ar);
this.xmlResponseStream = response.GetResponseStream();
}
protected override void RenderContents(HtmlTextWriter writer) {
base.RenderContents(writer);
if (string.IsNullOrEmpty(this.xmlUrl) || this.xmlResponseStream == null)
return;
XslCompiledTransform transform = new XslCompiledTransform();
string xslt;
if (this.HeadlineMode == RenderMode.Full)
xslt = @"Resources.RSS.xslt";
else
xslt = @"Resources.RssTitles.xslt";
string resourceName = @"LitwareWebParts" + xslt;
using (Stream res =
Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) {
using (XmlTextReader stylesheet = new XmlTextReader(res)) {
transform.Load(stylesheet);
}
}
try {
using (XmlReader reader = new XmlTextReader(this.xmlResponseStream)) {
XmlTextWriter results = new XmlTextWriter(writer.InnerWriter);
transform.Transform(reader, results);
reader.Close();
}
} catch (Exception ex) {
writer.Write(ex.Message);
if (this.xmlResponseStream != null) {
this.xmlResponseStream.Close();
this.xmlResponseStream.Dispose();
}
}
}
}
}
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
133
Webparts
RSS und Agenturdaten
RSS (Really Simple Syndication) ist ein XML-Standardvertriebsformat für Newsfeeds, Blogs, WSSListen und Unternehmensdatenströme. Es ist zwar sehr gut geeignet, um externe Daten in ein Portal
einzubinden, aber es stellt auch ein Sicherheitsrisiko dar. Daher sollten Sie den Einsatz auf vertrauenswürdige Websites beschränken. Da externer HTML-Code und externe Skripts auf Ihrer Portalseite
angezeigt werden, die für die meisten Benutzer eine vertrauenswürdige Website darstellt, sollten Sie
sorgfältig prüfen, welche Feeds Sie aktivieren.
RSS ist zudem ein Format, das sich gut mit Daten kombinieren lässt, die in Listenform vorliegen. Da
SharePoint seine Daten in Listen speichert, bietet sich RSS an und ist in WSS 3.0 als integrierte Komponente verfügbar. Die Anwendungsseite /_layouts/listfeed.aspx bietet jede Liste als RSS-Feed mit
Sicherheitseinschränkungen an, wenn die GUID der Liste als Parameter angegeben wird.
RSS lässt sich auch mit gebräuchlichen Erweiterungen wie Simple List Extensions und benutzerdefinierten SharePoint-Erweiterungen erweitern, damit Remoteclients und Aggregatoren bestimmte Listentypen verwenden können, zum Beispiel stark typisierte Listen. Weitere Informationen über die RSSSpezifikation finden Sie unter http://blogs.law.harvard.edu/tech/rss.
Listing 4.6
Ein einfacher XSLT-Quellcode für die Umformung von RSS-XML
RSS XSLT Transform
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dc="http://purl.org/dc/elements/1.1/"
version="1.0"
>
<xsl:output omit-xml-declaration="yes" method="html" encoding="utf-16" />
<xsl:template match='/rss'>
<h3>
<xsl:value-of select='channel/title'/>
</h3>
<xsl:apply-templates select='channel/item' />
</xsl:template>
<xsl:template match='item'>
<div style='margin:6px;'>
<strong>
<a href='{link}'>
<xsl:value-of select='title'/>
</a>
</strong><br/>
<xsl:value-of select='description' disable-output-escaping='yes' />
<xsl:text disable-output-escaping='yes'>&amp;nbsp;</xsl:text>
<a href='{link}'>Den Beitrag lesen</a>.<br />
<xsl:if test='dc:creator'>
<strong>Autor: </strong><xsl:value-of select='dc:creator' />
<br/>
</xsl:if>
<strong>Datum: </strong><xsl:value-of select='pubDate' /><br/>
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
134
Kapitel 4: Webparts
<font color='gray'>
<xsl:for-each select='category'>
<xsl:value-of select='.' /> |
</xsl:for-each>
</font>
<br />
</div>
</xsl:template>
<xsl:template match='category'>
<xsl:value-of select='.'/> |
</xsl:template>
</xsl:stylesheet>
Webpartbausteine
Wenn Sie Webparts entwickeln, empfiehlt es sich im Allgemeinen, die beteiligten Steuerelemente, Ressourcen und die Geschäftslogik zu geschlossenen Einheiten zusammenzufassen. Wie man Ressourcen
verwenden kann, haben Sie bereits am Beispiel einer XSLT-Datei gesehen, die als Ressource in die Assembly des RSS-Webparts eingebettet wurde. Auch statischen HTML-Code, JavaScript oder Bilder können
Sie als Ressourcen einbinden. Außerdem werden Sie auch Benutzersteuerelemente verwenden, wenn Sie
bereits vorhandene Anwendungen auf SharePoint umstellen, und gelegentlich XML-Datenquellen benutzen, beispielsweise RSS-Feeds oder Webdienstendpunkte. Im nächsten Abschnitt werden wir uns weitere
Webpartbausteine für zusammengesetzte Webpartanwendungen ansehen.
Verwenden von Benutzersteuerelementen in Webparts
Vielleicht stehen Sie vor der Aufgabe, eine vorhandene Webseitenanwendung auf SharePoint umzustellen.
Das ist relativ leicht, wenn man die Seiten in Benutzersteuerelemente konvertiert. Benutzersteuerelemente
werden zwar nicht für alle Webpartanwendungen empfohlen, können aber schnell zu Ergebnissen führen,
wenn es darum geht, eine ASP.NET-Anwendung in Ihrer SharePoint-Website bereitzustellen. Benutzersteuerelemente, die in SharePoint verwendet werden, müssen von der Klasse UserControl oder einer
davon abgeleiteten Klasse abgeleitet werden, die in der Webanwendung verfügbar ist (entweder im Verzeichnis bin oder im globalen Assemblycache), und sie müssen in derselben IIS-Webanwendung vorhanden sein.
Dann kann der Webpartcode das Steuerelement mit der Methode Page.LoadControl laden und zu Ihrem
Webpart hinzufügen. Da Ihr Benutzersteuerelement im Dateisystem vorhanden ist, also nicht aus der
Inhaltsdatenbank geladen wird, kann es bei Bedarf Inlinecode enthalten, da es nicht vom Parser für
sicheren Modus (Safe Mode Parser) bearbeitet wird. Beachten Sie bitte, dass Sie Benutzersteuerelemente
nicht in der Inhaltsdatenbank bereitstellen können. Listing 4.7 zeigt ein BenutzersteuerelementhostWebpart. Sie brauchen nur das Steuerelement zu laden und es zur Controls-Auflistung hinzuzufügen. Das
Steuerelementframework sorgt dann für die Anzeige.
TIPP
Benutzersteuerelemente können zwar an einem beliebigen Ort in der IIS-Webanwendung (im zugrunde liegenden Dateisystem) bereitgestellt werden, aber der für WSS 3.0 bevorzugte Pfad ist ein Unterordner des Ordners _controltemplates, der als %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES
im Dateisystem des Servers zu finden ist. Sie können auch ein benutzerdefiniertes Editorpart erstellen, mit dem Benutzer
ihre Wahl unter den Benutzersteuerelementen treffen können, die in einem bestimmten Ordner vorhanden sind.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
135
Webparts
Listing 4.7
Ein Beispielwebpart, das ein Benutzersteuerelement lädt
Benutzersteuerelementhost-Webpart
using
using
using
using
using
System;
System.Web;
System.Web.UI;
System.Web.UI.WebControls;
System.Web.UI.WebControls.WebParts;
namespace LitwareWebParts {
public class UserControlHost : WebPart {
protected Control userControl;
protected override void CreateChildControls() {
this.Controls.Clear();
string userControlPath =
@"/_controltemplates/Litware/LitwareUserControl.ascx";
this.userControl = this.Page.LoadControl(userControlPath);
this.Controls.Add(this.userControl);
}
}
}
Verwenden des Steuerelements SPGridView
SharePoint bietet im Namensraum Microsoft.SharePoint.WebControls einige nützliche Steuerelemente, die
gebräuchliche ASP.NET-Steuerelemente um SharePoint-Funktionen und das entsprechende Aussehen
und Verhalten erweitern. Das wohl nützlichste Websteuerelement ist SPGridView. Das SPGridView-Steuerelement erweitert die ASP.NET-Klasse GridView um Stildeklarationen für SharePoint und kann außerdem mit der Klasse SPDataSource WSS-Datenquellen wie Listen und websiteübergreifende Abfragen
unterstützen. In unserem nächsten Beispiel verwenden wir den SharePoint-Websitekontext, um eine Liste
der Feed-URLs in der SharePoint-Website und ihren Unterwebsites zusammenzustellen. Wir zeigen die
Feedliste mit einem SPGridView-Steuerelement an, das wir später mit unserem RSS-Anzeigewebpart
verbinden. Das SPGridView-Steuerelement kann auch an ein SPDataSource-Objekt gebunden werden,
das eine Liste als Datenquelle anbieten kann. In diesem Beispiel verwenden wir ein DataTable-Objekt,
das aus Listen mehrerer zusammengefasster SharePoint-Websites erstellt wird. Da dieses Beispiel verfügbare Feeds auflistet, überspringen wir Listen, die nicht auf Nachrichten basieren, wie Kataloge, Galerien
und Kategorielisten. Sehen Sie sich im Code von Listing 4.8 an, wie das SPGridView-Steuerelement mit
Daten über bestimmte Listen aus der aktuellen Website versorgt wird.
Listing 4.8
Dieses Feedlistenwebpart verwendet das SPGridView-Steuerelement
Ein Feedlistenwebpart mit dem SPGridView-Steuerelement
public class FeedListWebPart : WebPart {
private SPGridView listsView;
private DataTable dt;
protected override void CreateChildControls() {
List<SPList> lists = new List<SPList>();
this.AddLists(lists, SPContext.Current.Web);
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
136
Kapitel 4: Webparts
listsView = new SPGridView();
listsView.AutoGenerateColumns = false;
this.Controls.Add(listsView);
BoundField colTitle = new BoundField();
colTitle.DataField = "Title";
colTitle.HeaderText = "Titel";
listsView.Columns.Add(colTitle);
BoundField colXml = new BoundField();
colXml.DataField = "ItemCount";
colXml.HeaderText = "Elementanzahl";
listsView.Columns.Add(colXml);
CommandField colSelectButton = new CommandField();
colSelectButton.HeaderText = "Aktion";
colSelectButton.ControlStyle.Width = new Unit(75);
colSelectButton.SelectText = "Zeige RSS";
colSelectButton.ShowSelectButton = true;
listsView.Columns.Add(colSelectButton);
listsView.SelectedIndexChanged += new EventHandler(view_SelectedIndexChanged);
if (!this.Page.IsPostBack) {
dt = new DataTable();
dt.Columns.Add("Title");
dt.Columns.Add("ItemCount");
dt.Columns.Add("XmlUrl");
dt.Columns.Add("ID");
foreach (SPList list in lists) {
DataRow dr = dt.NewRow();
dr["Title"] = list.Title;
dr["ItemCount"] = list.ItemCount.ToString();
dr["ID"] = list.ID;
string url = this.Page.Request.Url.GetLeftPart(UriPartial.Authority)
+ SPUtility.MapWebURLToVirtualServerURL(
list.ParentWeb,
string.Format("{0}/_layouts/listfeed.aspx?List={1}",
list.ParentWebUrl, list.ID.ToString()));
dr["XmlUrl"] = url;
dt.Rows.Add(dr);
}
listsView.DataKeyNames = new string[] { "XmlUrl" };
listsView.DataSource = dt;
listsView.DataBind();
}
}
void view_SelectedIndexChanged(object sender, EventArgs e) {
GridViewRow row = listsView.SelectedRow;
this.xmlUrl = listsView.SelectedValue.ToString();
}
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
137
Webparts
private void AddLists(List<SPList> lists, SPWeb web) {
foreach (SPList list in web.Lists)
if (list.AllowRssFeeds && list.EnableSyndication &&
list.BaseTemplate != SPListTemplateType.Categories &&
list.BaseTemplate != SPListTemplateType.ListTemplateCatalog &&
list.BaseTemplate != SPListTemplateType.MasterPageCatalog &&
list.BaseTemplate != SPListTemplateType.WebPageLibrary &&
list.BaseTemplate != SPListTemplateType.WebPartCatalog &&
list.BaseTemplate != SPListTemplateType.WebTemplateCatalog &&
list.BaseTemplate != SPListTemplateType.UserInformation &&
list.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
lists.Add(list);
foreach (SPWeb subweb in web.Webs) {
if (web.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
AddLists(lists, subweb);
}
}
}
Webpartverben
Ein Webpartverb bezeichnet eine Aktion, die vom Webpartframework als Bestandteil des Anzeigerahmens (Chrome) im Webpartmenü angeboten wird. Durch diese Aktion kann eine clientseitige Funktion
oder ein serverseitiger Handler aufgerufen werden. Um Webpartverben als Menübefehle hinzuzufügen,
überschreiben Sie die Verbs-Eigenschaft des Webparts. Die Eigenschaft Verbs gibt eine WebPartVerbCollection zurück. Daher müssen Sie aus den gewünschten neuen Verben und der base.Verbs-Eigenschaft
eine neue WebPartVerbCollection erstellen. Listing 4.9 fügt Verben für eine serverseitige Übertragung
und ein clientseitiges JavaScript zum RSS-Anzeigewebpart hinzu, mit denen der Benutzer zum RSSQuellfeed wechseln kann. Abbildung 4.8 zeigt das resultierende Menü.
Abbildung 4.8 Webparts können benutzerdefinierte Verben
als Menüpunkte verwenden, wobei die Handler auf der Seite
des Clients oder des Servers liegen können
Listing 4.9
Ein Beispiel für eine Webpartverbimplementierung
Verwenden von Webpartverben für benutzerdefinierte Aktionen
namespace LitwareWebParts {
public class RssViewWebPart : WebPart, IWebEditable {
public override WebPartVerbCollection Verbs {
get {
List<WebPartVerb> verbs = new List<WebPartVerb>();
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
138
Kapitel 4: Webparts
if (!string.IsNullOrEmpty(this.XmlUrl)) {
WebPartVerb verb1 = new WebPartVerb(this.ID + "_ClientSideRssOpenerVerb",
string.Format("window.open('{0}','RSSXML')", this.XmlUrl));
verb1.Description = "Öffne den RSS-Feed in einem externen Fenster.";
verb1.Text = "Öffne den RSS-Feed";
verbs.Add(verb1);
WebPartVerb verb2 = new WebPartVerb(this.ID + "_ServerSideRssOpenerVerb",
new WebPartEventHandler(ServerSideVerbHandler));
verb2.Description = "Lade den RSS-Quellfeed.";
verb2.Text = "Zeige den RSS-Quellfeed";
verbs.Add(verb2);
}
WebPartVerbCollection allverbs =
new WebPartVerbCollection(base.Verbs, verbs);
return allverbs;
}
}
public void ServerSideVerbHandler(object sender, WebPartEventArgs e) {
if (!string.IsNullOrEmpty(this.XmlUrl))
Context.Response.Redirect(this.XmlUrl);
}
// (... der restliche Code wurde der Übersichtlichkeit halber weggelassen ...)
}
}
Webpartverbindungen
Webpartverbindungen sind eine weitere Webparttechnologie, die eine Wiederverwendung der Webparts
in anderen Anwendungen fördert. Verbindungen werden oft für Hauptbegriff/Detail-Datensätze verwendet. Verbindungen werden in Webparts spät (late-bound) hergestellt. Solange ein Webpart die Daten
liefert, die Ihr Webpart verwenden kann, lässt es sich im Webpartframework verbinden.
TIPP
Webpartverbindungen wurden mit WSS 2.0 eingeführt. Für Version 3.0 wurde die Implementierung stark verändert.
Die Schnittstelle ist wesentlich einfacher und beruht auf ASP.NET-Standardschnittstellen. Wie bei der Klasse Microsoft.SharePoint.WebPartPages.WebPart wurden der Namespace Microsoft.SharePoint.WebPartPages.Communication und die entsprechenden Schnittstellen zur Erhaltung der Abwärtskompatibilität noch beibehalten und sollten nicht für Neuentwicklungen
verwendet werden. Verwenden Sie stattdessen die Attribute und Schnittstellen, die in System.Web.UI.WebControls.WebParts
definiert werden.
Verbindungen werden mit dem Attribut ConnectionProvider aktiviert. Am einfachsten können Sie eine
Verbindung zu Ihrem Webpart hinzufügen, indem Sie eine benutzerdefinierte Schnittstelle wie die Schnittstelle ICustomerProvider aus Listing 4.10 implementieren und das Datenobjekt mit dem Attribut ConnectionProvider angeben. Die Schnittstelle definiert in diesem Beispiel einfach eine CustomerID-Eigenschaft,
die an das verbundene Webpart übermittelt wird. Damit eine Verbindung mit dem Anbieterwebpart hergestellt wird, kennzeichnet das Verbraucherwebpart einfach eine Verbindungsmethode mit dem Attribut
ConnectionConsumer. Im folgenden Beispiel finden Sie die für die Verbindung erforderlichen Methodensignaturen. Beachten Sie bitte, dass die Attribute ConnectionProvider und ConnectionConsumer für komplexere Verbindungsarten mehrfach überladen wurden. Aber die hier gezeigte einfache Verbindung dürfte
für die meisten Entwicklungszwecke ausreichen.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
139
Webparts
Listing 4.10
Ein Beispiel für Verbindungsanbieter- und Verbindungsverbraucherwebparts
Beispiel für die Verbindung von Webparts
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
namespace LitwareWebParts {
public interface ICustomerProvider {
string CustomerID { get; }
}
public class SimpleProviderExample : WebPart, ICustomerProvider {
private string customerID = "P1284";
protected override void RenderContents(HtmlTextWriter writer) {
writer.Write("Kunden-ID: " + this.CustomerID);
}
public string CustomerID {
get { return this.customerID; }
}
[ConnectionProvider("Customer ID", AllowsMultipleConnections = true)]
public ICustomerProvider GetCustomerProvider() {
return this;
}
}
public class SimpleConsumerExample : WebPart {
private ICustomerProvider customerProvider;
[ConnectionConsumer("Customer ID")]
public void RegisterCustomerProvider(ICustomerProvider provider) {
this.customerProvider = provider;
}
protected override void RenderContents(HtmlTextWriter writer) {
if (this.customerProvider != null)
writer.Write(this.customerProvider.CustomerID);
else
writer.Write("Keine Verbindung");
}
}
}
Listing 4.10 demonstriert eine Verbindung, die eine bekannte Schnittstelle für die Geschäftslogik verwendet. Außerdem gibt es im Namespace System.Web.UI.WebControls.WebParts einige vordefinierte
Schnittstellen für allgemeine Verbindungen, mit denen Sie auch ein Datenfeld zwischen Webparts übergeben können. Dazu bietet sich die Schnittstelle IWebPartField an. Mit der Schnittstelle IWebPartRow
können Sie auch einen ganzen Datensatz (eine Tabellenzeile) übergeben und mit der Schnittstelle IWebPartTable sogar eine ganze Tabelle. Diese Schnittstellen eignen sich für die Verbindung von lose gekoppelten Komponenten und zur Aktivierung von Verbindungen mit Webparts von anderen Herstellern.
Durch die Implementierung der Schnittstelle IWebPartField im RSS-Webpart können wir Verbindungen
mit selbstgeschriebenen Komponenten oder mit Listenansichtwebparts für Hyperlinklisten herstellen.
TIPP
Die Schnittstelle IWebPartField wird von vielen Webparts implementiert und für Verbindungen verwendet, beispielsweise von Listenansichtwebparts und vom Bildwebpart. Wenn Ihr Webpart zum Beispiel eine Verbindung mit IWebPartField herstellen kann, können Sie eine Verbraucherbindung mit einem Hyperlinklistenwebpart herstellen.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
140
Kapitel 4: Webparts
Listing 4.11 zeigt ein Webpart, das die Schnittstelle IWebPartField implementiert und eine Verbindung
mit der RSS-Anzeige herstellt. Dabei handelt es sich um eine Variante des bereits besprochenen Feedlistenwebparts, das einen XML-URL mit dem RSS-Anzeigewebpart verbindet. Die IWebPartField-Schnittstelle definiert die Eigenschaft Schema und die Methode GetFieldValue, wobei die Eigenschaft Schema
Reflektionsdaten über die Parameter liefert und die Methode GetFieldValue im Webpartverbraucher von
einem Delegaten benutzt wird. Um die Implementierung der Verbindung zu vervollständigen, muss noch
eine Methode, die einen Verweis auf den Anbieter an den Verbraucher zurückgibt, implementiert und
mit dem Attribut ConnectionProvider versehen werden. Beachten Sie bitte, dass die Methode, die für die
Verbindung sorgt, keine Schnittstelle oder Basisklassenmethode ist. Es handelt sich einfach um eine
Methode, die mit dem Attribut ConnectionProvider verfügbar gemacht wird.
Listing 4.11
Umwandlung des Feedlistenwebparts in ein IWebPartField
Das Feedlistenwebpart als IWebPartField
using
using
using
using
using
using
using
System;
System.ComponentModel;
System.Web;
System.Web.UI;
System.Web.UI.WebControls.WebParts;
System.Xml.Serialization;
System.Web.UI.WebControls;
namespace LitwareWebParts {
public class FeedListWebPart : WebPart, IWebPartField{
/* Der SPGridView-Code wurde der Übersichtlichkeit halber weggelassen. */
private string xmlUrl;
[WebBrowsable(true),
Category("Konfiguration"),
Personalizable(PersonalizationScope.User),
DefaultValue(""),
WebDisplayName("Xml Url"),
WebDescription("RSS Feed XML URL")]
public string XmlUrl {
get { return xmlUrl; }
set {
if (!string.IsNullOrEmpty(xmlUrl)) {
Uri xmlUri = new Uri(value);
xmlUrl = xmlUri.AbsolutePath;
} else
xmlUrl = null;
}
}
// Erlaube dem Verbraucherwebpart den Zugriff auf diese Daten.
public void GetFieldValue(FieldCallback callback) {
callback(Schema.GetValue(this));
}
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
141
Webparts
// Beschaffe einen PropertyDescriptor für diese Verbindung.
public System.ComponentModel.PropertyDescriptor Schema {
get {
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(this);
return properties.Find("XmlUrl", false);
}
}
[ConnectionProvider("Xml-URL-Anbieter")]
public IWebPartField GetConnectionInterface() {
return this;
}
}
}
Nun können Sie diese Verbindung in jedem Webpart als Verbraucher herstellen, indem Sie das Attribut
ConnectionConsumer für die Methode SetConnectionInterface angeben. Beachten Sie bitte, dass die Methode weder in einer Schnittstelle ist noch zu einer Basisklasse gehört. Das Besondere an ihr ist das
Attribut. Nun fügen wir einen Verbindungspunkt zum RSS-Webpart hinzu, damit es die Verbindung
annehmen kann. Listing 4.12 zeigt den Code für die Aktivierung der IWebPartField-Verbindung. Beachten
Sie bitte den zusätzlichen Code für die Bearbeitung der durch Kommas separierten Felder, die vom
Hyperlinklistenansichtswebpart geliefert werden. Die Liste liefert den Hyperlink und eine Beschreibung,
die durch ein Komma getrennt wird.
Listing 4.12
Aktivierung einer Verbindung mit einem IWebPartField-Anbieter
Annehmen einer IWebPartField-Verbindung
namespace LitwareWebParts {
public class RssViewWebPart: WebPart, IWebEditable {
/* Der restliche Code wurde der Übersicht halber weggelassen */
// Verbindung anfordern.
[ConnectionConsumer("Xml-URL-Verbraucher", AllowsMultipleConnections = false)]
public void SetConnectionInterface(IWebPartField provider) {
provider.GetFieldValue(new FieldCallback(GetXmlUrl));
}
// Eine Rückrufmethode für den IWebPartField-Delegaten
private void GetXmlUrl(object providedUrl) {
if (providedUrl != null) {
// Ein Workaround für den Url-Feldtyp
string[] urls = ((string)providedUrl).Split(',');
if (urls.Length > 0)
this.XmlUrl = urls[0];
}
}
}
}
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
142
Kapitel 4: Webparts
Nachdem nun alle Vorbereitungen getroffen sind, können unsere Webparts verbunden werden. Beachten
Sie bitte, dass es nicht erforderlich war, beide Webparts gleichzeitig zu programmieren. Außerdem brauchen die beiden Webparts nichts voneinander zu wissen, bevor sie verbunden werden. Unsere Geschäftskunden können die Webparts nun zur Laufzeit verbinden und unsere Webparts sogar mit einem Webpart
von einem anderen Hersteller verbinden. Beachten Sie bitte außerdem, dass Benutzer die Webpartseite in
den Bearbeitungsmodus umschalten müssen, um eine Webpartverbindung herstellen zu können. Die
Verbindung kann mit dem Menüpunkt Verbindungen eingerichtet werden, der im Standardwebpartmenü
erscheint (Abbildung 4.9).
Abbildung 4.9 Sie können eine Verbindung zwischen zwei verbindungsfähigen Webparts herstellen, während sich die Webpartseite im
Bearbeitungsmodus befindet
Verwenden von Ressourcen
Ressourcen sind ein ausgezeichneter Weg, um Webparts mit statischen Inhalten zu versorgen, wenn das
Steuerelement keine weiteren Arbeiten durchführen muss. Außerdem ist es eine gute Lösung, statische
oder lokalisierte Ressourcen einzubinden, weil dadurch keine zusätzlichen Bereitstellungsarbeiten erforderlich werden. Ressourcen lassen sich zum Beispiel verwenden, um Zeichenketten für die Zusammenstellung der Seite bereitzustellen. Eine weitere Verwendungsmöglichkeit wäre, eingebundene Skripts und
Bilder über einen URL verfügbar zu machen, die Ihrem Webpart zugänglich ist. Wenn Sie eine Ressource
in Ihre Webpartassembly aufnehmen möchten, wählen Sie die gewünschte Ressource aus und wählen in
den Dateieigenschaften für den Buildvorgang die Option Eingebettete Ressource. Dann können Sie in der
Assembly mit dem vollständigen Namespace und Dateinamen der Ressource auf die Ressource zugreifen.
Listing 4.13 zeigt eine Hilfsklasse, die sich für den Zugriff auf einen Ressourcenstream oder eine Ressourcenzeichenfolge aus einer Assembly eignet, beispielsweise zur Verwendung in einem Literal-Steuerelement.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
143
Webparts
Listing 4.13
Eine Hilfsklasse für den Ressourcenzugriff
Ressourcen aus einer Assembly auslesen
using System;
using System.Reflection;
using System.IO;
internal static class WebPartResources {
internal static string GetNamedResource(object reference, string fileName) {
Assembly thisApp = Assembly.GetExecutingAssembly();
string resource = null;
string resourceName = string.Format(@"{0}.{1}.{2}",
thisApp.GetName().Name,
reference.GetType().Namespace,
fileName);
using (Stream resStream = thisApp.GetManifestResourceStream(resourceName)) {
using (StreamReader reader = new StreamReader(resStream)) {
resource = reader.ReadToEnd();
}
resStream.Close();
}
return resource;
}
internal static Stream GetNamedResourceStream(object reference, string fileName) {
Assembly thisApp = Assembly.GetExecutingAssembly();
string resourceName = string.Format(@"{0}.{1}",
reference.GetType().Namespace,
fileName);
return thisApp.GetManifestResourceStream(resourceName);
}
}
Diese Technik lässt sich für HTML-Ressourcen in Ihren Webparts einsetzen, beispielsweise für Tabellenlayouts. Stellen Sie sich zum Beispiel vor, Sie haben einen komplexen HTML-Toolbereich für Ihr Steuerelement entwickelt. Statt ihn in ASP.NET-Code mit HtmlControls zu kodieren, können Sie die Tabelle als
HTML-Datei oder als .ascx-Datei entwerfen, die als Toolbar.ascx kompiliert wird, und sie dann als LiteralControl hinzufügen. Der Entwurf von HTML-Ressourcen ist in Visual Studio einfacher, wenn Sie die
Dateinamensendung .ascx wählen. Vergessen Sie aber nicht, dass Sie in einer Ressource, die als eingebettete Ressource kompiliert wird, keinen Servercode unterbringen sollten. Mit dem folgenden Code
könnten Sie mit der Methode GetNamedResource eine eingebettete Ressource namens Toolbar.ascx aus
dem Resources-Ordner der Assembly laden:
string controlText = WebPartResources.GetNamedResource("Resources", "Toolbar.ascx");
Ressourcen lassen sich außerdem verwenden, um Bilder oder JavaScript-Dateien für den Assemblyressourcenhandler bereitzustellen. Der Assemblyressourcenhandler (Assembly Resource Handler) beantwortet Webanfragen, die auf webresource.axd abgebildet werden. Diesen Mechanismus verwendet das
ASP.NET AJAX Toolkit für Skriptressourcen. Mit dem Assemblyressourcenhandler können Sie alle
externen Ressourcen einbinden, beispielsweise statischen HTML-Code, JavaScript oder Bilder, die von
Ihrem Webpart aus der Webpartassembly verwendet werden. Das hilft Ihnen, das Entwurfsziel zu erreichen, eine Webpartanwendung so eigenständig wie möglich zu gestalten, ohne Verknüpfungen mit
externen Skriptressourcen herzustellen oder JavaScript in den C#-Code einzubetten.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
144
Kapitel 4: Webparts
Der Webressourcenhandler (Web Resource Handler) ist ein ASP.NET-HTTP-Handler, der in einer Webpartanwendung besonders nützlich ist, wenn das Webpart eine eigenständig bereitstellbare Anwendung
ist. Um Ressourcen durch den Handler verfügbar zu machen, müssen Sie die Ressourcen mit dem Attribut WebResource aus dem Namespace System.Web.UI kennzeichnen. Außerdem müssen Sie in Visual
Studio den Buildvorgang Eingebettete Ressource wählen. Das WebResource-Attribut sorgt dafür, dass nur
solche Ressourcen über den Handler bereitgestellt werden, die als Webressourcen vorgesehen sind. Außerdem können Sie mit dem WebResource-Attribut einen Inhaltstyp für die Ressource angeben, so wie Sie in
jedem HTTP-Handler einen Inhaltstyp für den Antwortstream festlegen können. Wenn Sie die Eigenschaft PerformSubstitution verwenden, erfolgt der Zugriff auf die Webressource mit ersetzten RessourceURLs. Mit der Syntax <%=WebResource("VollständigerRessourcenname")%> können Sie also den URL
einer anderen kompilierten Webressource angeben. Das folgende Attribut gibt den Inhaltstyp und den
vollständigen Ressourcennamen für die Einbindung der HTML-Datei help.html als Webressource an, die
man als Onlinehilfe für Litware-Webparts verwenden könnte:
[assembly: WebResource(@"LitwareWebParts.Resources.help.html", @"text/html")]
Bei der Registrierung von Skripts durch die Klasse System.Web.UI.ScriptManager greift der Webbrowser
über WebResource.axd oder ScriptResource.axd auf die Ressource zu. Der generierte URL enthält auch
den Zeitstempel der letzten Erstellung der Assembly, damit der Browser eine entsprechende Zwischenspeicherung vornehmen kann. Für kulturspezifische Lokalisierungen können Sie Ressourcen auch in
Satellitenassemblys unterbringen, einschließlich lokalisierter JavaScript-Ressourcen, mit denen Sie Ihre
Webpartanwendungen auf den internationalen Einsatz vorbereiten können. Im nächsten Kapitel, wenn
wir uns mit der Erstellung von AJAX-fähigen Webparts beschäftigen, verwenden wir wieder JavaScriptRessourcen.
Arbeiten mit Webparts im SharePoint-Websiteobjektmodell
Wie alle Daten von SharePoint ist auch das Webpartframework über das Objektmodell von SharePoint
zugänglich. Webpartinstanzen werden über Webpartauflistungen (Webpartsammlungen) bereitgestellt,
die über das SPFile-Objekt zugänglich sind. Im Programmcode erhalten Sie Zugriff auf den Webpartmanager, wenn Sie die Methode GetLimitedWebPartManager eines SPFile-Objekts verwenden. Das ist
eine andere Klasse als der Webpartmanager, der von der Webpartseite verwendet wird (dabei handelt es
sich um ein Steuerelement, wie Abbildung 4.10 zeigt). Stattdessen ist der SPLimitedWebPartManager ein
Ressourcenmanager, der nur für die Verwaltung der Webparts im Websiteobjektmodell verwendet wird.
Während die Klasse SPWebPartManager von der Klasse WebPartManager abgeleitet wird, die wiederum
von Control abgeleitet wird, wird die Klasse SPLimitedWebPartManager von System.Object abgeleitet und
enthält keine Steuerelementfunktionen. Demselben Grundmuster folgt die Klasse SPLimitedWebPartCollection, die sie als ihre WebParts-Eigenschaft zugänglich macht. Dabei handelt es sich um eine leichtgewichtige (lightweight) Klasse, die der Klasse SPWebPartCollection ähnelt, aber schreibgeschützt ist und
nur über einen beschränkten Funktionsumfang verfügt.
Wenn Sie die Klasse SPFile mit einem bestimmten URL verwenden, können Sie die Webparts in den
Webpartzonen der Seite mit SPLimitedWebPartManager bearbeiten. Bei der Featureaktivierung können
Sie zum Beispiel die Eigenschaften der bekannten Webparts bearbeiten, Webparts hinzufügen und andere
Webparts entfernen. Sie können auch von vorhandenen Websites Webparts in ihre XML-Definitionen
exportieren und Dateimodule mit eingebetteten Webpartbeschreibungen für die Verwendung in Features
und Websitedefinitionen erstellen. Der Code in Listing 4.14 zeigt, wie man eine Instanz von RssViewWebPart zur Standardwebseite hinzufügt. Die Methode ExportWebPart der Klasse SPLimitedWebPartManager kann auch für den Export von Webparts nach XML verwendet werden. Listing 4.15 zeigt, wie
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
145
Webparts
ein Webpart in eine Datei exportiert wird. Diese Methode ist nützlich, wenn Sie eine Seitendefinition in
XML erstellen und in eine Featuredefinition aufnehmen möchten.
Abbildung 4.10 Ein Vergleich der Klassen SPLimitedWebPartManager und SPWebPartManager; der Übersichtlichkeit halber wurden
nicht alle Methoden aufgelistet
Listing 4.14
Bearbeitung von Webparts mit dem Websiteobjektmodell von SharePoint
Verwenden von SPLimitedWebPartManager zur Bearbeitung von Webparts
SPSite siteCollection = new SPSite("http://localhost");
SPWeb web = siteCollection.RootWeb;
SPFile file = web.Files["default.aspx"];
SPLimitedWebPartManager webPartManager =
file.GetLimitedWebPartManager(PersonalizationScope.Shared);
WebPart rssPart = new RssViewWebPart();
webPartManager.AddWebPart(rssPart, "Links", 0);
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)
146
Listing 4.15
Kapitel 4: Webparts
Exportieren von Webparts mit dem Websiteobjektmodell von SharePoint
Verwenden von SPLimitedWebPartManager für den Export von Webparts
SPSite siteCollection = new SPSite("http://localhost");
SPWeb web = siteCollection.RootWeb;
SPFile file = web.Files["default.aspx"];
SPLimitedWebPartManager webPartManager =
file.GetLimitedWebPartManager(PersonalizationScope.Shared);
XmlWriter xwriter = new XmlTextWriter("Example.webpart", Encoding.UTF8);
if (webPartManager.WebParts.Count > 0)
webPartManager.ExportWebPart(webPartManager.WebParts[0], writer);
Zusammenfassung
In diesem Kapitel haben Sie die Grundlagen der Webpartentwicklung und weiterführende Webpartkonzepte wie Editorparts, Verben, Verbindungen und die asynchrone Ausführung von Aufgaben kennengelernt. Wir haben uns mit den Unterschieden zwischen der WSS-Webpartentwicklung und der herkömmlichen ASP.NET-Programmierung beschäftigt. Nun sollten Sie in der Lage sein, Ihre eigenen Webparts zu
entwickeln, wobei Sie anpassbare und personalisierbare Eigenschaften verwenden, aggregierte Steuerelemente und asynchrone Methoden benutzen und die Webparts nach Bedarf untereinander verbinden.
Außerdem sollten Sie wissen, wie man mit dem Websiteobjektmodell von SharePoint Webparts auf Webpartseiteninstanzen bearbeitet. Im nächsten Kapitel entwickeln wird diese Grundtechniken weiter und
beschäftigen uns damit, wie man mithilfe des ASP.NET AJAX-Frameworks eine umfangreiche Internetclientschnittstelle entwickelt.
Ted Pattison, Daniel Larson: Windows SharePoint Services 3.0-Programmierung. Microsoft Press2007 (ISBN 978-3-86645-632-7)