2010-09-28 11 views
0

Je le fais dans SharePoint 2010, mais ne serais pas surpris si le problème existe dans SharePoint 2007 et a la même solution. J'ai un trimmer de sécurité d'exécution sur mes données BDC. Je m'attendais à ce que le tondeur de sécurité me donne des URL basées sur l'URL de profil "par défaut" définie 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 = 07nk0004080g10003o03vvfComment charger des données BDC à partir d'une URL BDC?

J'ai besoin pour obtenir les propriétés? de cet objet (vraiment juste la valeur de la clé primaire). Une idée de comment je fais cela avec le modèle d'objet BDC? Le lien suivant semble fournir de l'aide, mais je n'ai rien vu qui consomme 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 (Impossible de trouver une bonne documentation pour 2010 à ce sujet). Nous ne pouvons pas facilement avoir des descripteurs de sécurité dans la base de données, mais la méthode AccessChecker peut suffire. En creusant un peu plus loin, je vois que Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer est ce qui est probablement ce qui est utilisé par AccessChecker dans SharePoint 2010. Il semble que cela fasse une requête à la base de données par URL . Semble inefficace même s'il le fait sur plusieurs threads (que la documentation 2007 prétend faire). Je pense que je préférerais regrouper les informations dans un seul appel de service Web, mais je suis sur la clôture ...

+0

Sharepoint 2010 n'a pas de "BDC" il a "BCS" –

+0

Il a été renommé, mais BCS dans SharePoint 2010 contient des fichiers de modèle BDC et cet acronyme est utilisé dans l'API SharePoint 2010. –

Répondre

1

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.Connecteur 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 ID et pas d'autres. J'ai décidé de ne plus faire d'enquête et d'utiliser le UriParser spécial. Dans un exemple, les identifiants que je cherchais é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, 24952, 4 ". Cela m'a dérangé pendant quelques minutes puisque les 3 premières étaient correctes.

0

Je ne suis pas sûr que ce soit la meilleure approche, mais j'ai eu ce travail en utilisant Reflector à reverse engineering Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer. J'avais seulement besoin de la valeur d'identité pour que cela soit simplifié un peu. Ci-dessous est mon code qui prend un tableau de documentCrawlUrls fourni au coupe-bordure de sécurité et les traduit en un tableau de clés primaires tel que défini dans mon fichier de modèle BDC. Une fois que j'ai ceux que je peux déterminer la coupe de sécurité en utilisant plus de code .NET personnalisé.

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

String[] ids = GetIds(documentCrawlUrls); 

Ensuite, je 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 c'est interne, alors je triche avec la réflexion. Actuellement, je n'utilise que l'un des paramètres out pour améliorer mon efficacité. Je peux réécrire les parties de SPBdcUri dont 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 mon "en utilisant" déclarations:

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;