Mit XML erzeugtes Personenfeld fehlt in listdata.svc

Heute mal wieder die Lösung für ein kurioses Problem, das mich extrem viele Nerven gekostet hat. Ich hatte eine Liste, die u.a. auch über den zu SharePoint gehörenden REST-Service listdata.svc bearbeitet werden soll. Das hat alles problemlos funktioniert, bis auf die Tatsache, daß ein Personenfeld von dem Service nicht ausgegeben wurde. Die Standard-Personenfelder Erstellt von und Geändert von allerdings schon. Auch ein manuell neu angelegtes Personenfeld machte keine Probleme.

Lösung: die Liste wurde samt Inhaltstyp und allen Feldern deklarativ per XML aus einem eigenen Feature erzeugt. Der Vergleich der SchemaXml-Eigenschaft des problematischen Feldes mit derselben Eigenschaft des manuell angelegten Feldes, brachte dann die Lösung. Man muß dem Personenfeld im XML ein weiteres Attribut List="UserInfo" mitgeben, dann klappt’s auch mit dem REST.

WCF-Dienst aus einem asynchronen Ereignis aufrufen

Beim Versuch einen WCF-Dienst in SharePoint aus einem asynchronen EventHandler wie z.B. ItemUpdated aufzurufen, erhält man eine Meldung darüber, daß die Authentifizierung fehlgeschlagen ist. Die Lösung ist einfach: man darf den Dienst nicht als Service Reference in Visual Studio einbinden, sondern als Web Reference.

Der Weg zum Einbinden einer Web Reference ist in Visual Studio 2010 allerdings etwas versteckt. In den Vorversionen reichte ein Rechtsklick auf das Projekt und im Kontextmenü gab es einen Menüpunkt Add Web Reference. In Visual Studio 2010 gibt es nur noch Reference und Service Reference.

Für eine Web Reference klickt man also auf Add Service Reference und es öffnet sich dieser Dialog:

Man trägt hier jetzt nichts sein und klickt stattdessen unten links auf den Button Advanced. Es öffnet sich dieser Dialog:

Auch hier wird nichts eingetragen, aber man findet unten links den gesuchten Button Add Web Reference. Ein Klick darauf öffnet den altbekannten Dialog:

Man beachte wie immer bei WCF-Diensten, daß an die URL MEX angehängt werden muß um die Metadaten zu erhalten, die Visual Studio für die Referenz braucht.

Ein auf diese Art eingebundener WCF-Dienst wird jetzt auch beim Aufruf aus einem asynchronen EventHandler richtig authentifiziert.

WCF in SharePoint – Nachrichtengröße und Stringlängen

Vor einiger Zeit hatte ich in einem Beitrag gezeigt, wie man einen eigenen WCF-Dienst entwickelt und in SharePoint bereitstellt. Das ist alles relativ einfach und durch Nutzung der von SharePoint bereitgestellten Factory-Klasse MultipleBaseAddressBasicHttpBindingServiceHostFactory fällt auch die Konfiguration nicht schwer.

Aber: im produktiven Einsatz wird man wahrscheinlich sehr schnell über eine der folgenden Fehlermeldungen stolpern (ich habe hier nur die englischen Meldungen):

The maximum string content length quota (8192) has been exceeded while reading XML data. This quota may be increased by changing the MaxStringContentLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader.

– oder –

The remote server returned an unexpected response: (400) Bad Request.

– oder –

The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

Diese Fehlermeldungen bekommt man, wenn entweder ein String-Parameter größer als 8k ist oder die gesamte Nachrichtengröße 64k überschreitet. Dabei handelt es sich um die voreingestellten Standardwerte.

Kein Problem, dachte ich zunächst. Wie man das von WCF kennt, legt man einfach die gewünschten Werte in einer eigenen web.config fest und stellt diese im selben Ordner wie die svc-Datei bereit. Wie im genannten Beitrag gezeigt, gab es in diesem Fall sogar bereits eine web.config für eigene Einstellungen. Nach langem Herumprobieren, Testen und Feststellen, daß es nicht geht, Prüfen der Einstellungen, Testen und Feststellen, daß es immer noch nicht geht und nochmaligem Prüfen, mußte ich dann einsehen, daß die ServiceHostFactory-Klasse von SharePoint keine Einstellungen aus der web.config liest.

