Ignorer les commandes du Ruban
Passer au contenu principal

Lancement rapide

Accueil
CPL-logo.png
janvier 25
[SharePoint 2010] BCS Partie 5: Visual Studio 2010 les associations

Série D'articles:

Introduction

Comme on a vu avec SharePoint designer on peut faire les associations entre les entités de votre BCS afin de mettre en place des vues Master/Details sur des associations. On va reprendre la création de notre BCS fait avec Visual Studio, on va lui ajouter une entité Site et on va faire les changements permettant de l'exploiter, on verra que suite à ces changements, on aura le même comportement qu'avec SharePoint Designer, pour l'instant on recherche le même comportement on verra par la suite les avantages à utiliser Visual Studio.

Avant de continuer on va se pencher sur la description de méthode et de méthode instance :

Modification de l'existant 

Premièrement on va supprimer le type descriptor « Site » dans le BDC Explorer.

Puis on va modifier le code des classes pour ne plus retourner « Site » :

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// This class contains the properties for Entity1. The properties keep the data for Entity1.

/// If you want to rename the class, don't forget to rename the entity in the model xml as well.

/// </summary>

public partial class RiseDocument

{

//TODO: Implement additional properties here. The property Message is just a sample how a property could look like.

public long DocID { get; set; }

public string MimeType { get; set; }

public string Title { get; set; }

public string Description { get; set; }

public string Langue { get; set; }

public byte[] Content { get; set; }

}

}

 

 

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.SqlClient;

using System.Data;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// All the methods for retrieving, updating and deleting data are implemented in this class file.

/// The samples below show the finder and specific finder method for Entity1.

/// </summary>

public class RiseDocumentService

{

/// <summary>

/// This is a sample specific finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <param name="id"></param>

/// <returns>Entity1</returns>

///

 

 

private static SqlConnection getSQLConnection()

{

SqlConnection _cnData;

_cnData = new SqlConnection("Data Source=srvsql; Initial Catalog=CMSRise;User ID=SA; Password=P@ssw0rd;");

_cnData.Open();

return _cnData;

}

public static RiseDocument ReadItem(long docID)

{

RiseDocument rd = new RiseDocument();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content " +

"where t_cms_u_Document.c_id=@docID";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

if (drData.Read())

{

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Content = (byte[])drData.GetValue(2);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

}

else

{

rd.DocID = -1;

rd.MimeType = "";

rd.Content = null;

rd.Title = "";

rd.Description = "";

rd.Langue = "";

 

}

 

 

}

}

return rd;

}

/// <summary>

/// This is a sample finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <returns>IEnumerable of Entities</returns>

public static IEnumerable<RiseDocument> ReadList()

{

List<RiseDocument> rds = new List<RiseDocument>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content ";

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseDocument rd = new RiseDocument();

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Content = (byte[])drData.GetValue(2);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

rds.Add(rd);

}

 

}

}

return rds;

}

 

}

}

 

 

Maintenant on peut passer à la création de notre entité <Site>

Création de nouvelles entités

On va commencer par le BCS designer :

On va nommer l'entité Site puis on va mettre un nouvelle identifier SiteID :

Sans oublier de mettre le bon type pour SiteID :

 

On ajoute les deux méthodes ReadList et ReadItem

Pour nous aider a designer les méthodes on utilisera le BDC Method Detail :

On va créer les paramètres pour ReadList :

Voici le contenu, on change le nom du type descriptor et la direction en Return :

Maintenant on va créer notre List Instance

Une Méthode instance permet de spécifier quand utiliser la méthode (retour de l'ensemble des entités, d'une seule entité, mise a jours d'une entité, suppression d'une entité…….)

 

On specifie le return parameter :

On va faire de même avec ReadItem :

On spécifie le return parameter :

 

Si l'on regarde dans le solution explorer on se rend compte qu'on n'a pas le site entity mais que le SiteService, on va donc créer la classe Site.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BDCRiseCMS.BdcModel1

