Exportieren (0) Drucken
Alle erweitern
Erweitern Minimieren

Verwendung von Silverlight und von Webdiensten zum Datenzugriff in SharePoint Server 2010 (Wrox)

SharePoint 2010

Zusammenfassung: Erfahren Sie, wie Sie mit Microsoft SharePoint 2010-Webdiensten auf Daten von Microsoft Silverlight zugreifen und diese verwalten. Insbesondere lernen Sie, mit Silverlight zusammen mit SharePoint-Webdiensten Listenelemente abzurufen und zu aktualisieren sowie Listenanlagen hochzuladen.

Wrox-Logo

Wrox-Bücher zu SharePoint

Letzte Änderung: Montag, 9. März 2015

Gilt für: Business Connectivity Services | Open XML | SharePoint | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio

Inhalt dieses Artikels
Einführung in die Verwendung von Silverlight und von Webdiensten zum Datenzugriff in SharePoint Server 2010
Einführung in die SharePoint-Webdienste
Gründe für die Verwendung von Webdiensten anstelle von oder zusätzlich zu anderen APIs
Häufig verwendete Funktionen und wo sie in den Webdiensten zu finden sind
Senden von asynchronen Aufrufen an Webdienste von Silverlight aus
Auswählen und Laden von Listendaten aus dem Dienst "Lists.asmx"
Umwandeln von Listendaten-XML in Objekte
Übermitteln von Änderungen an Daten über die Webdienste
Hinzufügen einer Anlage zu einem SharePoint-Listenelement
Informationen zum Autor
Weitere Ressourcen

Autor: Raul Rodila

Herausgeber: WROX-Fachredakteure für SharePoint 2010-Artikel

Inhalt

Sie können eine vollständige funktionsfähige Version des in diesem Artikel beschriebenen Codes herunterladen. In der im Download enthaltenen Datei ReadMe.txt wird die Einrichtung des Codes erläutert. Zur erfolgreichen Ausführung des Codes benötigen Sie Zugriff auf eine SharePoint 2010-Website. Außerdem müssen Sie wissen, wie die Entwicklungsumgebungen Microsoft Visual Studio 2010 und Silverlight eingerichtet werden. Der Quellcode enthält Funktionen, die das Arbeiten mit XML und Collaborative Application Markup Language (CAML) erleichtern. Zudem folgt der Code dem Model-View-ViewModel-Muster, das die Datenbindungsstärken von Silverlight nutzt.

Code herunterladen

In diesem Artikel wird anhand des folgenden Szenarios die Verwendung von SharePoint 2010-Webdiensten für den Zugriff auf Daten von Microsoft Silverlight und deren Verwaltung erläutert.

Die Marketingabteilung von Adventure Works verwaltete ihre Objekte über eine SharePoint-Teamwebsite. Das Team entschied, die Benutzererfahrung zu verbessern und eine benutzerfreundliche Benutzeroberfläche zu erstellen. Nun wird Silverlight für die Suche und Verwaltung von genehmigten grafischen Objekten für die Produkte verwendet. Mitglieder der Marketingabteilung verwenden SharePoint-Workflows und eine Aufgabenliste, um Anforderungen für neue Objekte an das Grafikdesignteam zu erstellen. Nachdem das Grafikdesignteam das Objekt übermittelt hat, wird der Inhalt zunächst vom Marketingteam und dann von der Rechtsabteilung überprüft. Erst dann werden die Objekte im gesamten Unternehmen als genehmigte Versionen zur Verfügung gestellt. In einem einfachen in Visual Studio erstellten sequenziellen Workflow wird das Objekt als genehmigt gekennzeichnet, nachdem die Genehmigungsdaten der Rechtsabteilung und der Marketingabteilung festgelegt wurden. Das Beispiel in diesem Artikel weist einen Ansichts- und Bearbeitungsmodus für Objekte in der Objektliste auf. Zur Verwaltung der Elemente in dieser Liste wird die SharePoint-Webdienste-API verwendet.

Die SharePoint-Webdienste bieten eine API, mit der Sie remote auf SharePoint-Installationen zugreifen können. Sie umfasst zahlreiche Funktionen von der Erstellung und Verwaltung von SharePoint-Websites bis hin zum Zugriff auf Websitedaten und deren Verwaltung. Die API wurde mithilfe von ASMX-Webdiensten implementiert.

Die SharePoint-Webdienste-API unterscheidet sich vom gewohnten Serverobjektmodell, das Webpartentwickler verwenden. Während CAML in der Webdienste-API umfassend verwendet wird, sind gängige Objekte wie SPSite und SPList nicht vorhanden. Der Entwickler muss wissen, welche Funktionalität in welchem Dienst verfügbar ist. Beispielsweise können Sie den Copy-Dienst verwenden, um ein Dokument in einer Dokumentbibliothek zu erstellen und Feldwerte für diese Dokumente festzulegen. Ist jedoch ein Mehrfachwert-Suchfeld vorhanden, kann dieses nicht mit dem Copy-Dienst festgelegt werden. Zum Aktualisieren eines solchen Felds muss der Lists-Dienst aufgerufen werden.

