Archives du mot-clé programmation

Créer une colonne de données externes et la référencer dans une liste


Cet article fait partie d’une série concernant la mise en oeuvre de liste externes et de workflows avec SharePoint. Les étapes seront passées en revue :

_______________________________________________________________________________________________

Dans certains cas il peut être nécessaire d’utiliser un lien vers un type de contenu externe dans un autre type de contenu. Cela permet, entre autre, de créer un formulaire avec une liste de choix dynamique liée à un système tiers.

L’idée est la même que pour un champ de recherche (lookupField) mais pointant sur une source de données externes.

Par exemple il est possible d’utiliser le type de contenu externe « Personne » précédemment créé dans une liste d’annonce.

Pour cela il existe 2 méthodes :

  • Mode déclaratif
  • Utilisation du modèle objet

Avant de les passer en revue, commençons par voir ce que cela donne dans l’IHM native SharePoint 2013.

Via l’IHM

La procédure est faisable via l’IHM en ajoutant une colonne de type « Données Externe » dans une liste existante (vous ne verrez pas ce type de colonne lors de la création d’un type de contenu).

1 – Par exemple dans une liste d’annonce, ajouter une colonne de type « Données Externes ».

colonne de données externe

Sélectionner le type de contenu et le(s) champ(s) à afficher.

type de contenu externe sharepoint 2013

2 – Une fois la colonne ajoutée, créer une nouvelle annonce dans la liste.

colonne de données externe sharepoint 2013

3 – Sélectionner la personne liée à votre annonce dans la popup.

colonne de données externe sharepoint 2013

A ce moment-là si la liste de personne est trop longue et que vous n’avez aucun filtre de recherche vous ne pourrez pas sélectionner une personne au-delà de celles qui sont affichées (200 résultats dans mon cas). Il faudra donc créer un filtre de recherche (article à venir) via Visual Studio ou SharePoint Designer permettant de paginer les résultats mais aussi de les filtrer en fonction des noms / prénoms par exemple.

Mode déclaratif

Cette méthode n’est pas privilégiée, en effet, aucun wizzard Visual studio n’offre ce type de fonctionnalité. Nous allons tout de même la passer en revue. Pour tester cette méthode il faudra suivre les étapes suivantes :

1 – Créer un nouveau modèle + instance de liste de type « Annonces » via Visual Studio 2012.

liste sharepoint 2013

2 – Modifier le fichier schema.xml de ce modèle de liste afin d’ajouter de nouveaux champs à la section « Fields ». Et là cela devient complexe car il n’existe pas de règle simple concernant les propriétés des champs à créer. Afin de simplifier la procédure nous allons récupérer le code XML de la colonne « Personne » créée via l’IHM (cf. chapitre précédent) avec SharePoint Manager 2013.

–          Retrouver sa liste cible dans son site dans SharePoint Manager 2013

sharepoint manager 2013

–          Retrouver les colonnes permettant de constituer la colonne de données externe « Personne » :

  • Personne : Champs de type BusinessData qui est la colonne de données externe en elle-même
  • Personne_ID : champs caché qui permet de créer un pointeur vers la personne sélectionnées
  • Personne : FirstName : champs en lecture seule qui affiche le nom de la personne sélectionnée dans la liste
  • Personne : LastName : champs en lecture seule qui affiche le prénom de la personne sélectionnée dans la liste

sharepoint manager 2013

–          Récupérer le code XML de ces champs via l’onglet « Schema XML »

sharepoint manager 2013

–          Copier puis coller l’XML pour ces 3 champs dans la section <Fields> du schema.xml du votre template de liste.

A titre d’information voici le code XML des champs récupéré :

