Dans le précédent post, je vous ai montré comment créé une définition de liste et lier un ContentType à cette liste de la façon suivante :
QuizzListDefinition > schema.xml
1: <?xml version="1.0" encoding="utf-8"?>
2: <List Title="QuizzListDefinition" FolderCreation="FALSE"
3: Direction="$Resources:Direction;" Url="Lists/Quizz List" BaseType="0">
4: <MetaData>
5: <ContentTypes>
6: <ContentTypeRef ID="0x010081DA7661E43E254B8B4F823AA9A3F578"/>
7: <ContentTypeRef ID="0x0120" />
8: </ContentTypes>
9: <Fields>
10: <!-- Copier coller des champs QuestionMenu et NoMenu -->
11: </Fields>
12: <Views>
13: <View BaseViewId="0" Type="HTML"><!-- ... --></View>
14: <View BaseViewID="1" Type="HTML" WebPartZoneID="Main"
15: DisplayName="$Resources:core,objectiv_schema_mwsidcamlidC24;"
16: DefaultView="TRUE" SetupPath="pages\viewpage.aspx"
17: ImageUrl="/_layouts/images/generic.png" Url="AllItems.aspx">
18: <!-- ... -->
19: <ViewFields>
20: <FieldRef Name="QuizzQuestionMenu" />
21: <FieldRef Name="QuizzChoices" />
22: <FieldRef Name="QuizzAnswers" />
23: <FieldRef Name="QuizzCategory" />
24: </ViewFields>
25: <Query><!-- ... --></Query>
26: </View>
27: </Views>
28: <Forms><!-- ... --></Forms>
29: </MetaData>
30: </List>
Comme je disais précédemment, Le fait de réferencer le ContentType (<ContentTypeRef ID="0x010081DA7661E43E254B8B4F823AA9A3F578"/>) n'est pas suffisant pour faire le lien entre le ContentType et la liste.
Pour que cela fonctionne, il faudrait mettre en plus les colonnes de site du ContentType dans les champs de la liste... Bref dupliquer la définition du ContentType. Pas terrible...
Haut les coeurs, il existe une solution plus élégante qui permet de faire fonctionner la definition de liste ci-dessus.
Cette solution provient d'un dénommé Martin Hatch dans son billet sur [Code Update] SDK and Microsoft Press Both Wrong?? Custom Fields in the schema.xml.
Pour faire simple. Martin s'est rendu compte qu'il est possible de ne pas avoir à dupliquer les informations du ContentType en exécutant la manipulation suivante :
- Création d'un ContentType
- Création d'une définition de liste
- Ajout du ContentTypeRef dans la définition de la liste
- Activation de la feature définissant le ContentType
- Accè à la gallerie de ContentType et modification du ContentType (modifier un champ, supprimer, renommer, qu'importe)
- Activation de la feature de la définition de liste
- Création de la liste et verifier que le ContentType est bien référéncer et que les colonnes de site sont présentes
Assez étrange, comme comportement me direz vous, mais en tout cas ça fonctionne :)
Maintenant, il faut pouvoir automatiser tout ça. La solution donnée par Martin est de rajouter un FeatureReceiver à la feature du ContentType, quequechose dans ce style :
ContentTypeQuizz > feature.xml
1: <?xml version="1.0"?>
2: <Feature xmlns="http://schemas.microsoft.com/sharepoint/"
3: Id="08BF6137-EDD2-4401-A536-2A37766D49AC"
4: Title="$Resources:FeatureTitle;"
5: Description="$Resources:FeatureDescription;"
6: Scope="Site"
7: Hidden="True"
8: DefaultResourceFile="_Res"
9: ReceiverAssembly="SharePointOfView, Version=1.1.0.0, Culture=neutral, PublicKeyToken=85a56337686e234b"
10: ReceiverClass="SharePointOfView.EventReceivers.ContentTypeUpdaterFeatureReceiver"
11: Version="1.0.0.0">
12: <ElementManifests>
13: <ElementManifest Location="elements.xml" />
14: </ElementManifests>
15:
16: </Feature>
Le fichier elements.xml est un fichier classique de définition de ContentType.
ContentTypeQuizz > elements.xml
1: <?xml version="1.0"?>
2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
3: <ContentType ID="0x010081DA7661E43E254B8B4F823AA9A3F578" Name="QuizzItem" Group="Demo" Version="12" xmlns="http://schemas.microsoft.com/sharepoint/" Hidden="False" ReadOnly="False" Sealed="False">
4: <FieldRefs>
5: <FieldRef ID="{3bfd9f63-3c57-4a0d-b22a-3ed324150348}" Name="$Resources:Quizz,Quizz_Field_Question;" Required="TRUE" Hidden="FALSE" ReadOnly="FALSE" />
6: <FieldRef ID="{48b006bf-5e14-43cb-b5cb-9a3dae4f0646}" Name="$Resources:Quizz,Quizz_Field_Category;" Required="TRUE" Hidden="FALSE" ReadOnly="FALSE" />
7: <FieldRef ID="{71d78a3d-eaad-4e6e-b905-e183cf774693}" Name="$Resources:Quizz,Quizz_Field_Choices;" Required="TRUE" Hidden="FALSE" ReadOnly="FALSE" />
8: <FieldRef ID="{2a3f841f-ff0a-4348-9028-cf5e0a16a089}" Name="$Resources:Quizz,Quizz_Field_Answers;" Required="TRUE" Hidden="FALSE" ReadOnly="FALSE" />
9: <RemoveFieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" />
10: </FieldRefs>
11: </ContentType>
12: </Elements>
Si vous suivez mes posts, vous aurez compris que j'ai tendance à mettre tout ce qui peut être réutilisable dans notre projet Codeplex : SharePointOfView. Du coup, vous pourrez d'ailleurs retrouver dans les derniers check-ins, le FeatureReceiver "ContentTypeUpdaterFeatureReceiver" (Le code de ce FeatureReceiver est la propriété de Martin Hatch comme précisé dans la description de la fonction)
Nous avons maintenant fait le tour de toute la plomberie nécéssaire au fonctionnement de l'application. Dans le prochain post, je vous parlerai d'un outil développé par Adrien Siffermann et moi-même qui permet de déployer des WSP, de créer du "contenu SharePoint" (WebApplication, SiteCollection, Site, List, Items, WebPart, etc.) et pleins d'autre fonctionnalités...
J'utiliserai cet outil pour créer mon environnement SharePoint pour ce projet :
- Upload de la Solution
- Création de la WebApplication
- Déploiement de la Solution
- Création de la SiteCollection
- Activation des Features
- Création d'une liste Quizz Animaux basé sur notre ListDefinition
- Ajout de catégories dans la liste Quizz Catégories
- Ajout de Questions à la liste Quizz Animaux.
Le tout en une ligne de commande : SharePointDataPopulate.Client.exe" -filename "Demo.SharePoint.Quizz.Orijin.Local.xml" -verbose.
PS : On cherche encore un nom pour cet outil :)
<Philippe/>