{

public class RiseSite

{

public int SiteID { get; set; }

public String SiteName { get; set; }

}

}

 

 

Maintenant qu'on l'a créé on peut terminer le schema de notre BCS, dans le BDC explorer on va changer le type des type descriptor SiteRise et SiteRiseList :

Pour SiteRiseList on coche en plus is Enumerable :

SiteID :

 

On finit l'entité SiteRise :

SiteService a été généré par le designer :

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace BDCRiseCMS.BdcModel1

{

public partial class SiteService

{

public static IEnumerable<RiseSite> ReadList()

{

throw new System.NotImplementedException();

}

 

public static RiseSite ReadItem(int ID)

{

throw new System.NotImplementedException();

}

}

}

 

 

Avec le code :

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.SqlClient;

namespace BDCRiseCMS.BdcModel1

{

public partial class SiteService

{

private static SqlConnection getSQLConnection()

{

SqlConnection _cnData;

_cnData = new SqlConnection("Data Source=srvsql; Initial Catalog=CMSRise;User ID=SA; Password=P@ssw0rd;");

_cnData.Open();

return _cnData;

}

 

public static IEnumerable<RiseSite> ReadList()

{

List<RiseSite> lstRS = new List<RiseSite>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT c_id, c_u_Name FROM t_cms_u_Site" ;

 

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseSite rs=new RiseSite();

rs.SiteID = (int)drData.GetInt64(0);

rs.SiteName = drData.GetString(1);

lstRS.Add(rs);

}

}

}

return lstRS;

}

 

public static RiseSite ReadItem(int ID)

{

RiseSite rs = new RiseSite();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT c_id, c_u_Name FROM t_cms_u_Site " +

"where c_id=@ID";

cmdata.Parameters.AddWithValue("@ID", ID);

SqlDataReader drData = cmdata.ExecuteReader();

if (drData.Read())

{

rs.SiteID = drData.GetInt32(0);

rs.SiteName = drData.GetString(1);

}

else

{

rs.SiteID = -1;

rs.SiteName = "";

}

 

}

}

return rs;

}

}

}

 

Le résultat une fois la profile page terminé :

 

 

Mise en place de l'association

Très bien maintenant passons au plus simple, on va créer une association entre les deux entités, cette association générera une méthode dans chaque entité permettant de faire une vue Master/Details.

On ne remplit rien d'autre, seul le code sera à modifier :

Code dans SIteService

public static IEnumerable<RiseDocument> SiteToRiseDocument(int siteID)

{

List<RiseDocument> rds = new List<RiseDocument>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language " +

"FROM t_cms_u_Content INNER JOIN " +

"t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content INNER JOIN " +

"t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id WHERE (t_cms_u_Site.c_id = @siteID) ";

cmdata.Parameters.AddWithValue("@siteID", siteID);

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseDocument rd = new RiseDocument();

if(!drData.IsDBNull(0))

rd.DocID = drData.GetInt64(0);

if (!drData.IsDBNull(1))

rd.MimeType = drData.GetString(1);

if (!drData.IsDBNull(2))

rd.Content = (byte[])drData.GetValue(2);

if (!drData.IsDBNull(3))

rd.Title = drData.GetString(3);

if (!drData.IsDBNull(4))

rd.Description = drData.GetString(4);

if (!drData.IsDBNull(5))

rd.Langue = drData.GetString(5);

rds.Add(rd);

}

 

}

}

return rds;

 

}

 

 

Code dans RiseDocumentServices :

public static IEnumerable<RiseSite> RiseDocumentToSite(long docID)

{

List<RiseSite> lstRs = new List<RiseSite>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Site.c_id, t_cms_u_Site.c_u_Name "+

"FROM t_cms_u_Content INNER JOIN "+

"t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content INNER JOIN "+

"t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id WHERE (t_cms_u_Document.c_id = @docID) ";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseSite rs = new RiseSite();

rs.SiteID = (int)drData.GetInt64(0);

rs.SiteName = drData.GetString(1);

lstRs.Add(rs);

}

 

}

}

