Ich habe mich seit Freitag, hautpsächlich am Freitag, mal mit der Integration von MSBuilds und SharePoint Webservices beschäftigt. Ich möchte bei einem Integration-Build möglichst ohne Aufwände Daten in einer Sharepoint-Liste aktualisieren, oder auch mal neue Daten anhängen. Beim bingen nach einer out-of-the-box Lösung bin ich leider ins Leere gelaufen, daher der eigene Ansatz – Erstellen eines MSBuild Tasks.
Wer mit SharePoint über die Webservices arbeiten will, der sollte sehr fit mit Xml sein. Die Webservices arbeiten ausschließlich mit Xml Eingaben zur Steuerung. Mit den Beispielen in der MSDN kommt man gut voran, daher kann man sich schnell in die Webservice-Schnittstelle(n) einarbeiten.
Ergebnis der “Session” sind 3 MSBuild-Tasks um mit Listen im SharePoint zu interagieren. Den Source Code dafür gibt es hier: http://www.zieschang-jan.de/documents/MsBuildExtensions.zip. Ob ich den günstigsten Weg für die Abbildung der Eigenschaft für den Aufruf gewählt habe, weiß ich selber nicht so richtig, aber mir ist kein besser Weg dazu eingefallen.
Einrichtung
Um die Tasks nutzen zu können muss das Projekt compiliert werden, anschließend sind im Ausgabe-Verzeichnis 4 Dateien vorhanden. Es gibt nun 2 Möglichkeiten die Tasks zu nutzen:
- Kopieren der DLL und der “*.target”-Datei in den MSBuildExtensionsPath, welcher normalerweise “%programfiles%\MSBuild” ist. Anschließend im Import das Target-File referenzieren <Import Project="$(MSBuildExtensionsPath)\CapeVision.MsBuildExtensions.targets"/>
- Die Build-Dateien sollen lokal für das Projekt genutzt werden ohne globale Verfügbarkeit. In diesem Fall ist muss die Referenz für das Target angepasst werden, wie das geht ist im Sample.msbuild im Zip gezeigt.
Usage im MSBuild
Einbindung der Tasks:
1: <PropertyGroup>
2: <CapevisionMsBuildExtensionsTasksPath>.</CapevisionMsBuildExtensionsTasksPath>
3: <SharePoint>http://sdc-srv-moss/SiteDirectory/mcc/</SharePoint>
4: <List>Bücher</List>
5: </PropertyGroup>
6: <Import Project="$(MSBuildExtensionsPath)\CapeVision.MsBuildExtensions.targets"/>
Abrufen alle Listen der SharePoint Site
Dazu muss die Url der SharePoint Site übergeben werden, anschließend werden alle Libraries (Bibliotheken) der Site zurückgegeben. Die Rückgabe kann mittels des Output-Parameters abgefragt werden und anschließend wie andere TaskItems behandelt werden. Das Item verfügt über die folgendenen MetaDaten:
- ID
- Title
- Description
- Modified
- Created
- ItemCount
- EnabledAttachments
1: <SharepointListGetListsTask SharePointUrl="$(SharePoint)">
2: <Output TaskParameter="Libraries" ItemName="myItems"/>
3: </SharepointListGetListsTask>
4: <Message Text="@(myItems)"/>
Hinzufügen eines neuen Eintrages
Zum Anlegen eines Eintrages werden die Listen Felder und die Werte für diese Einträge benötigt. Beides wird als Items an den Task übergeben. Da ein Item benötigt wird und dies mit den Standardmitteln immer eine Datei erfodert wird im Beispiel immer das Build-Script selber referenziert. Die Spalten und die Werte müssen von der Anzahl übereinstimmen und werden entsprechend der Reihenfolge ausgewertet. Zusätzlich wird der Name der Liste benötigt, in die die Daten eingefügt werden.
1: <ItemGroup>
2: <!-- Include schould result in only one file, item requires file present!-->
3: <ListFields Include="Sample.msbuild">
4: <Name>Title</Name>
5: </ListFields>
6: <ListFields Include="Sample.msbuild">
7: <Name>Description</Name>
8: </ListFields>
9: <Add Include="Sample.msbuild">
10: <Name>New MsBuild Script Item</Name>
11: </Add>
12: <Add Include="Sample.msbuild">
13: <Name>This item was inserted by a script/Name>
14: </Add>
15: </ItemGroup>
16: <SharepointListAddTask SharePointUrl="$(SharePoint)"
17: ListName="$(List)" ListFields="@(ListFields)"
18: Values="@(Add)"/>
Ändern eines Eintrages
Am kompliziertesten ist das Ändern eines Eintrages, es muss zu den Felder und den Werten noch eine Bedingung übergeben werden, welche Einräge zu ändern sind. Aber an sich doch dann selbstsprechend, oder? Es gibt eine Einschränkung, maximal werden 200 Elemente geändert, weil nur 200 mit der Bedingung geladen werden. Die Bedingung kann sich aus mehreren Einträgen zusammensetzen, diese werden mit UND verbunden. Bei Condition könnte noch ein “operator” mitgegeben werden, der definiert, wie der Vergleich auszuführen ist. Der Standard-Operator ist “Eq”, also Gleichheit.
1: <ItemGroup>
2: <!-- Include schould result in only one file, item requires file present!-->
3: <ListFields Include="Sample.msbuild">
4: <Name>Title</Name>
5: </ListFields>
6: <Update Include="Sample.msbuild">
7: <Name>Updated MsBuild Script Item</Name>
8: </Update>
9: <Condition Include="Sample.msbuild">
10: <field>Title</field>
11: <value>New MsBuild Script Item</value>
12: </Condition>
13: </ItemGroup>
14: <SharePointListUpdateTask SharePointUrl="$(SharePoint)"
15: ListName="$(List)" ListFields="@(ListFields)"
16: Values="@(Update)"
17: QueryCondition="@(Condition)"/>
TODOs
- Momentan kann man keine ListItems abfragen, dass muss ich definitiv noch für MSBuild nach ausenlegen. Eigentlich ist der Code bereits vorhanden, denn beim Update werden die Einträge für die Referenzierung (ID) benötigt.
- Ich werde die Abfragesprache für das Updaten und Laden von Items auf SQL-like Queries umstellen. Dazu gibt es bereits ein interessantes Projekt auf Codeplex http://yacamlqt.codeplex.com/. Die Integration sollte auch nicht so schwer sein.
Keine Kommentare:
Kommentar veröffentlichen