Pregunta

Estoy haciendo esto en SharePoint 2010, pero no me sorprendería si el problema está en SharePoint 2007 y tiene la misma solución.

Tengo un optimizador de seguridad en tiempo de ejecución en mis datos de BDC. Yo estaba esperando el optimizador de seguridad para darme las direcciones URL con sede fuera de la URL del perfil "default" se define en el modelo. Desafortunadamente, ese no es el caso. Me da una URL como:    bdc3: // amms_amms / default / 00000000% 252d0000% 252d0000% 252d0000% 252d000000000000 / 1971 / AMM / 1973 S_ID = ibqaaaaaaaaa = & s_ce = 07nk0004080g10003o03vvf

necesito para obtener las propiedades de este objeto (en realidad sólo el valor de la clave primaria). ¿Alguna idea de cómo hacer esto con el modelo de objetos de BDC? En el siguiente enlace parece proporcionar un poco de ayuda, pero no he visto nada que consume la URL anterior.

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


Actualización: Me ver que SharePoint 2007 tiene una AccessChecker (http://msdn.microsoft.com/en-us/library/aa981124.aspx) y 2010 es probable que tenga esto también (no puede encontrar una buena documentación para el año 2010 en este). No podemos tener fácilmente los descriptores de seguridad en la base de datos, pero el método AccessChecker puede ser suficiente.

Excavar un poco más veo que Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer es lo que es probable que lo que se utiliza por el AccessChecker en SharePoint 2010. Parece que este hace una consulta a la base de datos por cada URL. Parece ineficaz incluso si lo hace hacerlo en varios subprocesos (que según la documentación 2007 para hacer). Creo que preferiría lote de seguridad de la información en una sola llamada de servicio web, pero estoy en la valla ...

¿Fue útil?

Solución

OK, he aquí una simplificación de mi respuesta anterior. Parece que se puede evitar totalmente la reflexión:

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

Tenga en cuenta que he intentado evitar el uso de la UriParser de Microsoft.Office.Server.Search.Connector utilizando código como:

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

Por desgracia, esto funcionó para algunos de Id y no a otros. Decidí no seguir investigando y sólo tiene que utilizar el UriParser especial. En un ejemplo de los identificadores que estaba buscando eran "5,20,21,7,8,6,14,19,17,18,4", pero este segundo enfoque me dieron "5,20,21,24581,8, 24580,24588,24593,17,24592,4" . Eso me mal estado durante unos minutos desde la primera 3 eran correctas.

Otros consejos

No estoy seguro de que es el mejor enfoque, pero tengo a este trabajo mediante el uso de reflector para revertir Microsoft.Office.Server.Search.Connector.BDC.BdcSecurityTrimmer ingeniero. Sólo necesitaba el valor de identidad para que simplifica esto un poco.

A continuación se muestra el código que toma una matriz de documentCrawlUrls proporcionadas a la optimizador de seguridad y las traduce en un conjunto de claves primarias como se definen en mi archivo de modelo BDC. Una vez que tengo los puedo determinar la seguridad de recorte con más código personalizado .NET.

En CheckAccess () de mi optimizador de seguridad (ISecurityTrimmer2) Tengo:

String[] ids = GetIds(documentCrawlUrls);

A continuación, tengo el siguiente método privado:

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

Yo no quería volver a escribir la clase SPBdcUri y es interna, por lo que hago trampa con la reflexión. Yo sólo uso actualmente uno de los parámetros out para que pueda mejorar en eficiencia. Puedo volver a escribir las partes de SPBdcUri que necesito en lugar de recurrir a la reflexión.

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, aquí está mis declaraciones "utilizando":

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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top