In SharePoint 2010 wurden zwei neue Möglichkeiten zum Zugreifen auf und Ändern von SharePoint-Informationen von einem Remoteclient eingeführt: das Clientobjektmodell und die WCF Data Services, die als REST-Dienste (Representational State Transfer) implementiert sind. Durch das Clientobjektmodell wird für Entwickler, die bisher serverseitige SharePoint-Anwendungen erstellt haben, eine gewohnte Programmiertechnik auf den Client übertragen. Mit den REST-Diensten können Sie Listendaten auf Plattformen verwenden, auf denen das Clientobjektmodell nicht verfügbar ist, z. B. Windows Phone 7. Beide SharePoint-Zugriffsmethoden stehen in Silverlight zur Verfügung. Da sie leichter zu handhaben sind, fragen Sie sich vielleicht, warum Sie überhaupt die SharePoint-Webdienste in SharePoint 2010 verwenden sollten.

Hierfür gibt es im Wesentlichen zwei Gründe:

  • Zum Ausführen von Vorgängen auf SharePoint-Daten, die weder über das Clientobjektmodell noch über die APIs der REST-Dienste verfügbar sind.

  • Zum Entwickeln von Anwendungen, die sowohl in SharePoint 2010 als auch in älteren Versionen von SharePoint funktionsfähig sind, in denen Webdienste die einzige Möglichkeit zur Remoteprogrammierung von SharePoint darstellten.

Entwickler verwenden Webdienste möglicherweise auch in älteren SharePoint-Anwendungen, die sie aktualisieren möchten und deren Neuerstellung mit einer der neuen APIs nicht möglich ist.

Weitere Informationen zu Gründen für die Verwendung von Webdiensten finden Sie unter Auswählen der zu verwendenden SharePoint-API.

Die SharePoint-Webdienste bieten einen umfassenden Satz von Funktionen zur Verwaltung und Bearbeitung von SharePoint-Daten. In Microsoft SharePoint Foundation 2010 stehen 25 Dienste und in der Vollversion von Microsoft SharePoint Server 2010 weitere 6 Webdienste zur Verfügung.

Der am häufigsten verwendete Dienst zur Verwendung von Listendaten und Dokumentbibliotheken ist Lists.asmx. Sie können ihn verwenden, um Listenelemente abzurufen und zu aktualisieren und um Feldwerte für Elemente in Dokumentbibliotheken festzulegen. In Tabelle 1 sind einige Methoden beschrieben.

Tabelle 1.

Methode

Beschreibung

GetListCollection

Ruft eine Liste der Listen auf der SharePoint-Website ab.

GetListItems

Ruft mit einer CAML-Abrage Elemente aus der angegebenen Liste ab.

UpdateListItems

Aktualisiert oder erstellt Listenelemente.

Verwenden Sie den Dienst Copy.asmx, um Dateien in SharePoint zu kopieren und in eine Dokumentbibliothek hochzuladen. Dieser Dienst stellt die in Tabelle 2 beschriebene Methode bereit.

Tabelle 2.

Methode

Beschreibung

CopyIntoItems

Kopiert ein durch ein Byte-Array dargestelltes Dokument in einen oder mehrere Speicherorte auf einem Server.

Verwenden Sie UserGroup.asmx für die Arbeit mit Benutzern und Gruppen. Dieser Dienst stellt die in Tabelle 3 beschriebenen Methoden bereit.

Tabelle 3.

Methode

Beschreibung

GetGroupCollectionFromUser

Ruft die Gruppen ab, denen der angegebene Benutzer als Mitglied angehört.

GetUserCollectionFromGroup

Ruft die Benutzer ab, die Mitglieder der angegebenen Gruppe sind.

Verwenden Sie den Dienst Search.asmx, um auf SharePoint-Indizes zuzugreifen. Dieser Dienst stellt die in Tabelle 4 beschriebene Methode bereit.

Tabelle 4.

Methode

Beschreibung

Query

Führt eine serverseitige Abfrage mithilfe des SharePoint-Suchdiensts aus.

Eine vollständige Liste der Dienste finden Sie unter SharePoint 2010-Webdienste.

Auch wenn Silverlight mit Webentwicklung verbunden ist, gleicht das Programmieren in Silverlight mehr dem Schreiben einer Windows-Anwendung als einer ASP.NET-Anwendung. Im Gegensatz zu Anwendungen, die mit der vollen Version von .NET geschrieben sind, müssen jedoch alle Aufrufe an einen Server asynchron sein. Für einen bestimmten Webdienst umfasst der Aufruf einer Methode das Erstellen des Dienstproxys, das Registrieren eines Rückrufhandlers und schließlich das asynchrone Aufrufen der Methode. Mit dem Clientobjektmodell bietet Microsoft Silverlight-DLLs, um den Zugriff auf SharePoint zu kapseln. Ähnliche DLLs stehen für SharePoint-Webdienste nicht zur Verfügung. Stattdessen muss der Entwickler der ASMX-Datei in der Silverlight-Anwendung einen Dienstverweis hinzufügen, durch den die erforderlichen Proxyklassen generiert werden.