Es gab jetzt zwei Möglichkeiten: eine eigene Factory-Klasse oder eine andere Möglichkeit suchen. Nachdem ich mehr Zeit mit der Suche nach einer anderen Lösung verbrachte, als ich zum Entwickeln einer eigenen Factory-Klasse gebraucht hätte, habe ich dann doch noch die Lösung gefunden: einen Blogbeitrag von Doug Ware von Elumenotion Specifying Reader Quotas for WCF Services in SharePoint 2010. Danke dafür!

Doug zeigt in diesem Beitrag, wie man Einstellungen für in SharePoint gehostete WCF-Dienste mit Programmcode setzen kann. Dieser Code läßt sich z.B. im FeatureInstalled- oder FeatureActivated-Ereignis unterbringen.

Man benötigt folgende using-Anweisung:

using Microsoft.SharePoint.Administration;

Der Code sieht so aus:

SPWebService svc = SPWebService.ContentService;

SPWcfServiceSettings settings = new SPWcfServiceSettings();

settings.ReaderQuotasMaxStringContentLength = 10485760;

settings.MaxReceivedMessageSize = 10485760;

settings.MaxBufferSize = 10485760;

// hier kann man weitere Einstellungen vornehmen

svc.WcfServiceSettings["myservice.svc"] = settings;

svc.Update();

Oder mit PowerShell:

$svc = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$setting = new-object Microsoft.SharePoint.Administration.SPWcfServiceSettings
$setting.ReaderQuotasMaxStringContentLength = 10485760
$setting.MaxReceivedMessageSize = 10485760
$setting.MaxBufferSize = 10485760
$svc.WcfServiceSettings.item("myservice.svc") = $setting
$svc.update()

Als Schlüssel zum Speichern der Einstellungen muß dabei der exakte Name der svc-Datei verwendet werden. Die Werte wurden im Beispiel willkürlich auf 10MB gesetzt. Den "richtigen" Wert muß jeder für seinen Anwendungsfall selbst herausfinden.

Noch ein sehr wichtiger Hinweis zum Schluß: man muß sowohl den Namen der svc-Datei als auch den Schlüssel zum Speichern der Einstellungen in Kleinbuchstaben schreiben, sonst funktioniert es nicht. Den Hinweis darauf habe ich erst nach langem Suchen hier bei MSDN gefunden.

WCF und Silverlight in SharePoint. Teil 2: eine Silverlight-Anwendung entwickeln, die den Dienst nutzt

Das ist der zweite Teil einer Serie über eigene WCF-Dienste in SharePoint und deren Nutzung in Silverlight. Im ersten Teil wurde gezeigt, wie der WCF-Dienst entwickelt wurde. Hier wird jetzt die zugehörige Silverlight-Anwendung entwickelt, die diesen Dienst nutzt.

Teil 2: eine Silverlight-Anwendung entwickeln, die den Dienst nutzt

Die grundsätzliche Entwicklung mit Silverlight soll hier nicht gezeigt werden. Auch dafür sollten sich im Web ausreichend Anleitungen finden lassen. Hier geht es nur um eine einfache Silverlight-Anwendung, die unseren im letzten Teil entwickelten WCF-Dienst nutzt.

Bei meinem "echten" Projekt ist noch eine Silverlight-Bibliothek dazwischengeschaltet, weil die gesamte Lösung aus mehreren Silverlight-Anwendungen besteht, die alle denselben Dienst und dieselben Businessdaten nutzen.

Schritt 1: Erstellen des Projekts in Visual Studio

Wir fügen unserer Projektmappe ein neues Projekt vom Typ Silverlight Application hinzu:

Ich habe es SilverlightDemo genannt. Im sich öffnenden Dialog wird die Option zum Erstellen eines Webprojektes (das normalerweise zum Testen der Silverlight-Anwendung dient) abgewählt:

Unsere Silverlight-Anwendung würde wegen Authentifizierungsproblemen im Testprojekt sowieso nicht (ohne Anpassungen) funktionieren und wir wollen sie ja in SharePoint haben. Als Silverlight-Version habe ich 3 gewählt. Version 4 sollte aber ebenso funktionieren.

Dem Silverlight-Projekt fügen wir jetzt noch Verweise auf System.Runtime.Serialization und System.ServiceModel (s. Teil 1) hinzu, damit wir WCF nutzen können. Zusätzlich brauchen wir Verweise auf die beiden Silverlight-Client-Assemblies von SharePoint, damit wir den Kontext bekommen. Die Assemblies heißen Microsoft.SharePoint.Client.Silverlight und Microsoft.SharePoint.Client.Silverlight.Runtime und befinden sich im ClientBin-Ordner:

