Archive

Archive for the ‘SP2010’ Category

[SL-SPCOM] : SP2010 Client Object Model – Part 1

Une nouveauté intéressante pour la communauté Silverlight est apparue dans SharePoint 2010. Il est désormais possible, grâce au Client Objet Model, de réaliser des applications interagissant avec SharePoint 2010 sans avoir à réaliser du code personnalisé sur l’environnement SharePoint.

Grâce au Client Object Model nous pouvons à présent réaliser simplement des applications Silverlight ou ECMAScript (JavaScript) accédant à SharePoint sans avoir à développer quoi que ce soit sur l’environnement SharePoint 2010.

Dans SharePoint 2007, nous devions utiliser des WebServices pour réaliser ces opérations. Ce qui avait donc un impact sur les délais de développement d’une application cliente.

Les références nécessaires

Pour un projet Silverlight

Vous devez référencer l’assembly « Microsoft.SharePoint.Client.Silverlight.dll » et « Microsoft.SharePoint.Client.Silverlight.Runtime.dll » qui se trouve dans l’installation SharePoint 2010 à l’emplacement suivant : « C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin\ »

Pour un projet .net classique

Vous devez référencer l’assembly « Microsoft.SharePoint.Client.dll » et « Microsoft.SharePoint.Client.Runtime.dll » qui se trouve dans l’installation SharePoint 2010 à l’emplacement suivant : « C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\ »

L’API

Le Client Object Model est un « mapping » des objets présents sur le modèle objet Sharepoint ainsi vous retrouverez des noms familiers pour un développeur SharePoint :

  • Site -> SPSite
  • Web –> SPWeb
  • ClientContext -> SPContext
  • User -> SPUser
  • List -> SPList
  • ListItem -> SPListItem
  • Field  -> SPField
  • File -> SPFile
  • Folder -> SPFolder

Utilisation

Afin de voir comment utiliser cette librairie nous allons en guise d’exemple tenter de récupérer la liste des « Listes SharePoint » disponibles.

Récupération du contexte / création d’une connexion

 using (ClientContext clientContext = new ClientContext("http://yoursharepointweburl"))
            {
               //actions TODO
            }

Initialisation de la requête

Pour cela il faut tout d’abord utiliser « clientContext.LoadQuery » qui va se charger d’empiler une action à réaliser.

ListCollection listCollections = clientContext.Web.Lists;
clientContext.LoadQuery(listCollections);

A ce stade vous ne pouvez toujours pas utiliser la variable listCollections car elle n’est toujours pas initialisée !

Exécution de la requête

Pour cela il faut appeler « clientContext.ExecuteQuery(); » qui va réaliser l’appel au serveur. Il est donc possible d’empiler plusieurs actions et de faire qu’un seul appel. Limitant ainsi les appel couteux Client Serveur…

    clientContext.ExecuteQuery();

A ce moment le serveur SharePoint est appelée et une réponse JSon est reçue contenant la collection des Listes SharePoint demandées :
[
{
« SchemaVersion »: »14.0.0.0″, »LibraryVersion »: »14.0.4762.1000″, »ErrorInfo »:null
},16,{
« IsNull »:false
},18,{
« IsNull »:false
},20,{
« IsNull »:false
},21,{
« _ObjectType_ »: »SP.ListCollection », »_Child_Items_ »:[
{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:7461b3be-a298-477d-970b-74e07c053a32″, »_ObjectVersion_ »: »0″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1303826931000)\/ », »LastItemModifiedDate »: »\/Date(1303995918000)\/ », »LastItemDeletedDate »: »\/Date(1303826931000)\/ », »Id »: »\/Guid(7461b3be-a298-477d-970b-74e07c053a32)\/ », »Description »: »Cette liste vous permet de prendre connaissance des \u00e9v\u00e9nements \u00e0 venir, des changements d\u2019\u00e9tat ou d\u2019autres informations concernant votre \u00e9quipe. », »Title »: »Annonces », »Direction »: »none », »BaseType »:0, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitann.png », »ItemCount »:2, »BaseTemplate »:104, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-d1ce-42de-9c63-a44004ce0104)\/ », »DefaultViewUrl »: »\u002fLists\u002fAnnonces\u002fAllItems.aspx », »DefaultEditFormUrl »: »\u002fLists\u002fAnnonces\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fLists\u002fAnnonces\u002fNewForm.aspx », »DefaultDisplayFormUrl »: »\u002fLists\u002fAnnonces\u002fDispForm.aspx », »EnableAttachments »:true, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:false, »EnableModeration »:false, »EnableVersioning »:false, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:false, »IsCatalog »:false, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:4a1affe4-2721-4321-bf20-eab8ca008942″, »_ObjectVersion_ »: »0″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1303826923000)\/ », »LastItemModifiedDate »: »\/Date(1303826923000)\/ », »LastItemDeletedDate »: »\/Date(1303826923000)\/ », »Id »: »\/Guid(4a1affe4-2721-4321-bf20-eab8ca008942)\/ », »Description »: »Utilisez la biblioth\u00e8que de style pour stocker des feuilles de style telles que des fichiers CSS ou XSL. Les feuilles de style de cette galerie peuvent \u00eatre utilis\u00e9es par ce site et tous ses sous-sites. », »Title »: »Biblioth\u00e8que de styles », »Direction »: »none », »BaseType »:1, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitdl.png », »ItemCount »:0, »BaseTemplate »:101, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-e717-4e80-aa17-d0c71b360101)\/ », »DefaultViewUrl »: »\u002fStyle Library\u002fForms\u002fAllItems.aspx », »DefaultEditFormUrl »: »\u002fStyle Library\u002fForms\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fStyle Library\u002fForms\u002fUpload.aspx », »DefaultDisplayFormUrl »: »\u002fStyle Library\u002fForms\u002fDispForm.aspx », »EnableAttachments »:false, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:true, »EnableModeration »:false, »EnableVersioning »:false, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:false, »IsCatalog »:true, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
},