<Field Type="BusinessData" DisplayName="Personne" Required="FALSE" EnforceUniqueValues="FALSE" ID="{f4194a0c-b0d6-4f12-b3e9-9ade42f2cb6d}" SourceID="{11411064-1db6-4071-ada7-b87308d09c5f}" StaticName="Personne" BaseRenderingType="Text" Name="Personne" ColName="nvarchar3" RowOrdinal="0" SystemInstance="AdventureWorksPerson" EntityNamespace="SPAlex.Labs.ContentTypes.AdventureWorksPerson" EntityName="Personne" BdcField="BusinessEntityID" Profile="" HasActions="True" SecondaryFieldBdcNames="10%209%20FirstName%20LastName%205" RelatedField="Personne_ID" SecondaryFieldWssNames="32%2031%20Personne%5Fx003a%5F%5Fx0020%5FFirstName%20Personne%5Fx003a%5F%5Fx0020%5FLastName%206" RelatedFieldBDCField="" RelatedFieldWssStaticName="Personne_ID" SecondaryFieldsWssStaticNames="32%2031%20Personne%5Fx003a%5F%5Fx0020%5FFirstName%20Personne%5Fx003a%5F%5Fx0020%5FLastName%206" AddFieldOption="AddToDefaultContentType, AddFieldToDefaultView" Version="1" />
      <Field Type="Note" DisplayName="Personne_ID" Hidden="TRUE" ReadOnly="TRUE" BdcField="Personne_ID" ID="{c639810f-4582-4807-9cb9-5fa05e33a77a}" SourceID="{11411064-1db6-4071-ada7-b87308d09c5f}" StaticName="Personne_ID" Name="Personne_ID" ColName="ntext3" RowOrdinal="0" />
      <Field Type="Note" DisplayName="Personne: FirstName" ReadOnly="TRUE" BdcField="FirstName" ID="{9283024f-2d09-4fc5-99ef-9e7c5652de19}" SourceID="{11411064-1db6-4071-ada7-b87308d09c5f}" StaticName="Personne_x003a__x0020_FirstName" Name="Personne_x003a__x0020_FirstName" ColName="ntext4" RowOrdinal="0" Version="1" />
      <Field Type="Note" DisplayName="Personne: LastName" ReadOnly="TRUE" BdcField="LastName" ID="{92cb9e80-3012-43ea-9739-e92f2a5c0caf}" SourceID="{11411064-1db6-4071-ada7-b87308d09c5f}" StaticName="Personne_x003a__x0020_LastName" Name="Personne_x003a__x0020_LastName" ColName="ntext5" RowOrdinal="0" Version="1" />

Il faut bien comprendre ici que ces champs s’appuient sur une liste externe existante déjà déployée sur mon site. On reprend donc le principe du lookupfield.

–          Ajouter ces champs à la vue par défaut (propriété defaultview à TRUE) dans le schema.xml du template de liste.

<ViewFields>
<FieldRef Name="LinkTitle"></FieldRef>
<FieldRef Name="Personne_x003a__x0020_FirstName"></FieldRef>
<FieldRef Name="Personne_x003a__x0020_LastName"></FieldRef>
<FieldRef Name="Modified"></FieldRef></ViewFields>

–          Ouvrir maintenant l’instance de liste, les colonnes ajoutées sont maintenant visibles dans le designer.  Modifier les paramètres de visibilité de celles-ci afin de décider d’afficher ou non ces colonnes sur le formulaire de création/édition/affichage etc. Dans mon cas la colonne « Personne » est visible dans le newForm/editForm/displayForm, les colonne Personne8ID reste cachée et les autres sont visibles dans le displayForm.

lite instance property sharepoint 2013

Cette solution est plutôt simple mais difficilement lisible et maintenable. De plus ce n’est pas une bonne pratique mais elle a le mérite d’exister J

Une fois ce modèle et l’instance de liste déployés sur mon site via une feature le résultat suivant est alors visible :

colonne de données externe sharepoint

external data column sharepoint

Via le modèle objet

Créer une liste de la même manière que dans la méthode précédente. Puis via un feature receiver déclencher le code suivant :