Außerdem brauchen wir einen Verweis auf unseren Dienst (Rechtsklick auf References -> Add Service Reference):

In diesem Dialog gibt man oben die URL des Dienstes an (mit dem Suffix MEX, wie im Browser am Ende von Teil 1) und klickt dann auf Go. Wenn alles klappt, dann wird der Dienst mit seinen Methoden gefunden und angezeigt. Visual Studio erstellt dann Proxy-Klassen für den Dienst selbst und alle Entitäten, die die Methoden des Dienstes eventuell liefern. Der Namensraum, in dem diese Klassen erstellt werden, kann unten angegeben werden.

Schritt 2: die Silverlight-Oberfläche

Die Oberfläche der Silverlight-Anwendung, d.h. das was die Benutzer später sehen, befindet sich in MainPage.xaml. Ich habe dort einen Button zum Aufruf des Dienstes und einen TextBlock zur Anzeige des Ergebnisses eingefügt. Die Datei sieht dann so aus:

<UserControl x:Class="SilverlightDemo.MainPage"

  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;

  xmlns:d="http://schemas.microsoft.com/expression/blend/2008&quot;

  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006&quot;

  mc:Ignorable="d">

 

  <Grid x:Name="LayoutRoot" Background="White">

    <StackPanel Name="stackPanel1" Orientation="Horizontal">

      <Button Height="30" Width="150" Content="Klick mich" Name="Button1" Click="Button1_Click" />

      <TextBlock Height="30" Text="klick den Button" Name="TextBlock1" Padding="6" />

    </StackPanel>

  </Grid>

</UserControl>

 

Optisch sieht das so aus:

Schritt 3: der Code zum Aufruf des Dienstes

Zuerst müssen wir den Kontext zu SharePoint herstellen. Das geschieht durch Hinzufügen einer Zeile zum Application_Startup-Ereignis, das sich in der Datei App.xaml.cs findet. Der gesamte Ereignishandler sieht dann so aus:

private void Application_Startup(object sender, StartupEventArgs e) {

  ApplicationContext.Init(e.InitParams, SynchronizationContext.Current);

  this.RootVisual = new MainPage();

}

Damit das funktioniert, muß man noch eine using-Direktive oben einfügen:

using Microsoft.SharePoint.Client;

Über die Klasse ApplicationContext, die zum SharePoint-Silverlight-Client gehört, erhält man später Zugriff auf den SharePoint-Kontext.

Jetzt können wir uns dem CodeBehind der eigentlichen Anwendung in MainPage.xaml.cs zuwenden. Im Ereignishandler für den Buttonklick definieren wir zunächst die Umgebung für den Dienst:

BasicHttpBinding binding = new BasicHttpBinding();

binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;

EndpointAddress endpoint = new EndpointAddress(ApplicationContext.Current.Url + "/_vti_bin/WcfDemo/DemoService.svc");

 

Durch Setzen der EndpointAddress auf die aktuelle URL der Website plus den Pfad zu unserem Dienst wird erreicht, daß der Dienst immer im richtigen Kontext aufgerufen wird. Innerhalb des Dienstes kann man so z.B. über SPContext.Current.Site bzw. SPContext.Current.Web auf die aktuelle Websitesammlung bzw. auf die aktuelle Website von SharePoint zugreifen.

Jetzt können wir uns damit eine Instanz des Dienstproxy erzeugen:

DemoServiceClient srv = new DemoServiceClient(binding, endpoint);

In Silverlight können externe Dienstaufrufe immer nur asynchron erfolgen. Visual Studio hat das beim Erzeugen der Proxyklassen berücksichtigt und entsprechende EventHandler und Methodenaufrufe erzeugt. Wir rufen also die Methode GetMessage unseres Dienstes asynchron auf. Sobald der Dienst antwortet, ruft dieser dann den vorher gesetzten EventHandler auf und dort verarbeiten wir dann das Ergebnis:

srv.GetMessageCompleted += GetMessageCompleted;

srv.GetMessageAsync();

Und hier noch der entsprechende EventHandler:

private void GetMessageCompleted(object sender, GetMessageCompletedEventArgs e) {

  TextBlock1.Text = e.Result;

}

Wie man sieht, bekommt man den Rückgabewert der Dienstmethode hier über die Result-Eigenschaft der entsprechenden EventArgs. Man kann sie direkt verwenden und z.B. in einem TextBlock ausgeben. Um die Synchronisierung der verschiedenen Threads kümmert sich der erzeugte Proxy automatisch.

