none
CrossListQueryInfo, CrossListQueryCache, et multiple audiences RRS feed

  • Question

  • Bonjour à tous !

    J'utilise un webpart custom, pour recupérer des pages de types publishing et les afficher. A l'interieur j'utilise pour le requettage à rpoprement dit les classes CrossListQueryInfo et CrossListQueryCache.

    Lorsque j'utilise le parametre "ApplyAudience" et que mes items ont plusieurs audiences assignées, le composant de requettage applique un "OU" entre chaque audience :

    Item1 target AudienceA et AudienceB -> Item1 visible si l'utilisateur en face appartient à l'audience AudienceA OU AudienceB.

    Est-il possible de faire en sorte que le filtre soit de type "ET" ?

    Sachant que je ne peut pas tellement préparer les combinaisons d'audiences de type ET au préalable vu le nombre de combinaisons possibles : j'ai un referentiel de 100 à 200 audiences "unitaires", et je peux avoir de 1 à 4 audiences selectionnées sur chaque item....

    Une idée ?

    Merci

    Lio

    vendredi 24 février 2012 08:21

Réponses

  • Exact, je suis à coté de la plaque...

    Bon, sinon j'ai utilisé mon ami Reflector :

    En fait le CrossListQueryCache semble effectuer la requete interne sans utiliser les audiences. C'est uniquement après la requète qu'il appelle FilterContentByQueryListItemsByAudience();

    Cette méthode ne fait que filtrer les éléments suivants les audiences de l'utilisateur.

    Donc il est peut être possible de mettre la propriété "FilterByAudience" à false, puis de faire le filtrage par audience manuellement...
    Et analyser contenu de la méthode "FilterContentByQueryListItemsByAudience" (private) pour voir si c'est possible

    Petite précision : j'ai regardé sur SP2007 uniquement...


    Sylvain Reverdy
    Consultant / Formateur Winwise à Tahiti
    Mon blog
    Twitter : @sreverdy

    vendredi 24 février 2012 17:22
    Auteur de réponse
  • Salut Sylvain. Merci pour ta réponse ! j'avais prévu d'inviter notre ami commun Reflector ;) ce WE à la maison ! du coup tu l'as fait pour moi, c'est sympa ! En plus cet appel à FilterContentByQueryListItemsByAudience() est bien caché  !:)

    Bon je pensais que l'audience servait en amont pour requetter encore moins de données de la base, mais c'est manifestement pas le cas. Donc au niveau perfs je n'aurais effectivement pas tellement plus d'impact à faire le filtrage moi même.

    Pour la petite histoire, la méthode que tu m'indique utilise pour le fitrage cette autre méthode : AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceTextRepresentation, this.queryInfo.ShowUntargetedItems)) et c'est elle qui fait le critère "OU" à proprement dit puisque pour chaque audience si l'utilisateur courant en fait partie, il positionne un flag à true , flag qui est utilisé comme retour, donc une seule suffit:

      foreach (string str in globalAudienceIDs)
            {
                bool isMember = audienceLoader.IsUserMemberOfGlobalAudience(str);
                AudienceLoader.RegisterAudienceFetchedDuringPageRequest(new Guid(str), isMember);
                if (isMember)
                {
                    flag = true;
                }
            }

    Enfin pour partager sur le même sujet je me demandais pourquoi le RowLimit que j'utilisais sur ma CrossListQueryInfo devait etre multiplié par 5 à partir du moment où j'activais le filtre par audience. Valeur trouvée plus par experimentation qu'autre chose. Et bien la réponse est dans la fonction mais avec un algo que j'ai du mal à comprendre pour le moment :) :

     int num = 0;
            uint num2 = this.queryInfo.RowLimit / 5;
            AudienceLoader audienceLoader = AudienceLoader.GetAudienceLoader();
            List<DataRow> list4 = new List<DataRow>();
            foreach (DataRow row2 in this.results.Data.Rows)
            {
                string audienceTextRepresentation = row2[this.queryInfo.AudienceFieldId] as string;
                if ((num >= num2) || !AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceTextRepresentation, this.queryInfo.ShowUntargetedItems))
                {
                    list4.Add(row2);
                    continue;
                }
                num++;
            }

    Merci pour l'info en tout cas!

    p.s. : j'ai bien la même chose sur SP2010 puisque le code viens de là :)




    samedi 25 février 2012 14:34