//le scope de la feature est "web"
            SPWeb currentWeb = (SPWeb)properties.Feature.Parent;
            if (currentWeb != null)
            {
                SPList myList = currentWeb.Lists.TryGetList("MesAnnonces");
                if (myList != null)
                {
                    SPBusinessDataField myPerson = myList.Fields.CreateNewField("BusinessData", "Personne2") as SPBusinessDataField;
                    myPerson.SystemInstanceName = "AdventureWorksPerson";
                    myPerson.EntityNamespace = "SPAlex.Labs.ContentTypes.AdventureWorksPerson";
                    myPerson.EntityName = "Personne";
                    myPerson.HasActions = false;
                    myPerson.BdcFieldName = "BusinessEntityID";
                    string[] myArray = new string[]{"FirstName", "LastName"};
                    myPerson.SetSecondaryFieldsNames(myArray);

                    myList.Fields.Add(myPerson);
                    myList.Update();
                }
            }
 

Même résultat à l’écran qu’avec la méthode précédente sauf que celle-ci est plus « propre » 🙂

Création d’une liste externe SharePoint 2013 en programmation


Cet article fait partie d’une série concernant la mise en oeuvre de liste externes et de workflows avec SharePoint. Les étapes seront passées en revue :

_______________________________________________________________________________________________

La liste externe va permettre d’exploiter le type de contenu externe précédemment créé dans SharePoint. Il existe différents moyens de la créer en programmation :

  • En mode déclaratif via une nouvelle instance de Liste (element.xml)
  • En utilisant le modèle objet et plus particulièrement SPListDatasource.BDCProperties

Comme nous l’avons déjà vu une liste externe peut également être créée via l’IHM SharePoint 2013 ainsi qu’avec SharePoint Designer 2013.

Le mode déclaratif

Créer une instance de liste externe via la Wizzard Visual Studio 2012 n’est pas possible. En effet le modèle de type « Liste externe » n’est pas disponible à la sélection, on peut rapidement en conclure que cette solution n’est pas celle privilégiée par Microsoft.

Nous allons tout de même voir comment y arriver en modifiant le fichier elements.xml correspondant à l’instance.

1 – Dans Visual Studio 2012 ajouter un nouvel élément de type Liste au projet.

liste externe SharePoint

2 – Choisir de créer uniquement une instance de liste basée sur n’importe quel modèle (« Annonces » par exemple) étant donné que nous allons le modifier par la suite.

liste externe SharePoint

liste externe SharePoint

3 – Une nouvelle feature ainsi qu’une nouvelle instance de liste viennent d’être créées. Trouver le fichier elements.xml correspondant à cette instance de liste.

liste externe SharePoint element.xml

4- Editer ce fichier et remplacer le code existant par la code suivant


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

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">

<ListInstance Title="Personnes"

OnQuickLaunch="TRUE"

TemplateType="600"

FeatureId="00bfea71-d1ce-42de-9c63-a44004ce0104"

Url="Lists/Personnes"

Description="Liste Externe Personnes">

<DataSource>

<Property Name="LobSystemInstance" Value="AdventureWorksPerson" />

<Property Name="EntityNamespace" Value="SPAlex.Labs.ContentTypes.AdventureWorksPerson" />

<Property Name="Entity" Value="Personne" />

<Property Name="SpecificFinder" Value="ReadItem" />

</DataSource>

</ListInstance>

</Elements>

–          Il faudra noter le TemplateType qui est égal à 600 pour les listes externes

–          L’ajout d’un noeud DataSource avec un ensemble de propriétés que l’on peut facilement trouver via l’administration centrale si le type de contenu externe sur lequel se base cette liste a déjà été déployé une fois. Pour cela il faut se rendre sur l’application de service BDC et y trouver le type de contenu. Les informations dont vous avez besoin sont alors disponibles.

type de contenu externe administration centrale

Cliquer sur le type de contenu externe.