Hier nochmal der gesamte Code von MainPage.xaml.cs:

using System;

using System.Windows;

using System.Windows.Controls;

using System.ServiceModel;

using SilverlightDemo.ServiceProxy;

using Microsoft.SharePoint.Client;

 

namespace SilverlightDemo {

  public partial class MainPage : UserControl {

    public MainPage() {

      InitializeComponent();

    }

 

    private void Button1_Click(object sender, RoutedEventArgs e) {

      BasicHttpBinding binding = new BasicHttpBinding();

      binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;

      EndpointAddress endpoint = new EndpointAddress(ApplicationContext.Current.Url + "/_vti_bin/WcfDemo/DemoService.svc");

      DemoServiceClient srv = new DemoServiceClient(binding, endpoint);

      srv.GetMessageCompleted += GetMessageCompleted;

      srv.GetMessageAsync();

    }

 

    private void GetMessageCompleted(object sender, GetMessageCompletedEventArgs e) {

      TextBlock1.Text = e.Result;

    }

  }

}

 

Schritt 4: Abschluß und Test

Unser gesamtes Projekt sieht jetzt so aus:

Sobald man das Projekt kompiliert hat, kann es getestet werden. Dazu lädt man die erzeugte SilverlightDemo.xap-Datei (zu finden im Bin\Debug– bzw. Bin\Release-Ordner) in eine beliebige Dokumentbibliothek in SharePoint hoch und merkt sich den Pfad zur Datei (z.B. /site/library/SilverlightDemo.xap). Jetzt fügt man auf einer beliebigen Webpartseite das Silverlight-Webpart, das zu SharePoint 2010 gehört, hinzu:

Im darauf erscheinenden Dialog gibt man jetzt die URL zur vorher hochgeladenen Datei an (absolut oder relativ):

Das Webpart erscheint dann auf der Seite so:

Und nachdem auf den Button geklickt wurde:

Wie man sieht wird der Text aus der web.config des Dienstes ausgegeben. Dieser kann jetzt geändert werden und die Änderung wird dann sofort in Silverlight angezeigt – natürlich nur, wenn man erneut auf den Button klickt 😉

WCF und Silverlight in SharePoint. Teil 1: einen eigenen WCF-Dienst entwickeln und in SharePoint bereitstellen

Ich habe gerade ein größeres Projekt, bei dem zwar SharePoint als Frontend genutzt werden soll, aber ein Großteil der für die Benutzer sichtbaren Oberfläche in Silverlight gebaut werden muß. Die Anwendung soll außerdem intensiv auf SAP zugreifen – lesend und schreibend. Viele dieser SAP-Zugriffe müssen aus Silverlight erfolgen und da Silverlight im Browser, also auf dem Client, läuft und von dort der direkte Zugriff auf SAP nicht möglich ist, mußte eine Zwischenschicht her. Was bietet sich mehr an, als eigene WCF-Dienste?

Die Verwendung von Externen Inhaltstypen für die Integration von SAP wurde verworfen, weil sehr spezielle Operationen mit den Daten notwendig sind. Das könnte man zwar alles auch dort einbauen, aber die Entwicklung wäre mindestens genauso kompliziert. Außerdem werden diese Daten nur in Silverlight und nicht in SharePoint selbst benötigt. WCF-Dienste bieten die Möglichkeit genau die notwendige Funktionalität zu implementieren – nicht mehr und nicht weniger.

Zum Zugriff auf SAP benutzen wir übrigens ERPConnect von Theobald Software.

Bei meinen ersten Tests mußte ich allerdings ziemlich schnell feststellen, daß das alles gar nicht so einfach ist, wie es (zumindest für mich) auf den ersten Blick aussah. Nach intensiver Webrecherche und sehr viel Ausprobieren habe ich jetzt aber eine funktionierende Testumgebung. Es gibt einen von außen d.h. ohne Codeänderung konfigurierbaren WCF-Dienst, der direkt in SharePoint bereitgestellt wird (und damit die Berechtigungen und die Grundkonfiguration von dort übernimmt) und es gibt eine Silverlight-Anwendung, die diesen Dienst nutzen kann. Die gesamte Lösung läßt sich in WSP-Dateien verpacken und so sauber beim Kunden bereitstellen.

