Domanda

Sto facendo questo in SharePoint 2010, ma non sarei sorpreso se il problema esiste in SharePoint 2007 e ha la stessa soluzione.

Ho un trimmer di protezione runtime sui miei dati BDC. Mi aspettavo che il trimmer di protezione di darmi gli URL in base al largo del profilo URL "default" definito nel modello. Purtroppo, questo non è il caso. Mi dà un URL del tipo:    bdc3: // amms_amms / default / 00000000% 252d0000% 252d0000% 252d0000% 252d000000000000 / 1971 / AMM / 1973 S_ID = ibqaaaaaaaaa = & s_ce = 07nk0004080g10003o03vvf

Ho bisogno di ottenere le proprietà di questo oggetto (in realtà solo il valore della chiave primaria). Qualsiasi idea di come lo faccio con il modello a oggetti BDC? Il seguente link sembra fornire qualche aiuto, ma non ho visto nulla che consuma l'URL sopra.

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


Update: vedo che SharePoint 2007 ha un AccessChecker (http://msdn.microsoft.com/en-us/library/aa981124.aspx) e nel 2010 ha probabilmente anche questo (non riesce a trovare una buona documentazione per il 2010 su questo). Non possiamo avere facilmente descrittori di protezione nel database, ma il metodo AccessChecker potrebbe essere sufficiente.

Scavando un po 'più vedo che Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer è ciò che è probabile che ciò che viene utilizzato dal AccessChecker in SharePoint 2010. Sembra che questo fa una query al DB per URL. Sembra inefficiente anche se lo fa farlo su più thread (che, secondo la documentazione 2007 di fare). Penso che preferirei lotto backup delle informazioni in una singola chiamata di servizio web, ma sono sul recinto ...

È stato utile?

Soluzione

OK, ecco una semplificazione della mia risposta precedente. Sembra che si può assolutamente evitare di riflessione:

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;
}

Si noti che ho provato evitando di usare l'UriParser da Microsoft.Office.Server.Search.Connector utilizzando il codice come:

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

Purtroppo, questo ha funzionato per un po 'Id e non altri. Ho deciso di non indagare oltre e basta usare l'UriParser speciale. In un esempio gli ID che cercavo erano "5,20,21,7,8,6,14,19,17,18,4", ma questo secondo approccio mi ha dato "5,20,21,24581,8, 24580,24588,24593,17,24592,4" . Che mi ha incasinato per un paio di minuti da quando i primi 3 erano corrette.

Altri suggerimenti

Non sono sicuro che sia l'approccio migliore, ma ho ottenuto questo lavoro utilizzando Reflector per decodificare Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer. Ho solo bisogno il valore di identità in modo che questo un po 'semplificato.

Di seguito è riportato il mio codice che accetta un array di documentCrawlUrls forniti al trimmer di protezione e li traduce in una serie di chiavi primarie, come definito nel mio file di modello BDC. Una volta che ho coloro che posso determinare la per motivi di sicurezza con più codice personalizzato NET.

In CheckAccess () del mio trimmer di protezione (ISecurityTrimmer2) ho:

String[] ids = GetIds(documentCrawlUrls);

Poi ho il seguente metodo privato:

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;
}

Non ho voglia di riscrivere la classe SPBdcUri ed è interna, quindi io baro con la riflessione. Io attualmente uso solo uno dei parametri fuori in modo da poter migliorare l'efficienza. Posso riscrivere le porzioni di SPBdcUri che ho bisogno invece di ricorrere alla riflessione.

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, ecco le mie dichiarazioni "utilizzando":

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top