Toutes les réponses

  • Bonjour,

    Une solution serait ce créer un RuntimeFilter custom :
    C'est le mécanisme standard SharePoint pour les audiences sur les webparts.

    Vous pourrez ainsi controler dans quel cas on doit ou non cacher la webpart.

    Un bon post en parle :
    http://blog.mastykarz.nl/content-targeting-anonymous-users-sharepoint-server-2010-part2-2/

    ++


    Sylvain Reverdy
    Consultant / Formateur Winwise à Tahiti
    Mon blog
    Twitter : @sreverdy

    vendredi 24 février 2012 09:24
    Auteur de réponse
  • Salut Sylvain,

    Merci pour l'info. Malheureusement ça ne semble pas correspondre à mon besoin ds la mesure (à valider) où le RuntimeFilter ne semble intervenir que dans la cas d'utilisation d'audience sur un webpart.

    Dans mon cas l'audience(s)  est/sont positionnées sur chaque items que le webpart doit afficher...

    vendredi 24 février 2012 09:41
  • Exact, je suis à coté de la plaque...

    Bon, sinon j'ai utilisé mon ami Reflector :

    En fait le CrossListQueryCache semble effectuer la requete interne sans utiliser les audiences. C'est uniquement après la requète qu'il appelle FilterContentByQueryListItemsByAudience();

    Cette méthode ne fait que filtrer les éléments suivants les audiences de l'utilisateur.

    Donc il est peut être possible de mettre la propriété "FilterByAudience" à false, puis de faire le filtrage par audience manuellement...
    Et analyser contenu de la méthode "FilterContentByQueryListItemsByAudience" (private) pour voir si c'est possible

    Petite précision : j'ai regardé sur SP2007 uniquement...


    Sylvain Reverdy
    Consultant / Formateur Winwise à Tahiti
    Mon blog
    Twitter : @sreverdy

    vendredi 24 février 2012 17:22
    Auteur de réponse
  • Salut Sylvain. Merci pour ta réponse ! j'avais prévu d'inviter notre ami commun Reflector ;) ce WE à la maison ! du coup tu l'as fait pour moi, c'est sympa ! En plus cet appel à FilterContentByQueryListItemsByAudience() est bien caché  !:)

    Bon je pensais que l'audience servait en amont pour requetter encore moins de données de la base, mais c'est manifestement pas le cas. Donc au niveau perfs je n'aurais effectivement pas tellement plus d'impact à faire le filtrage moi même.

    Pour la petite histoire, la méthode que tu m'indique utilise pour le fitrage cette autre méthode : AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceTextRepresentation, this.queryInfo.ShowUntargetedItems)) et c'est elle qui fait le critère "OU" à proprement dit puisque pour chaque audience si l'utilisateur courant en fait partie, il positionne un flag à true , flag qui est utilisé comme retour, donc une seule suffit:

      foreach (string str in globalAudienceIDs)
            {
                bool isMember = audienceLoader.IsUserMemberOfGlobalAudience(str);
                AudienceLoader.RegisterAudienceFetchedDuringPageRequest(new Guid(str), isMember);
                if (isMember)
                {
                    flag = true;
                }
            }

    Enfin pour partager sur le même sujet je me demandais pourquoi le RowLimit que j'utilisais sur ma CrossListQueryInfo devait etre multiplié par 5 à partir du moment où j'activais le filtre par audience. Valeur trouvée plus par experimentation qu'autre chose. Et bien la réponse est dans la fonction mais avec un algo que j'ai du mal à comprendre pour le moment :) :

     int num = 0;
            uint num2 = this.queryInfo.RowLimit / 5;
            AudienceLoader audienceLoader = AudienceLoader.GetAudienceLoader();
            List<DataRow> list4 = new List<DataRow>();
            foreach (DataRow row2 in this.results.Data.Rows)
            {
                string audienceTextRepresentation = row2[this.queryInfo.AudienceFieldId] as string;
                if ((num >= num2) || !AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceTextRepresentation, this.queryInfo.ShowUntargetedItems))
                {
                    list4.Add(row2);
                    continue;
                }
                num++;
            }

    Merci pour l'info en tout cas!

    p.s. : j'ai bien la même chose sur SP2010 puisque le code viens de là :)




    samedi 25 février 2012 14:34