void LoadProductListData()
{ 
// Create the service proxy
ListsSoapClient service = new ListsSoapClient();

// Register the call-back handler
service.GetListItemsCompleted += new EventHandler<GetListItemsCompletedEventArgs>(
ListsService_GetListItemsCompleted);

// Begin the method call
service.GetListItemsAsync(ListName, viewName, query, viewFields,
rowLimit, queryOptions, string.Empty, null);
}

Fügen Sie den entsprechenden Rückrufhandler hinzu, um eine Fehlerüberprüfung auszuführen und das Ergebnis zu behandeln.

void ListsService_GetListItemsCompleted(object sender, GetListItemsCompletedEventArgs e)
{
if (e.Error != null)
HandleException(e.Error);
else
HandleResult(e.Result);
}

Entsprechend einer bewährten Methode sollte der Rückrufhandler vor dem Zugriff auf die Result-Eigenschaft die Error-Eigenschaft überprüfen. Andernfalls kann der Zugriff auf die Result-Eigenschaft eine Ausnahme auslösen, wodurch der eigentliche Fehler verdeckt wird.

Falls im Code während der Verarbeitung der Ergebnisse auf Benutzeroberflächenobjekte oder Objekte, die an Benutzeroberflächenobjekte gebunden sind, zugegriffen wird, muss im Code zudem das Dispatcher-Objekt verwendet werden, um die Ergebnisbehandlung im Benutzeroberflächenthread aufzurufen.

Dispatcher.BeginInvoke(() => HandleResult(e.Result));