return lstRs;

}

 

 

Le résultat est le suivant :

Le master detail est bien en place. On a donc le même comportement qu'avec SharePoint Designer.

Résultat

Le résultat est proche de SharePoint designer, même si actuellement il est impossible d'indexer ce BCS. Ici on se rend compte que faire la même chose que SharePoint Designer n'est pas si simple avec Visual Studio, cependant à partir de maintenant les possibilités réélles de Visual Studio vont être utilisées.

janvier 18
[SharePoint 2010] BCS Partie 4: Visual Studio 2010

Série D'articles:

Introduction

J'ai beaucoup utilisé les BDC dans SharePoint 2007, il est clair que l'édition de fichiers XML était loin d'être la chose que j'appréciais le plus. Lorsque j'ai abordé les BCS avec SharePoint 2010 (pendant des BDC de SharePoint 2007) j'ai été ravi de voir qu'un éditeur BCS était présent dans Visual Studio. Puis ma joie a fait place à la déception. En effet il ne faut pas vous attendre à un éditeur qui fasse tout, il est là pour vous aider mais en aucune manière il est possible d'accéder au BCS sans connaitre le schéma BDCM. Par exemple l'éditeur de Visual Studio n'offre pas d'assistant directement vers SQL Server, ou une autre base de données ou même WCF. Tout doit être fait à la main.

 

L'application

L'application est simple, votre entreprise a fait le choix d'un ECM qui s'appelle RISE (ndlr : ce CMS est disponible dans la galerie Visual Studio).

Dans ce CMS pour l'administration de votre société certains documents ont été publiés. La demande est de créer un connecteur entre ce CMS et SharePoint. Vous avez donc la responsabilité de développer le connecteur.

Il peut être relativement aisé de développer une web part vers le CMS. Mais, on le verra à travers les différents articles, le fait de le faire par un BCS offrira beaucoup d'avantage non négligeable. On abordera aussi les limites de l'éditeur.

Création du projet

Dans Visual Studio on prendra le type de projet Business Data Connectivity Model :

Une fois le projet créé l'éditeur s'ouvre sur le model BDCM.

C'est ici qu'on va travailler le plus pour la configuration, pour le code on a deux class qui sont créés, Entity1 qui représente les données renvoyées, c'est entity1 qui représente le schéma du type de contenu, l'ensemble des champs de votre external content type correspondra à l'ensemble des propriétés de votre entité qui seront mappé dans le schéma BDCM. Ensuite on a Entity1Service qui représentes le chargement des données tous simplement.

On va commencer par donner des noms plus user friendly.

On va mettre RiseDocument à la place de « Entity1 » car on va remplir les entités en partant des tables Document et Content du CMS Rise.

La classe ainsi obtenue RiseDocument contiendra une propriété par champs pertinent de la table:

Voici le schéma des deux tables :

Voici le code de la classe RiseDocument

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// This class contains the properties for Entity1. The properties keep the data for Entity1.

/// If you want to rename the class, don't forget to rename the entity in the model xml as well.

/// </summary>

public partial class RiseDocument

{

//TODO: Implement additional properties here. The property Message is just a sample how a property could look like.

public long DocID { get; set; }

public string MimeType { get; set; }

public string Title { get; set; }

public string Description { get; set; }

public string Langue { get; set; }

public string site { get; set; }

public byte[] Content { get; set; }

}

}

 

Voici le code de la classe RiseDocumentService

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.SqlClient;

using System.Data;

 

namespace BDCRiseCMS.BdcModel1