{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:08a34d3e-9336-4124-b6a0-d8e7ce442192″, »_ObjectVersion_ »: »6″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1303828530000)\/ », »LastItemModifiedDate »: »\/Date(1303828853000)\/ », »LastItemDeletedDate »: »\/Date(1303828530000)\/ », »Id »: »\/Guid(08a34d3e-9336-4124-b6a0-d8e7ce442192)\/ », »Description »: » », »Title »: »Utilisateurs », »Direction »: »none », »BaseType »:0, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitgen.png », »ItemCount »:2, »BaseTemplate »:100, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-de22-43b2-a848-c05709900100)\/ », »DefaultViewUrl »: »\u002fLists\u002fUtilisateurs\u002fAllItems.aspx », »DefaultEditFormUrl »: »\u002fLists\u002fUtilisateurs\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fLists\u002fUtilisateurs\u002fNewForm.aspx », »DefaultDisplayFormUrl »: »\u002fLists\u002fUtilisateurs\u002fDispForm.aspx », »EnableAttachments »:true, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:false, »EnableModeration »:false, »EnableVersioning »:false, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:false, »IsCatalog »:false, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:e278088c-0c52-40dd-9b32-1719cef6c0f3″, »_ObjectVersion_ »: »0″, »ParentWebUrl »: »\u002f », »HasExternalDataSource »:false, »Created »: »\/Date(1304005536000)\/ », »LastItemModifiedDate »: »\/Date(1304005536000)\/ », »LastItemDeletedDate »: »\/Date(1304005536000)\/ », »Id »: »\/Guid(e278088c-0c52-40dd-9b32-1719cef6c0f3)\/ », »Description »: »description de la voiture », »Title »: »voiture », »Direction »: »none », »BaseType »:1, »ImageUrl »: »\u002f_layouts\u002fimages\u002fitwp.png », »ItemCount »:0, »BaseTemplate »:119, »DefaultContentApprovalWorkflowId »: »\/Guid(00000000-0000-0000-0000-000000000000)\/ », »TemplateFeatureId »: »\/Guid(00bfea71-c796-4402-9f2f-0eb9a6e71b18)\/ », »DefaultViewUrl »: »\u002fvoiture\u002fForms\u002fAllPages.aspx », »DefaultEditFormUrl »: »\u002fvoiture\u002fForms\u002fEditForm.aspx », »DefaultNewFormUrl »: »\u002fvoiture\u002fForms\u002fUpload.aspx », »DefaultDisplayFormUrl »: »\u002fvoiture\u002fForms\u002fDispForm.aspx », »EnableAttachments »:false, »ServerTemplateCanCreateFolders »:true, »EnableFolderCreation »:false, »EnableModeration »:false, »EnableVersioning »:true, »ForceCheckout »:false, »EnableMinorVersions »:false, »DraftVersionVisibility »:0, »Hidden »:false, »IsApplicationList »:true, »IsCatalog »:false, »AllowContentTypes »:true, »DocumentTemplateUrl »:null, »ContentTypesEnabled »:false, »MultipleDataList »:false, »NoCrawl »:false
}
]
}
]

Comme on peut le voir nous recevons beaucoup d’informations, ce qui n’est peut être pas utilise tout le temps. Parfois nous n’avons besoin que de 2 ou 3 informations, il serait donc judicieux de ne renvoyer que ce dont on a vraiment besoin pour améliorer les performances de l’application.

Comment récupérer les listes avec uniquement certaines données ?

Pour faire cela rien de plus simple car la librairie est très modulable.
Il suffit de changer l’appel à la méthode Load vu ci-dessus par l’expression suivante utilisant des lambda Linq.
Nous allons par exemple demander à ne récupérer que les propriétées Title, TemplateFeatureId et ImageUrl de chaques listes

 clientContext.Load(listCollections, (lists => lists.Include(list => list.Title, list => list.TemplateFeatureId, list => list.ImageUrl)));