Normalerweise versuche ich meine Beiträge in Deutsch zu verfassen und werde das auch hier tun. Allerdings ist meine gesamte Entwicklungsumgebung englisch und ich hatte auch noch nie eine deutsche Version von Visual Studio unter den Fingern. Screenshots und Erklärungen zu Visual Studio werden also in Englisch sein.

Da das Ganze naturgemäß etwas länger ist, werde ich es in zwei Teile aufteilen. Teil 1 (dieser Beitrag) behandelt die Entwicklung des WCF-Dienstes und dessen Bereitstellung in SharePoint. Teil 2 behandelt die Entwicklung einer SharePoint-fähigen Silverlight-Anwendung, die diesen Dienst nutzt.

Teil 1: einen eigenen WCF-Dienst entwickeln und in SharePoint bereitstellen

Die Bereitstellung eines WCF-Dienstes in WSS 3.0 bzw. MOSS 2007 war relativ kompliziert. Zum einen nutzt diese Version "nur" .NET 2.0, was Änderungen an der web.config notwendig macht und zum anderen ist die Konfiguration eines WCF-Dienstes auch ohne SharePoint relativ kompliziert. In SharePoint 2010 ist das jetzt deutlich einfacher. Zum einen weil SharePoint selbst mit .NET 3.5 und WCF-Diensten arbeitet, so daß das gesamte System bereits vorbereitet ist, und zum anderen weil man die Konfiguration des Dienstes SharePoint überlassen kann.

Eine grundlegende Anleitung zur Entwicklung und Bereitstellung eines WCF-Dienstes in SharePoint findet man hier auf MSDN. Ich habe noch ein paar Erweiterungen zur dort gezeigten Vorgehensweise gemacht. Z.B. weil ich meinem Dienst Konfigurationseinstellungen von außen mitgeben mußte.

Schritt 1: erstellen des Projekts in Visual Studio

Ich beginne immer damit, mir eine leere Projektmappe in Visual Studio anzulegen. Visual Studio legt dann alle Projekte dieser Projektmappe in Unterordnern an. Wenn man das nicht tut, dann liegt später entweder die SLN-Datei in einem Unterordner oder im Ordner eines Projektes. Eine neue, leere Projektmappe erstellt man, indem man File -> New -> Project klickt und dann diese Vorlage auswählt:

Der neuen Projektmappe fügt man jetzt ein neues, leeres SharePoint-Projekt hinzu (durch Rechtsklick im Solution Explorer und dann Add -> New Project:

Ich habe es WcfDemo genannt. Wichtig ist, daß im sich öffnenden SharePoint Customization Wizard die Option "Deploy as a farm solution" ausgewählt wird. Der Dienst läßt sich nicht als sandboxed solution bereitstellen:

Dem Projekt müssen jetzt noch mehrere Verweise hinzugefügt werden (Rechtsklick auf References und dann Add Reference): System.Runtime.Serialization und System.ServiceModel werden für WCF gebraucht. System.Web wird für das Auslesen der Einstellungen gebraucht. Man findet sie direkt im .NET-Reiter:

Zur Benutzung der von SharePoint bereitgestellten Service Factories, die den Dienst automatisch konfigurieren, ist ein weiterer Verweis auf Microsoft.SharePoint.Client.ServerRuntime notwendig. Die Datei findet sich im GAC und kann über den Browse-Reiter des Dialogs ausgewählt werden:

 

Schritt 2: implementieren des Dienstes

Zum Auslesen und Bereitstellen der Einstellungen (dazu weiter unten mehr) gibt es eine statische Klasse AppSettings:

using System;

using System.Collections.Specialized;

using System.Web.Configuration;

 

namespace WcfDemo {

  internal static class AppSettings {

 

    public static string Message {

      get { return WebConfigurationManager.AppSettings["Message"]; }

    }

 

  }

}

Wie genau ein WCF-Dienst entwickelt wird, soll hier nicht weiter erläutert werden. Im Web sollten sich dazu ausreichend Quellen finden lassen. Der Dienst soll zu Testzwecken einfach einen String aus den Einstellungen zurückgeben. Wir brauchen dazu ein Interface IDemoService und eine Klasse DemoService, deren Inhalt ich hier kommentarlos bereitstelle:

using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.ServiceModel;

 

namespace WcfDemo {

  [ServiceContract]

  public interface IDemoService {

 

    [OperationContract]

    string GetMessage();

 

  }

}

 

 

using System;

using System.Collections.Generic;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Activation;

using Microsoft.SharePoint.Client.Services;

 

namespace WcfDemo {

  [ServiceBehavior]

  [BasicHttpBindingServiceMetadataExchangeEndpointAttribute]

  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]

  public class DemoService : IDemoService {

 

    public string GetMessage() {

      return AppSettings.Message;

    }

 

  }

}