{

/// <summary>

/// All the methods for retrieving, updating and deleting data are implemented in this class file.

/// The samples below show the finder and specific finder method for Entity1.

/// </summary>

public class RiseDocumentService

{

/// <summary>

/// This is a sample specific finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <param name="id"></param>

/// <returns>Entity1</returns>

///

 

 

private static SqlConnection getSQLConnection()

{

SqlConnection _cnData;

_cnData = new SqlConnection("Data Source=srvsql; Initial Catalog=CMSRise;User ID=SA; Password=P@ssw0rd;");

_cnData.Open();

return _cnData;

}

public static RiseDocument ReadItem(long docID)

{

RiseDocument rd = new RiseDocument();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language, t_cms_u_Site.c_u_Name " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content " +

"INNER JOIN t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id where t_cms_u_Document.c_id=@docID";

cmdata.Parameters.AddWithValue("@docID", docID);

SqlDataReader drData = cmdata.ExecuteReader();

if (drData.Read())

{

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Content = (byte[])drData.GetValue(2);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

rd.site = drData.GetString(6);

}

else

{

rd.DocID = -1;

rd.MimeType = "";

rd.Content = null;

rd.Title = "";

rd.Description = "";

rd.Langue = "";

rd.site = "";

 

}

 

 

}

}

return rd;

}

/// <summary>

/// This is a sample finder method for Entity1.

/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.

/// </summary>

/// <returns>IEnumerable of Entities</returns>

public static IEnumerable<RiseDocument> ReadList()

{

List<RiseDocument> rds = new List<RiseDocument>();

using (SqlConnection cndata = getSQLConnection())

{

using (SqlCommand cmdata = new SqlCommand())

{

cmdata.Connection = cndata;

cmdata.CommandText = "SELECT t_cms_u_Document.c_id, t_cms_u_Document.c_u_MimeType, " +

"t_cms_u_Document.c_u_Data, t_cms_u_Content.c_u_Title, t_cms_u_Content.c_u_Description, " +

"t_cms_u_Content.c_u_Language, t_cms_u_Site.c_u_Name " +

"FROM t_cms_u_Content INNER JOIN t_cms_u_Document ON t_cms_u_Content.c_id = t_cms_u_Document.c_r_Content " +

"INNER JOIN t_cms_u_Site ON t_cms_u_Content.c_r_Site = t_cms_u_Site.c_id";

SqlDataReader drData = cmdata.ExecuteReader();

while (drData.Read())

{

RiseDocument rd = new RiseDocument();

rd.DocID = drData.GetInt64(0);

rd.MimeType = drData.GetString(1);

rd.Content = (byte[])drData.GetValue(2);

rd.Title = drData.GetString(3);

rd.Description = drData.GetString(4);

rd.Langue = drData.GetString(5);

rd.site = drData.GetString(6);

rds.Add(rd);

}

 

}

}

return rds;

}

 

}

}

 

On va changer aussi le nom ET le type de l'identifier de notre entity RiseDocument :

Le BDC Explorer

Lorsque le model BCS est ouvert (et uniquement dans ce cas) une fenêtre apparait, le BDC Explorer :

Il peut être très pratique de mettre la fenêtre des propriétés en dessous du BDC Explorer, il sera ainsi plus facile de travailler avec les type descriptor, On renomme le model pour avoir des noms plus simple :

Pour cela on va utiliser la fenêtre des propriétés pour renommer les model.

Pour la methode ReadItem() :

On renomme l'identifier1 en DocID et les entités en dessous de returnparameter pour coller EXACTEMENT a ce que contient la classe RiseDocument, On ajoute des propriétés (ou type descriptor dans le cas du BDCExplorer) en faisant un clique avec le bouton droit et Add Type Descriptor :

Voici a quoi correspond notre entité :

Il faut bien paramétrer les TypeDescriptor (Nom et Type).

Une fois la partie ReadItem faites on va copier/coller l'entité DocRise en dessous de DocRiseList :

Voici le résultat final :