Wenn Sie den SharePoint-Dienst Lists verwenden, müssen Sie im ersten Schritt einen Dienstverweis zu Lists.asmx hinzufügen. Der Dienst Lists befindet sich wie alle anderen SharePoint-Webdienste im Ordner _vti_bin einer SharePoint-Website (beispielsweise http://sl2sp.local/_vti_bin/Lists.asmx).

Verwenden Sie die GetListItems-Methode, um Listenelemente abzurufen. Die Daten werden als XML zurückgegeben.

<listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="2">
   <z:row ows_Attachments="1" ows_LinkTitle="LL Bottom Bracket" ows_ProductNumber="BB-7421" ows_ProductCategory="1;#Bottom Brackets" ows_ProductModel="LL Bottom Bracket" ows_Description="Chromoly steel." ows_AttachmentFile="/Lists/Products/Attachments/1/Tulips.jpg" ows__ModerationStatus="0" ows__Level="1" ows_Title="LL Bottom Bracket" ows_ID="1" ows_UniqueId="1;#{D7425118-089A-40B7-98CD-EA3968E84EC6}" ows_owshiddenversion="32" ows_FSObjType="1;#0" ows_Created_x0020_Date="1;#2011-04-14 10:35:58" ows_Created="2011-04-14 10:35:58" ows_FileLeafRef="1;#1_.000" ows_PermMask="0x7fffffffffffffff" ows_Modified="2011-05-26 00:21:22" ows_FileRef="1;#Lists/Products/1_.000" ows_MetaInfo="1;#" />
   <z:row ows_Attachments="1" ows_LinkTitle="ML Bottom Bracket" ows_ProductNumber="BB-8107" ows_ProductCategory="1;#Bottom Brackets" ows_ProductModel="ML Bottom Bracket" ows_Description="Aluminum alloy cups; large diameter spindle." ows_AttachmentFile="/Lists/Products/Attachments/2/Penguins.jpg" ows__ModerationStatus="0" ows__Level="1" ows_Title="ML Bottom Bracket" ows_ID="2" ows_UniqueId="2;#{39915255-4B04-43F5-AC66-E7385D8EBB21}" ows_owshiddenversion="3" ows_FSObjType="2;#0" ows_Created_x0020_Date="2;#2011-04-14 10:35:58" ows_Created="2011-04-14 10:35:58" ows_FileLeafRef="2;#2_.000" ows_PermMask="0x7fffffffffffffff" ows_Modified="2011-05-26 00:22:18" ows_FileRef="2;#Lists/Products/2_.000" ows_MetaInfo="2;#" />
</rs:data>
</listitems>

In der obigen XML stellt jede Zeile einen Datensatz in einer SharePoint-Liste dar. Auch wenn Sie die XML direkt verwenden könnten, sollten Sie sie für eine sinnvolle Nutzung in Silverlight in eine Auflistung von Objekten konvertieren.

Beachten Sie bezüglich der zurückgegebenen XML folgende Hinweise:

  • Werte für Nachschlagespalten werden als Zeichenfolge mit durch ";#" getrennten Werten von ID und Wert zurückgegeben. Beispiel: ows_ProductCategory="1;#Bottom Brackets".

  • Der Wert vor dem Trennzeichen ist die ID des SharePoint-Listenelements. Der Wert nach dem Trennzeichen ist der Inhalt des Felds, das als Anzeigefeld in der Nachschlagespalte aus der referenzierten Liste ausgewählt wurde. Das Beispiel enthält zwar keine Mehrfachwert-Nachschlagespalten, gegebenenfalls werden diese jedoch durch ";#" zwischen jedem ID/Wert-Paar getrennt, wobei die ID wiederum durch ";#" vom Wert getrennt wird.

  • Allen Feldnamen wird "ows_" vorangestellt. Feldnamen mit einem Leerzeichen enthalten "_x0020_" anstelle des Leerzeichens.

  • Folgende Tatsache ist nicht offensichtlich und kann schwer zu erkennen sein: Der Name, durch den ein Feld dargestellt wird, ist der zugrunde liegende Name einer SharePoint-Listenspalte, nicht der Anzeigename. Wenn eine Spalte mit dem Namen "ProdCtg" in einer Liste erstellt wird und später in "Product Category" umbenannt wird, erwarten Sie möglicherweise einen Feldnamen wie "ows_Product_x0020_Category". Stattdessen enthält die XML "ows_ProdCtg". Wenn Sie die richtigen Namen für alle Spalten einer Liste ermitteln möchten, schreiben Sie eine einfache CAML-Abfrage (beispielsweise: <Query xmlns="http://schemas.microsoft.com/sharepoint/soap/"></Query>), und führen Sie sie für die betreffende Liste aus. Das XML-Ergebnis enthält die genauen Spaltennamen, die von den SharePoint-Webdiensten verwendet werden. Wenn Sie schnell den Namen einer einzelnen Spalte finden möchten, navigieren Sie in einem Webbrowser zu der Liste mit der Spalte, und klicken Sie unter Listeneinstellungen auf den Spaltennamen. Die URL enthält den echten Spaltennamen im Format "...&Feld=EchterSpaltenname".

  • Von der GetListItems-Methode werden die Felder zurückgegeben, die in der Standardansicht der SharePoint-Liste enthalten sind. Sie können im Dienstaufruf eine andere Ansicht und eine andere Sortierreihenfolge der Ergebnisse angeben. Im Aufruf können weitere Parameter angegeben werden, die Abfrageeinschränkungen wie das rekursive Durchlaufen von Ordnern beim Abruf von Elementen ermöglichen.

Wie erwähnt, geben die SharePoint-Webdienste Listendaten in Form von XML zurück. Silverlight verwendet ein erweitertes Bindungsmodell, das am besten für Objekte und Eigenschaften geeignet ist, jedoch nicht für XML. Daher muss der Entwickler die vom Lists-Dienst gelieferte XML in eine Menge entsprechender Objekte konvertieren.

Um die Konvertierung von XML in Objekte zu vereinfachen, können Sie einen Satz von Basisklassen erstellen, die für jede SharePoint-Liste verfügbare, häufig verwendete Funktionen kapseln. Die folgende ListItemBase-Klasse enthält zwei Eigenschaften, die allen SharePoint-Listenelementen gemeinsam sind: die ID- und die Titelspalte.

public class ListItemBase : ObservableObjectBase
{
public int Id 
{
get { return _id; }
set
{
if ((this._id != value))
{
this._id = value;
NotifyPropertyChanged("Id");
}
}
}
private int _id;

public string Title
{
get { return _title; }
set
{
if ((this._title != value))
{
this._title = value;
NotifyPropertyChanged("Title");
}
}
}
protected string _title;
}

Beachten Sie, dass die ListItemBase-Klasse von der ObservableObjectBase-Klasse erbt. Die ObservableObjectBase-Klasse stellt die Implementierung für die INotifyPropertyChanged-Schnittstelle bereit. Diese stellt den Hauptmechanismus dar, über den der reichhaltige Bindungsmechanismus in Silverlight die Benutzeroberfläche von Änderungen in zugrunde liegenden Objekten benachrichtigt. Die Abstraktionen, die in den Klassen ListItemBase und ObservableObjectBase implementiert sind, ermöglichen die Wiederverwendung dieser grundlegenden Funktionalität in mehreren Silverlight-zu-SharePoint-Projekten.

Der Schwerpunkt des Beispiels in diesem Artikel liegt auf zwei Listen: der Liste Products der Liste ProductCategories. Die Liste Products enthält alle Produktdaten. Die Liste ProductCategories enthält eine Menge von Kategorienamen, auf die von Elementen der Liste Products verwiesen wird. Nachdem die ListItemBase-Klasse definiert wurde, können nun eine Klasse Product und eine Klasse ProductCategory definiert werden, die die von der GetListItems-Methode zurückgegebenen Informationen kapseln. Jede Klasse darf nur die Eigenschaften definieren, die nur in der jeweiligen Liste vorkommen. Die Eigenschaften ID und Title wurden bereits in der Basisklasse definiert.

public class Product : ListItemBase
{
public string ProductNumber
{
get { return _ProductNumber; }
set
{
if (_ProductNumber != value)
{
_ProductNumber = value;
NotifyPropertyChanged("ProductNumber");
}
}
}
private string _ProductNumber;

public ProductCategory ProductCategory
{
get { return _ProductCategory; }
set
{
if (_ProductCategory != value)
{
_ProductCategory = value;
NotifyPropertyChanged("ProductCategory");
}
}
}
private ProductCategory _ProductCategory;

public string ProductModel
{
get { return _ProductModel; }
set
{
if (_ProductModel != value)
{
_ProductModel = value;
NotifyPropertyChanged("ProductModel");
}
}
}
private string _ProductModel;

public string Description
{
get { return _Description; }
set
{
if (_Description != value)
{
_Description = value;
NotifyPropertyChanged("Description");
}
}
}
private string _Description;

public string AttachmentFile
{
get { return _AttachmentFile; }
set
{
if (_AttachmentFile != value)
{
_AttachmentFile = value;
NotifyPropertyChanged("AttachmentFile");
}
}
}
private string _AttachmentFile;
public string OriginalAttachmentFile { get; set; }
}

Product-Objekte enthalten alle Informationen zu einem Produkt. Im Gegensatz zu den Server- oder Clientobjektmodellen gibt es kein Context-Objekt zum Nachverfolgen von Änderungen an Eigenschaften von Listenelementobjekten. Entwickler, die diese Funktionalität benötigen, müssen sie implementieren. Beispielsweise könnten sie mit jedem Objekt eine Kopie der Quell-XML speichern oder bei der Erstellung eines Objekts eine Schattenkopie von diesem Objekt erstellen.

Nachdem nun das Product-Objekt definiert wurde, muss im letzten Schritt die XML in Objekte konvertiert werden. In der Vollversion von .NET Framework könnte die XML mithilfe eines Dataset-Objekts analysiert oder durch XML-Serialisierung deserialisiert werden. Da keines von beiden in Silverlight verfügbar ist, analysieren Sie die Ergebnis-XML manuell.

Zur Erleichterung der Ergebnisanalyse kapseln Sie die Datenzugriffsmethoden und führen einige der üblichen Vorgänge zum Zugriff auf Listendaten und deren Aktualisierung aus. Betrachten Sie die folgende generische Klasse ListAccessBase.

public class ListAccessBase<T> where T : ListItemBase, new()
{
…
public string ListName { get; protected set; }

protected void GetListItemsAsync(string viewName, XElement query, XElement queryOptions, XElement viewFields, string rowLimit)
{
if (string.IsNullOrEmpty(ListName))
throw new ArgumentNullException("ListName");

ListsSoapClient service = CreateListsService();
service.GetListItemsCompleted += new EventHandler<GetListItemsCompletedEventArgs>(ListsService_GetListItemsCompleted);
service.GetListItemsAsync(ListName, viewName, query, viewFields, rowLimit, queryOptions, string.Empty, null);
}

protected void ListsService_GetListItemsCompleted(object sender, GetListItemsCompletedEventArgs e)
{
Exception error = e.Error;
List<T> items = null;

// Check if the SP web service callback reported any exceptions
if (error == null)
{
try
{
ValidateListsCallbackResult(e.Result, true, false, string.Format("Error while getting records from list '{0}'", ListName));

items = new List<T>();

if (e.Result != null && e.Result.HasElements)
{
foreach (XElement row in e.Result.Descendants(XName.Get("row", "#RowsetSchema")))
{
items.Add(FillItemFromXml(row));
}
}

}
catch (Exception ex)
{
error = ex;
}
}

// Raise the completed event supplying the list or the error encountered.
RaiseListLoadingCompletedEvent(items, error);
}

public void SaveItemAsync(T item)
{
if (string.IsNullOrEmpty(ListName))
throw new ArgumentNullException("ListName");

BatchFactory b = new BatchFactory();

XElement batch = b.Batch(b.Update("1", item.Id.ToString(), GetItemFields(item)));

ListsSoapClient service = CreateListsService();
service.UpdateListItemsCompleted += new EventHandler<UpdateListItemsCompletedEventArgs>(service_UpdateListItemsCompleted);
service.UpdateListItemsAsync(ListName, batch);
}

void service_UpdateListItemsCompleted(object sender, UpdateListItemsCompletedEventArgs e)
{
Exception error = e.Error;
List<T> items = null;

// Check if the SP web service callback reported any exceptions
if (error == null)
{
try
{
ValidateListsCallbackResult(e.Result, true, false, string.Format("Error while saving records to list '{0}'", ListName));

items = new List<T>();

if (e.Result != null && e.Result.HasElements)
{
XElement row = (from node in e.Result.Descendants(XName.Get("row", "#RowsetSchema")) select node).FirstOrDefault();
items.Add(FillItemFromXml(row));
}
}
catch (Exception ex)
{
error = ex;
}
}

// Raise the completed event supplying the list or the error encountered.
RaiseListLoadingCompletedEvent(items, error);
}

protected virtual XElement[] GetItemFields(T item)
{
return new XElement[] { GetField("Title", item.Title) };
}

protected virtual T FillItemFromXml(XElement row)
{
T listItem = new T()
{
Id = GetValueFromXml(row, "ID").ToInt32OrDefault(),
Title = GetValueFromXml(row, "Title")
};
return listItem;
}
…
}

Die ListAccessBase-Klasse enthält Methoden zur Ausführung von Webdienstaufrufen, Analyse von XML-Daten und Nachschlagefeldern sowie zur Überprüfung von Serverantworten.

Von besonderer Bedeutung ist die FillItemFromXml-Methode, die in einer Unterklasse überschrieben werden kann, um alle erforderlichen Felder für die Liste zu analysieren. Der folgende Code enthält die ProductDAL-Klasse, eine Erweiterung von ListAccessBase.

public class ProductsDAL : ListAccessBase<Product>
{

public ProductsDAL(string spUrl)
: base("Products", spUrl) { }

protected override Product FillItemFromXml(XElement row)
{
Product product = base.FillItemFromXml(row);

product.ProductNumber = GetValueFromXml(row, "ProductNumber");
product.ProductModel = GetValueFromXml(row, "ProductModel");
product.Description = GetValueFromXml(row, "Description");
product.AttachmentFile = GetValueFromXml(row, "AttachmentFile");
product.OriginalAttachmentFile = product.AttachmentFile;
product.ProductCategory = new LookupValue(GetValueFromXml(row, "ProductCategory"));

return product;
}

protected override XElement[] GetItemFields(Product item)
{
BatchFactory b = new BatchFactory();
return new XElement[] 
{
b.Field("Title", item.Title),
b.Field("ProductNumber", item.ProductNumber),
b.Field("ProductModel", item.ProductModel),
b.Field("Description", item.Description),
b.Field("AttachmentFile", item.AttachmentFile),
b.Field("ProductCategory", item.ProductCategory.ToLookupValueString())
};
}

public void GetProductsAsync()
{
QueryFactory q = new QueryFactory();
XElement query = null;

GetListItemsAsync(query, GetQueryOptions(true, null, true, true));
}
}

Die ListAccessBase-Klasse enthält generische Funktionalität für die Kommunikation mit dem SharePoint-Dienst Lists. Die ProductsDAL-Klasse bietet spezielle Funktionalität für die Interaktion mit der Products-Liste in SharePoint.

Durch zwei Methoden in dieser Klasse werden Methoden in der ListAccessBase-Klasse überschrieben: die Methoden GetItemFields und FillItemFromXml. Die FillItemFromXml-Methode füllt das Product-Objekt mit Daten aus der zugrunde liegenden XML. Die GetItemFields-Methode konvertiert das Product-Objekt zurück in XML, mit der dann Listenelemente aktualisiert werden können.

Die letzte Methode in der ProductsDAL-Klasse ist die GetProductsAsync-Methode. Sie stellt die CAML-Abfrage bereit, mit der alle Produkte in der Products-Liste abgerufen werden. Sie können ähnliche Methoden mit CAML-Abfragen erstellen, um bestimmte Produkte abzurufen, z. B. GetProductsByProductNumberAsync.

Nachdem die Infrastruktur so weit entwickelt wurde, ist die Aktualisierung von Listendaten sehr einfach. Durch die ProductsDAL-Klasse wird eine weitere Methode der ListAccessBase-Klasse überschrieben, nämlich die GetItemFields-Methode. Diese Methode konvertiert die Objekteigenschaften in das für die Update-Methode erforderliche CAML-Batch-XML-Format. Sie können ähnliche CAML-Batch-XML konstruieren, um Listendaten zu erstellen und zu löschen.

Verwenden Sie den folgenden Code, um ein Produkt zu aktualisieren.

private void SaveItemAsync()
{
ProductsDAL productsDal = new ProductsDAL(AppViewModel.Instance.SharePointSiteURI);
productsDal.ListLoadingCompleted += new EventHandler<Helpers.ListLoadingCompletedEventArgs<Product>>(productsDal_ListSavingCompleted);
productsDal.SaveItemAsync(SelectedProduct);
}

void productsDal_ListSavingCompleted(object sender, Helpers.ListLoadingCompletedEventArgs<Product> e)
{
if (e.Error != null)
throw new Exception(string.Format("Query failed for the {0} List with message {1}", e.ListName, e.Error.Message));

// update SelectedItem fields if necessary
SelectedProduct.OriginalAttachmentFile = e.Result[0].OriginalAttachmentFile;
}

Mit dem SaveItemAsync-Aufruf können Sie ein einzelnes Listenelement speichern. Sie können auch einen SaveItemsAsync-Aufruf erstellen, um mehrere Elemente in einem Dienstaufruf zu speichern, da die Update-Methode in den Webdiensten CAML-Batch-XML verwendet. Obwohl alle Aktualisierungsanforderungen in einem Batch zusammengefasst werden, wird der Batch nicht in einer einzelnen Transaktion ausgeführt. Wenn für einen Datensatz ein Fehler auftritt, wird für andere Datensatzaktualisierungen weiterhin ein Commit in SharePoint ausgeführt. Um die fehlgeschlagenen Aktualisierungen leichter ermitteln zu können, wird in der Batch-XML eine Methoden-ID verwendet, die im Aufruf angegeben und im Ergebnis zusammen mit eventuellen Ausnahmen zurückgegeben wird. Die ID kann ein beliebiger Zeichenfolgenwert sein. Da die ID im Aufruf angegeben und im Ergebnis zurückgegeben wird, können Ausnahmen ggf. über die ID direkt mit der Anforderung verbunden werden.

Zur Optimierung werden die Aktualisierungen nur auf die angegebenen Felder angewendet. Sie müssen für die Aktualisierung nicht den gesamten Datensatz übergeben.

Auch wenn die von der GetListItems-Methode zurückgegebene XML für jedes Feld das Präfix "ows_" enthält, sollte das Präfix nicht in die Aktualisierungs-XML eingeschlossen werden. Leerzeichen müssen jedoch in "_x0020_" konvertiert werden.

Das Ergebnis einer Aktualisierung ist XML, die im Wesentlichen der XML für GetListItems gleicht, und sie kann auf dieselbe Art analysiert werden. Sie enthält eine aktuelle Kopie der aktualisierten Elemente von SharePoint. Auch wenn dies in einem Aktualisierungsvorgang keine so große Rolle spielt, enthält die XML in einem Hinzufügevorgang die ID des neu erstellten Elements.

SharePoint enthält ein Error-Objekt innerhalb des Ereignisargumenteobjekts, das in jeder Rückrufmethode für einen asynchronen Aufruf enthalten ist. Ist beispielsweise die an den Server gesendete CAML fehlerhaft, enthält das Error-Objekt eine Ausnahme.

Eine sehr wichtige Eigenschaft des Aktualisierungsprozesses besteht darin, dass u. U. von SharePoint Ausnahmeinformationen direkt in die vom Methodenaufruf zurückgegebene XML eingeschlossen werden, ohne dass das Error-Objekt eine Ausnahme enthält. In der Regel bedeutet es Erfolg, wenn das Error-Objekt keine Ausnahme enthält. Um den Erfolg einer Aktualisierung zu überprüfen, müssen Sie jedoch jeden <Result>-Knoten im XML-Ergebnis anhand der Knoten <ErrorCode> und <ErrorText> daraufhin analysieren, ob der durch den <Result>-Knoten dargestellte Vorgang einen Erfolg oder einen Fehler geliefert hat. Analysieren Sie diese Fehler mithilfe der ListAccessBase-Klasse. Der folgende Beispielcode zeigt die zurückgegebene XML von einem Update-Aufruf, der ein Element aktualisieren soll, das nicht in der SharePoint-Liste vorhanden ist.

<Results xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<Result ID="1,Update">
<ErrorCode>0x81020016</ErrorCode>
<ErrorText>Item does not exist
The page you selected contains an item that does not exist.  It may have been deleted by another user.</ErrorText>
</Result>
</Results>

In diesem Beispiel besitzt der <Result>-Knoten ein ID-Attribut, das den Wert enthält, der dem Vorgang beim Senden der Aktualisierungsanforderung zugewiesen wird. Es handelt sich nicht um die ID eines Listenelements. Da mehrere Vorgänge in der Batch-XML angefordert werden können, die an eine Aktualisierungsanweisung gesendet wird, können Sie die ID im <Result>-Knoten mit den IDs in der Batch-XML vergleichen und bestimmen, welcher Vorgang erfolgreich oder mit einem Fehler beendet wurde.

Einer der Hauptgründe für die Verwendung von SharePoint-Webdiensten besteht in der Ausführung von Vorgängen, die über andere Client-APIs nicht verfügbar sind, beispielsweise das Hinzufügen einer Anlage zu einem SharePoint-Listenelement. Sie können zwar Daten über die anderen Client-APIs in SharePoint lesen und aktualisieren, das Hinzufügen von Anlagen ist aber nur über Webdienste möglich.

Obwohl die Adventure Works-Produkte zum großen Teil über Produktbilder verfügen, hat das Marketingteam beschlossen, ein Miniaturbild für jedes Produkt als Anlage zum Produktelement zu speichern. Im Codebeispiel wird das FileOpenDialog-Objekt verwendet, um dem Benutzer die Auswahl einer hochzuladenden Datei zu ermöglichen.

private void AddAttachmentAsync()
{
FileInfo fileInfo = FileToUpload;
FileStream fs = fileInfo.OpenRead();
byte[] fileContents = new byte[fs.Length + 1];
fs.Read(fileContents, 0, (int)fs.Length);

ListsSoapClient service = new ListsSoapClient();
service.AddAttachmentCompleted += new EventHandler<AddAttachmentCompletedEventArgs>(service_AddAttachmentCompleted);
//Attach the Document the Sharepoint Entity
service.AddAttachmentAsync(productsDal.ListName, SelectedProduct.Id.ToString(), fileInfo.Name, fileContents);
}

Raul Rodila ist geschäftsführender Gesellschafter und Seniorarchitekt bei Arrow Consulting & Design in West Palm Beach, Florida. Raul befasst sich bei Arrow mit der Automatisierung von Geschäftsabläufen in großem Maßstab für die Bereiche Prüfungs- und Finanzwesen und Masterdatenverwaltung mithilfe von SharePoint zusammen mit Silverlight. Raul ist außerdem ein ausgebildeter Datenbankarchitekt und Leistungsoptimierungstechniker. Raul ist aktives Mitglied der .NET- und SharePoint-Community und hält Vorträge auf Codecamps. Die Firma von Raul finden Sie im Internet unter www.ArrowDesigns.com.

Die folgenden Fachredakteure waren an Microsoft SharePoint 2010-Artikeln von Wrox beteiligt:

  • Matt Ranlett ist ein SQL Server MVP und war über viele Jahre eine feste Institution der .NET-Entwicklercommunity in Atlanta. Als Gründungsmitglied von Atlanta Dot Net Regular Guys hat Matt mehrere regionale Benutzergruppen gegründet und leitet diese. Nach der Arbeit verbringt er viele Stunden mit lokalen und nationalen Communityaktivitäten, wie beispielsweise der SharePoint 1, 2, 3!-Reihe, der Organisation von drei Codecamps in Atlanta, der Tätigkeit als Vice President of Technology im Vorstand von INETA sowie Auftritten bei mehreren Podcasts wie z. B. .Net Rocks und dem ASP.NET-Podcast. Dennoch fand Matt kürzlich Zeit, sich mit einer wunderbaren Frau namens Kim zu verheiraten, die er bei der Aufzucht von drei riesigen Hunden unterstützt. Matt arbeitet derzeit als Seniorberater für Intellinet und gehört dem Team an, das mithilfe von innovativen Lösungen für den Erfolg von Unternehmen sorgt.

  • Jake Dan Attis. Was Muster, Praxis und Steuerung im Hinblick auf die SharePoint-Entwicklung betrifft, sind Sie bei Jake Dan Attis goldrichtig. Er ist von Moncton, Kanada, in die Region Atlanta gezogen und hat einen Abschluss in angewandter Mathematik, ist aber ein hundertprozentiger SharePoint-Hardcoreentwickler. Normalerweise nimmt Dan an Community-Events in der Region Atlanta teil, hält dort Vorträge oder organisiert derartige Events, wie beispielsweise Codecamps, SharePoint-Samstage und die SharePoint-Benutzergruppe in Atlanta. Wenn Dan einmal nicht in Visual Studio arbeitet, verbringt er gerne Zeit mit seiner Tochter Lily, schaut sich Hockey und Football an und kostet weltweite Biersorten.

  • Kevin Dostalek kann über 15 Jahre Erfahrung in der IT-Branche sowie über 10 Jahre Erfahrung in der Verwaltung großer IT-Projekte und der Führung von IT-Personal aufweisen. Er hat Projekte für Unternehmen ganz unterschiedlicher Größe geleitet und hatte verschiedene Funktionen inne, wie beispielsweise Entwickler, Architekt, Business Analyst, technischer Leiter, Manager Entwicklung, Projektmanager, Programm-Manager und Mentor/Coach. Darüber hinaus hat Kevin zwischen 2005 und 2008 auch als Vice President eine Lösungsbereitstellungsabteilung für einen MS Gold Partner mittlerer Größe geleitet und war später auch als Vice President of Innovation and Education tätig. Anfang 2010 gründete Kevin das Unternehmen Kick Studios, das Beratungs-, Entwicklungs- und Schulungsservices für die Spezialbereiche SharePoint und Social Computing anbietet. Seitdem ist er auch bei zahlreichen Benutzergruppenversammlungen, Treffen und Konferenzen im ganzen Land als Referent aufgetreten. Weitere Informationen zu Kevin finden Sie in seinem Blog "The Kickboard".

  • Larry Riemann verfügt über mehr als 17 Jahre Erfahrung im Entwurf und der Entwicklung von Geschäftsanwendungen für einige der weltweit größten Unternehmen. Larry ist ein unabhängiger Berater, Eigentümer von Indigo Integrations und bietet SharePoint-Beratung ausschließlich über SharePoint911 an. Er ist Autor, veröffentlicht Artikel und hält gelegentlich Vorträge auf Konferenzen. In den letzten Jahren befasste er sich in erster Linie mit SharePoint, dem Entwickeln und Erweitern von über SharePoint hinausgehender Funktionalität. Neben seiner Arbeit an SharePoint ist Larry ein ausgebildeter .NET-Architekt und verfügt über umfangreiches Know-how in Sachen Systemintegration, Unternehmensarchitektur und Hochverfügbarkeitslösungen. Weitere Informationen zu Larry finden Sie in seinem Blog.

  • Sundararajan Narasiman ist ein technischer Architekt bei der Content Management & Portals Group von Cognizant Technology Solutions, Chennai, und verfügt über mehr als 10 Jahre Branchenerfahrung. Sundararajan ist in erster Linie als Architektur- und Technologieberater für die SharePoint Server 2010-Stapel- und Mainstream .NET 3.5-Entwicklung tätig. Er ist ein begeisterter Programmierer und interessiert sich auch für Extremprogrammierung und EDT.

Anzeigen:
© 2015 Microsoft