Schritt 3: den Dienst bereitstellen

Der Dienst soll im ISAPI-Ordner unterhalb des 14-Hive bereitgestellt werden, damit er später über das von SharePoint bereitgestellte virtuelle Verzeichnis _vti_bin erreicht werden kann. Im Web finden sich mehrere Anleitungen, wie man einen WCF-Dienst konfigurierbar machen kann. Meist wird dabei entweder die web.config-Datei im ISAPI-Ordner angepaßt (eine zu SharePoint gehörende Datei, die man nicht verändern sollte) oder es wird ein eigener Service Host entwickelt, der Einstellungen dann aus einer beliebigen Quelle (Datei, Datenbank, …) verarbeiten kann (was relativ kompliziert ist).

Ich habe hier einen anderen, einfacheren Weg gewählt: wir legen den Dienst in einen Unterordner, damit wir ihm seine eigene web.config-Datei bequem per WSP-Datei mitgeben können. Diese web.config wird nichts anderes enthalten, als die benötigten Einstellungen. Wie bei ASP.NET üblich, werden dadurch alle anderen Konfigurationseinstellungen von der übergeordneten web.config (im ISAPI-Ordner) geerbt.

Wir nehmen in unser Projekt also einen "SharePoint Mapped Folder" auf (Rechtsklick auf das Projekt -> Add -> SharePoint Mapped Folder):

Dem Ordner fügen wir jetzt einen Unterordner hinzu (Rechtsklick -> Add -> New Folder), z.B. WcfDemo. In diesen Ordner nehmen wir zwei neue Dateien auf (Rechtsklick -> Add -> New Item). Als Vorlage nimmt man Text File und benennt die Dateien web.config und DemoService.svc.

Die Datei web.config enthält nur die Einstellungen, die wir im Dienst brauchen und die später jederzeit geändert werden können, z.B. wenn sich in der Umgebung beim Kunden etwas ändert. Das können z.B. Servernamen von Fremdsystemen oder Verbindungsstrings zu Datenbanken sein. Die Datei sieht so aus:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

<configuration>

  <appSettings>

    <add key="Message" value="Hallo Welt!"/>

  </appSettings>

</configuration>

Durch Hinzufügen von weiteren add-Elementen kann man beliebige weitere Einstellungen ablegen und später bequem über die AppSettings-Klasse (s.o.) wieder auslesen.

Die Datei DemoService.svc stellt den eigentlichen Dienst bereit. Sie sieht so aus:

<%@ServiceHost Language="C#" Debug="true"

Service="WcfDemo.DemoService, $SharePoint.Project.AssemblyFullName$"

Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressBasicHttpBindingServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

Das Factory-Attribut legt fest, wie SharePoint den Dienst konfiguriert. Die Möglichkeiten sind hier auf MSDN beschrieben. Beim Service-Attribut gibt man die Klasse mit Namensraum des Dienstes und den "fully qualified assembly name" an. Mit Visual Studio 2010 und seinen SharePoint-Projektvorlagen kann man die korrekte Angabe Visual Studio überlassen. Das Token $SharePoint.Project.AssemblyFullName$ wird nach dem kompilieren automatisch ersetzt. Was damit alles machbar ist, findet man hier auf MSDN.

Allerdings ersetzt Visual Studio standardmäßig keine Tokens in svc-Dateien. Damit das funktioniert, muß man entweder die Projektdatei editieren (dann funktioniert es in diesem Projekt) oder man paßt gleich die verantwortliche MSBuild-Datei an, damit es für alle Projekte funktioniert. Eine kurze Anleitung wie das geht findet man z.B. hier bei Andrew Connell.

Schritt 4: Abschluß und Test

Das gesamte Projekt sieht im Solution Explorer jetzt so aus:

Durch einen Rechtsklick auf das Projekt und Deploy kann es jetzt einfach kompiliert und in SharePoint bereitgestellt werden. Man kann den Dienst dann mit dem Browser über die folgende URL aufrufen: http://<sharepoint>/_vti_bin/WcfDemo/DemoService.svc/MEX (das angehängte /MEX steht für Metadata Exchange).