Quand on a terminé on lance le débuggueur, si vous avez mis des points d'arrêt dans le code ils apparaitront sur la page de profil.

Voici ce qu'on a dans la service application Business Data Service :

On retrouve RiseDocument, on va créer la page de profile en cochant la case à côté de RiseDocument et en cliquen sur Create/Upgrade :

On clique sur OK

Ensuite on va sur la page de profil en remplaçant {0} dans l'url par l'ID de la DB qu'on souhaite voir, ici 2 :

janvier 01
[SharePoint 2010] Bonne année et MVP une année de plus

Bonjour à tous je vous souhaite une très bonne année 2012.

Mon année démarre rapidement puisque je viens d'être renouvelé MVP pour un an de plusJ.

Le programme pour 2012 n'est pas encore définit clairement comme l'année dernière mais beaucoup de choses sont prévu, un ensemble d'article sur les BCS et deux release majeur pour le Pivot Viewer for SharePoint et le Thumbnail extender for SharePoint mais aussi deux autres projets en cours, Pivot Viewer for Office 365 et un quatrième en cours d'analyse.

Xavier VANNESTE

décembre 19
[Fast Search for SharePoint] Récupérer les Visual Best Bet et les Best Bet avec Keyword Query et Fast Search

Source : http://techmikael.blogspot.com/2011/12/returning-best-bets-and-visual-best.html

 

Quand vous utilisez les Best Bet ou Visual Best Bet dans le centre de rechercher SharePoint, celle-ci fonctionne parfaitement, cependant il est difficile de les faire fonctionner avec la classe de l'api KeywordQuery de SharePoint.

J'avais fait quelques recherches, après avoir été contacté par Xavier VANNESTE qui a blogué à propos de cette difficulté (http://blog.xvanneste.com/Lists/Billets/Post.aspx?ID=82 ), mais je n'avais pas été en mesure de résoudre cette issue à ce moment-là.

Etant actuellement en train d'écrire un livre sur FS4SP, j'ai dû me résoudre à trouver une solution. Le temps de sortir les outils!

Une heure plus tard après avoir utilisé le plugin Reflector pour Visual Studio a mettre des points d'arrêt dans le code des Search Service Application et j'ai compris. Et dans un sens, la solution fût évidente.

Tous les paramètres de mot clé avec FAST nécessitent un Search Setting Group et vous aurez un groupe pour chaque collection de sites dans votre batterie de serveurs SharePoint. L'ID du groupe de paramètre de recherche est le GUID de la collection de sites. Et cet ID est la solution.

 

KeywordQuery a une propriété nommée " UserContextGroupID ", et le MSDN déclare:

Obtient ou définit l'identifiant utilisé pour le groupe de mots clé correspondant au best bets et visual best bets.

En attribuant la propriété UserContextGroupID et en demandant de récupérer les SpecialTermResults cela fonctionne parfaitement.

 

Voici un petit exemple qui retourne les visual best bet attribué au terme «FAST Search for SharePoint" :

var searchProxy = (SearchServiceApplicationProxy)SearchServiceApplicationProxy.GetProxy(SPServiceContext.Current);

KeywordQuery kq = new KeywordQuery(searchProxy);

kq.QueryText = "FAST Search for SharePoint";

kq.ResultsProvider = SearchProvider.FASTSearch;

// specify best bets/visual best bets

kq.ResultTypes = ResultType.SpecialTermResults;

// specify the Search Settings Group ID

kq.UserContextGroupID = SPContext.Current.Site.ID.ToString();

ResultTableCollection resultTableCollection = kq.Execute();

ResultTable visualBestBetsTable = resultTableCollection[ResultType.VisualBestBetsResults];

foreach (DataRow row in visualBestBetsTable.Table.Rows)

{

string name = (string)row["Name"];

string uri = (string)row["Uri"];

string description = (string)row["Description"];

string keyword = (string)row["Keyword"];

string teaser = (string)row["Teaser"];

string contentType = (string)row["TeaserContentType"];

}