type de contenu externe sharepoint 2013

  • La valeur de « Nom » doit être utilisée pour « Entity ».
  • La valeur de « Espace de noms » pour « EntityNamespace »
  • La valeur de « Système externe » pour « LobSystemInstance »

5 – Déployer sur le site via Visual Studio et le tour est joué.

liste externe sharepoint

Modèle Objet

Cette solution semble privilégiée. Il est possible de créer une instance de liste via un feature receiver par exemple.

1 – dans Visual Studio 2012, ajouter une nouvelle fonctionnalité via clic droit sur l’élément « features ».

feature visual studio 2012

Nommer la feature.

feature sharepoint 2013 visual studio 2012

2 – Faire un clic droit sur la feature et lui ajouter un récepteur d’évènement (ou feature Receiver).

feature eceiver visual studio 2012 sharepoint

3 – Remplacer le code de la classe nouvellement créée par le code suivant :


using System;

using System.Runtime.InteropServices;

using System.Security.Permissions;

using Microsoft.SharePoint;

namespace SPAlex.Labs.Features.LissteExternePersonneDev

{

/// <summary>

/// Cette classe gère les événements déclenchés lors de l'activation, la désactivation, l'installation, la désinstallation et la mise à niveau de fonctions.

/// </summary>

/// <remarks>

/// Le GUID attaché à cette classe peut être utilisé lors de la compression et ne doit pas être modifié.

/// </remarks>

[Guid("e7c5fb55-26b4-43a1-8050-3d99c77e5f2b")]

public class LissteExternePersonneDevEventReceiver : SPFeatureReceiver

{

public override void FeatureActivated(SPFeatureReceiverProperties properties)

{

//défintion du datasource

SPListDataSource ds = new SPListDataSource();

ds.SetProperty(SPListDataSource.BDCProperties.LobSystemInstance, "AdventureWorksPerson");

ds.SetProperty(SPListDataSource.BDCProperties.EntityNamespace, "SPAlex.Labs.ContentTypes.AdventureWorksPerson");

ds.SetProperty(SPListDataSource.BDCProperties.Entity, "Personne");

ds.SetProperty(SPListDataSource.BDCProperties.SpecificFinder, "ReadItem");

//le scope de la feature est "web"

SPWeb currentWeb = (SPWeb) properties.Feature.Parent;

if (currentWeb != null)

{

currentWeb.Lists.Add("Personnes Dev", "Personnes Dev", "Lists/PersonnesDev", ds);

}

}

public override void FeatureDeactivating(SPFeatureReceiverProperties properties)

{

//le scope de la feature est "web"

SPWeb currentWeb = (SPWeb)properties.Feature.Parent;

if (currentWeb != null)

{

SPList myList = currentWeb.Lists.TryGetList("Personnes Dev");

if (myList != null)

{

currentWeb.Lists.Delete(myList.ID);

}

}

}

}

}

L’ajout de l’instance de liste se fait au moment de l’activation de la feature, la suppression au moment de la désactivation. Les propriétés de la datasource sont les mêmes que celles décrites dans la méthode précédente.

4 – Déployer la solution avec Visual Studio, la feature est alors automatiquement activée.

Package et features

La feature correspondant au type de contenu externe est déployée globalement au niveau Ferme, ce qui signifie que ce type de contenu sera accessible à toutes les applications web liées au Business Connectivity Service. Le même type de contenu externe ne peut donc pas être déployé 2 fois par 2 WSP différents sur la même ferme. Il convient donc de réfléchir en amont à l’organisation des solutions déployées.Mon WSP comprend donc :

  • 1 feature qui déploie mon type de contenu externe niveau ferme
  • 2 features qui déploient mes listes externes niveau web

Il convient de toujours nommer ses features en respectant des conventions de nommage définies au niveau de votre ferme SharePoint cible. Une petite image pour l’illustrer est toujours la bienvenue.

sharepoint package et features visual studio 2012