Question

Je fais cela dans SharePoint 2010, mais ne serait pas surpris si le problème existe dans SharePoint 2007 et a la même solution.

J'ai une coupe de sécurité d'exécution sur mes données BDC. Je me attendais à la taille de la sécurité pour me donner URL basées hors de l'URL du profil « par défaut » défini dans le modèle. Malheureusement, ce n'est pas le cas. Il me donne une URL comme:    BDC3: // amms_amms / default / 00000000% 252d0000% 252d0000% 252d0000% 252d000000000000 / 1971 / AMM / 1973 S_ID = ibqaaaaaaaaa = & s_ce = 07nk0004080g10003o03vvf

Je dois obtenir les propriétés de cet objet (vraiment juste la valeur de clé primaire). Toute idée comment je le fais avec le modèle d'objet BDC? Le lien suivant semble fournir une aide, mais je n'ai rien vu qui consume l'URL ci-dessus.

http://msdn.microsoft.com/en-us/library/ ee556400.aspx


Mise à jour: Je vois que SharePoint 2007 a une AccessChecker (http://msdn.microsoft.com/en-us/library/aa981124.aspx) et 2010 a probablement cela aussi bien (ne peut pas trouver une bonne documentation pour 2010 sur ce). Nous ne pouvons pas avoir facilement des descripteurs de sécurité dans la base de données, mais la méthode de AccessChecker pourrait suffire.

Creuser un peu plus loin je vois que Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer est ce qui est probablement ce qui est utilisé par le AccessChecker dans SharePoint 2010. Il semble que cela ne une requête à la base de données par URL. Il semble inefficace, même si elle ne le fait sur plusieurs threads (que les demandes de documentation 2007 à faire). Je pense que je préférerais traiter en lots l'information dans un appel de service Web unique, mais je suis sur la clôture ...

Était-ce utile?

La solution

OK, voici une simplification de ma réponse précédente. Il semble que vous pouvez totalement éviter la réflexion:

using Microsoft.BusinessData.Runtime;
using Microsoft.Office.Server.Search.Connector;
using Microsoft.Office.Server.Search.Query;    

private string[] GetIds(IList<string> documentCrawlUrls)
{
    string[] ids = new String[documentCrawlUrls.Count];
    for (int i = 0; i < documentCrawlUrls.Count; i++)
    {
        try
        {
            string url = documentCrawlUrls[i];
            string id = new Microsoft.Office.Server.Search.Connector.UriParser(new Uri(url)).QueryStringParameters["s_id"];
            ids[i] = Identity.Deserialize(id).GetIdentifierValues()[0].ToString();
        }
        catch (Exception ex)
        {
            System.Diagnostics.Trace.WriteLine("Error: " + ex.Message);
        }
    }

    return ids;
}

Notez que j'ai essayé d'éviter l'utilisation du UriParser de Microsoft.Office.Server.Search.Connector en utilisant le code comme:

string id = HttpUtility.ParseQueryString(new Uri(url).Query)["s_id"];
ids[i] = Identity.Deserialize(id.ToUpper()).GetIdentifierValues()[0].ToString();

Malheureusement, cela a fonctionné pour certains de Id et pas d'autres. J'ai décidé de ne pas enquêter plus loin et il suffit d'utiliser la UriParser spéciale. Dans un exemple les ids que je recherchais étaient « 5,20,21,7,8,6,14,19,17,18,4 », mais cette seconde approche m'a donné « 5,20,21,24581,8, 24580,24588,24593,17,24592,4" . Cela me foiré pendant quelques minutes depuis les 3 premiers étaient corrects.

Autres conseils

Je ne suis pas sûr qu'il est la meilleure approche, mais je me suis que cela fonctionne en utilisant réflecteur pour désosser Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer. Je ne avais besoin la valeur d'identité de sorte que simplifié un peu.

Voici mon code qui prend un tableau de documentCrawlUrls fourni à la taille de la sécurité et les traduit dans un tableau de clés primaires telles que définies dans mon dossier de modèle BDC. Une fois que j'ai ceux que je peux déterminer la sécurité rognage à l'aide du code .NET plus personnalisé.

Dans CheckAccess () de ma coupe de sécurité (ISecurityTrimmer2) Je:

String[] ids = GetIds(documentCrawlUrls);

J'ai la méthode privée suivante:

private string[] GetIds(IList<string> documentCrawlUrls)
{
    string[] ids = new String[documentCrawlUrls.Count];
    for (int i = 0; i < documentCrawlUrls.Count; i++)
    {
        try
        {
            string url = documentCrawlUrls[i];

            Identity identity = null;
            IEntity entity = null;
            ILobSystemInstance lsi = null;
            ParseUri(url, out entity, out identity, out lsi);
            if (identity != null)
            {
                object[] values = identity.GetIdentifierValues();
                if (values.Length > 0)
                {
                    ids[i] = values[0].ToString();
                }
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Trace.WriteLine("Error: " + ex.Message);
        }
    }

    return ids;
}

Je ne voulais pas réécrire la classe SPBdcUri et il est interne, donc je triche avec la réflexion. J'utilise actuellement un seul des paramètres sur que je puisse améliorer l'efficacité. Je peux réécrire les portions de SPBdcUri que j'ai besoin au lieu de recourir à la réflexion.

private void ParseUri(string crawlUri, out IEntity entity, out Identity identity, out ILobSystemInstance lsi)
{
    //SPBdcUri uri = new SPBdcUri(new Uri(crawlUri));
    AssemblyName assemblyName = new AssemblyName("Microsoft.Office.Server.Search.Connector, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");
    Assembly assembly = Assembly.Load(assemblyName);
    Type spBdcUriType = assembly.GetType("Microsoft.Office.Server.Search.Connector.BDC.SPBDC.SPBdcUri");
    object uri = Activator.CreateInstance(spBdcUriType,
        BindingFlags.NonPublic | BindingFlags.Instance,
        null, new object[] { new Uri(crawlUri) }, System.Globalization.CultureInfo.CurrentCulture);

    //uri.DoOverrideBDCThrottlingLimits = false;
    spBdcUriType.InvokeMember("DoOverrideBDCThrottlingLimits",
        BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty,
        null, uri, new object[] { false });

    //entity = uri.Entity;
    object entityObj = spBdcUriType.InvokeMember("Entity",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
        null, uri, null);
    entity = (IEntity)entityObj;

    //identity = uri.Identity;
    object identityObj = spBdcUriType.InvokeMember("Identity",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
        null, uri, null);
    identity = (Identity)identityObj;

    //lsi = uri.LobSystemInstance;
    object lsiObj = spBdcUriType.InvokeMember("LobSystemInstance",
        BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty,
        null, uri, null);
    lsi = (ILobSystemInstance)lsiObj;
}

Oh, voici mes déclarations "en utilisant":

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

using Microsoft.BusinessData.MetadataModel.Collections;
using Microsoft.BusinessData.MetadataModel;
using Microsoft.BusinessData.Runtime;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.BusinessData.SharedService;
using Microsoft.Office.Server.Search.Query;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top