Nous obtenons une réponse JSon beaucoup plus « light » et donc beaucoup plus petite à transférer sur un réseau informatique.

[
{
« SchemaVersion »: »14.0.0.0″, »LibraryVersion »: »14.0.4762.1000″, »ErrorInfo »:null
},90,{
« IsNull »:false
},92,{
« IsNull »:false
},94,{
« IsNull »:false
},95,{
« _ObjectType_ »: »SP.ListCollection », »_Child_Items_ »:[
{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:7461b3be-a298-477d-970b-74e07c053a32″, »_ObjectVersion_ »: »0″, »Title »: »Annonces », »TemplateFeatureId »: »\/Guid(00bfea71-d1ce-42de-9c63-a44004ce0104)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitann.png »
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:4a1affe4-2721-4321-bf20-eab8ca008942″, »_ObjectVersion_ »: »0″, »Title »: »Biblioth\u00e8que de styles », »TemplateFeatureId »: »\/Guid(00bfea71-e717-4e80-aa17-d0c71b360101)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitdl.png »
},

{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:08a34d3e-9336-4124-b6a0-d8e7ce442192″, »_ObjectVersion_ »: »6″, »Title »: »Utilisateurs », »TemplateFeatureId »: »\/Guid(00bfea71-de22-43b2-a848-c05709900100)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitgen.png »
},{
« _ObjectType_ »: »SP.List », »_ObjectIdentity_ »: »740c6a0b-85e2-48a0-a494-e0f1759d4aa7:web:5db0d1d5-c41a-43ec-82c3-b694288a3ef9:list:e278088c-0c52-40dd-9b32-1719cef6c0f3″, »_ObjectVersion_ »: »0″, »Title »: »voiture », »TemplateFeatureId »: »\/Guid(00bfea71-c796-4402-9f2f-0eb9a6e71b18)\/ », »ImageUrl »: »\u002f_layouts\u002fimages\u002fitwp.png »
}
]
}
]

Soit une réponse de 8 109 bytes contre de 35 524 bytes pour la requête initiale !

Comment factoriser cela sous forme de méthodes ?

Méthodes pour récupérer les listes
using System;
using Microsoft.SharePoint.Client;
using File = Microsoft.SharePoint.Client.File;
using System.Linq.Expressions;
using System.Linq;
using System.Collections.Generic;
using System.Windows.Threading;
using System.Threading;
using System.Text;

namespace SliverlightSPTests
{
    ///
<summary> /// Classe permettant de simplifier les accès à SharePoint via Silverlight
 /// </summary>
    public class SharePointTools
    {
        #region Membres
          private String _webFullUrl = String.Empty;
        #endregion

        #region Ctors
        ///
<summary> /// Créé une instance de la classe permettant de simplifier les accès à SharePoint via Silverlight
 /// </summary>
        ///Url du site sur lequel les requetes vont s'effectuer
        public SharePointTools(String webUrl)
        {
            _webFullUrl = webUrl;
           }
        #endregion

        #region Méthodes

 ///
<summary> /// Permet de récupérer les listes (avec toutes les propriétés) du site actuel
 /// </summary>
        /// Collection des listes du site
        public ListCollection GetAllList()
        {
            ListCollection listCollections = null;

            using (ClientContext clientContext = new ClientContext(_webFullUrl))
            {
                listCollections = clientContext.Web.Lists;

                clientContext.Load(listCollections);
                clientContext.ExecuteQuery();
            }

            return listCollections;
        }

        ///
<summary> /// Permet de récupérer les listes (avec uniquement les propriétés spécifiées) du site actuel
 /// </summary>
        ///Filtres d'inclusion à appliquer sur la requete
        /// Collection des listes du site
        public ListCollection GetAllListWithSpecificProperties(Expression> retrievals)
        {
            ListCollection listCollections = null;

            using (ClientContext clientContext = new ClientContext(_webFullUrl))
            {
                listCollections = clientContext.Web.Lists;

                clientContext.Load(listCollections, retrievals);
                clientContext.ExecuteQuery();
            }

            return listCollections;
        }
#endregion
}
Comment l’appeler ?

Le Client Object Model Silverlight n’accepte pas les appels synchrones autrement dit non exécutés dans une autre Thread que celui de l’UI.

SharePointTools sptools = new SharePointTools("http://yoursharepointweburl");
				ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>
				{
					ListCollection lists = sptools.GetAllList();
                    //ou : IEnumerable lists = sptools.GetAllListWithSpecificProperties((l => l.Include(list => list.Title, list => list.TemplateFeatureId, list => list.ImageUrl)));

					Dispatcher.BeginInvoke(() =>
					{
						Lists.ItemsSource = lists;
					});
				}));

Résultat

Il est donc facile de réaliser des WebPart dynamiques en Silverlight avec un minimum d’effort !

SP2010-COM-GetList

Prochainement

Nous verrons plus en détail comment intéragir avec les Listes SharePoint et comment simplifier les appels vers la Client Object Library

Publicités