Article traduit avec l'accord de Mikael Svenson.

décembre 16
[SharePoint 2010] BCS Partie 3: Les Associations

Série D'articles:

Introduction

Faire un BCS pour une table sera relativement rare quand même, la plupart du temps vous utiliserez le BCS avec plusieurs tables et des associations entre elle.

L'avantage avec les BCS et qu'ils fournissent une vue master détail assez facilement. On le verra, avec SharePoint Designer on peut facilement créer les liens et faire des pages Master Details.

Préparation.

On va créer deux external content type comme vu précédemment un pour ProductSubCategory et un pour ProductCategory :

Create All Operation sur la table SubCat :

Name en Show in DataPicker

On n'oublie pas la création de la profile page:

Pareil pour la catégorie :

Comme on peut le voir les External Content Type sont regroupé par Namespace :

Comme dans cet article on n'a pas réécrit les namespaces l'url du site est prise par défaut pour faire les External Content Type.

Les relations

On va ré-ouvrir notre external content type Adventure Works.

Et cliquez sur

On revient sur le design de notre external content type.

On fait un clic avec le bouton droit sur la table qui a servie à faire l'external content type à savoir product et on clique sur new association :

On va le lier a un external content type en cliquant sur browse :

On selection sub cat car dans la DB on a un lien entre product et subcategorie.

SharePoint designer découvre de lui-même la relation.

On selectionne ProductSubCategoryID comme identifier :

On continue jusque la fin avec Next sans rien modifier.

On fait pareil avec SubCategory en faisant une relation avec Catégorie.

Une fois les relations faites il faut refaire les Profile page des Categorie et SubCategorie car leur page fera un Master Details (on sélectionne une catégorie on a les sourcategories et on sélectionne une sous-catégorie on a les produits).

Après avoir refait les profils pages on obtient :

La même chose avec les sous catégories :

Petite déception pas de liens actifs pour naviguer sur les produits ou les sous catégories à partir de la page parente.

XSLT

Pas grave on va éditer le XSLT :

On édite la page avec les catégories et on édite la webpart de navigation :

On clique sur XSL Editor :

Et on change la partie suivante :

<td class="ms-vb">

<xsl:attribute name="style">

<xsl:choose>

<xsl:when test="$dvt_1_form_selectkey = @*[name()=$ColumnKey]">color:blue</xsl:when>

<xsl:otherwise />

</xsl:choose>

</xsl:attribute>

<xsl:value-of select="@ProductSubcategoryID" />

</td>

   

Avec celle la :

   

<td class="ms-vb">

<xsl:attribute name="style">

<xsl:choose>

<xsl:when test="$dvt_1_form_selectkey = @*[name()=$ColumnKey]">color:blue</xsl:when>

<xsl:otherwise />

</xsl:choose>

</xsl:attribute>

<a>

<xsl:attribute name="href">

<![CDATA[http://srvmoss:80/_bdc/http___srvmoss/AdventureWorksSubCat_1.aspx?ProductSubcategoryID=]]><xsl:value-of select="@ProductSubcategoryID" />

</xsl:attribute>

<xsl:value-of select="@ProductSubcategoryID" />

</a>

</td>

   

Bien entendu la page profil doit être adaptée.

Le résultat est le suivant :

Il suffit de cliquer dessus pour naviguer sur la page de la sous-catégorie. Il suffira de faire de même avec la page des sous catégories pour naviguer vers produits.

1 - 5Suivante
 

 À propos de ce blog

 
À propos de ce blog
Bonjour,
Je suis VANNESTE Xavier, développeur depuis 10 ans sur les technologies microsoft, depuis 2002 sur la plateforme .NET et depuis 2003 sur SharePoint.
Ce site me permet de partager mes connaissances sur l'architecture, sur .Net et sur SharePoint.
 

 @xvanneste twitter

 
Extraction de données