miércoles, 28 de julio de 2010

FileNotFoundException al crear un objeto SPSite en Visual Studio 2010

Hoy me he encontrado con un problema tonto, pero que me ha hecho perder un ratillo de trabajo, y es el siguiente:

He creado una aplicación de consola con Visual Studio 2010 y me he propuesto hacer un simple SPSite site = new SPSite("http://localhost");, me he quedado estupefacto cuando esta instrucción me ha lanzado una excepción del tipo FileNotFoundException. Al principio he pensado que era algo de temas de permisos y tal y he empezado a mirar detalladamente, pero nada todo parecía estar correcto.

Googleando he visto el siguiente hilo: http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopmentprerelease/thread/ae57f9f1-7a6c-48bc-95ac-2643b76867d8 y efectivamente, !!esto es lo que me pasaba a mi!!

Mi entorno es un entorno de 64bits donde tengo instalado mi granja de MSS 2010. Parece ser que cuando creas un proyecto de console application en visual studio 2010, queda configurado x86 como platform target, simplemente cambiando esto a x64 o Any CPU, funciona correctamente.

Para cambiarlo, hemos de acceder a las propiedades del proyecto y en la pestaña Build cambiar el dropdown de platform target.

martes, 27 de julio de 2010

Add managed properties programmatically

Siguiendo con el tema de búsqueda en MSS 2010, nos podemos encontrar que deseamos crear managed properties en tiempo de despliegue, por lo que necesitariamos de alguna forma poder crear managed properties dentro de un feature receiver por ejemplo. Antes de proceder comentar que si bien esto es posible, primero necesitariamos contar con crawled properties ya generadas (por ejemplo de nuestros metadatos), y para ello primero necesitariamos una primera indexación. Una vez comentado esto procederemos a explicar como provisionar estas managed properties.

Lo primero que deberiamos hacer es obtener el searchserviceapplication, para que a partir de este podamos obtener el schema. Esto lo vimos en el post anterior.



SPServiceContext serviceContext = SPServiceContext.GetContext(site);

SPServiceApplicationProxy proxy = serviceContext.GetDefaultProxy(typeof(SearchServiceApplicationProxy));
SearchServiceApplicationProxy searchAppProxy = proxy as SearchServiceApplicationProxy;

SearchServiceApplicationInfo ssai = searchAppProxy.GetSearchServiceApplicationInfo();
SearchServiceApplication application =
Microsoft.Office.Server.Search.Administration.SearchService.Service.SearchApplications.
GetValue(ssai.SearchServiceApplicationId);

Schema schema = new Schema(application);



Una vez tenemos esto podemos proceder a crear la managed property, una managed property consta principalmente de un nombre, un tipo de dato (text, integer, datetime), y un mapping con una o más crawled properties.



MappingCollection mappingCollection = new MappingCollection();

Microsoft.Office.Server.Search.Administration.ManagedProperty managedProperty = schema.AllManagedProperties.Create("My Managed Property", ManagedDataType.Text);


CrawledProperty crawledProperty = GetCrawledProperty(schema, "MyCrawledProperty", ManagedDataType.Text);
Mapping mapping = new Mapping(crawledProperty.Propset, crawledProperty.Name, crawledProperty.VariantType, managedProperty.PID);

mappingCollection.Add(mapping);


managedProperty.SetMappings(mappingCollection);

managedProperty.Update();



En este trozo de código podemos ver que hacemos una llamada a un método que nos devuelve una crawled property a partir del schema, un tipo y un nombre. A continuación muestro este método que se encarga de recorrer las crawled properties para obtener la que hemos solicitado.



protected CrawledProperty GetCrawledProperty(Schema schema, string name, ManagedDataType type)
{
CrawledProperty result = null;

foreach (CrawledProperty cproperty in schema.QueryCrawledProperties(string.Empty, 1000, Guid.NewGuid(), string.Empty, true))
{
if (cproperty.Name == name)
{
if (cproperty.VariantType == GetVariantType(type))
{
result = cproperty;
break;
}
}
}

return result;
}

protected int GetVariantType(ManagedDataType type)
{
switch (type)
{
case ManagedDataType.Text: return 31;
case ManagedDataType.Decimal: return 5;
case ManagedDataType.Integer: return 20;
case ManagedDataType.DateTime: return 64;
default: return 31;
}
}


Bueno, pues esto es todo.

lunes, 26 de julio de 2010

Crear exclude crawling rules programmatically 2010

Hace unos días comentaba como crear exclude crawling rules en Microsoft Office SharePoint Server 2007 , hoy haremos lo mismo pero ahora con Microsoft SharePoint Server 2010.


1. Obtener el Search Context a partir del SPSite



SPServiceContext serviceContext = SPServiceContext.GetContext(site);



2. Obtenemos el proxy del application service de search (esto es nuevo en 2010, como sabemos ahora desaparecido el shared service provider y tenemos una nueva arquitectura de servicios de aplicación)



SPServiceApplicationProxy proxy = serviceContext.GetDefaultProxy(typeof(SearchServiceApplicationProxy));
SearchServiceApplicationProxy searchAppProxy = proxy as SearchServiceApplicationProxy;



3. Obtenemos el objecto de la aplicación de search


SearchServiceApplicationInfo ssai = searchAppProxy.GetSearchServiceApplicationInfo();
SearchServiceApplication application =
Microsoft.Office.Server.Search.Administration.SearchService.Service.SearchApplications.
GetValue(ssai.SearchServiceApplicationId);



4. Obtenemos el Content Source a partir del objecto SerchApplication



Content content = new Content(application);



A partir de aquí es bastante parecido a como trabajabamos con MOSS 2007.

5. Añadir la crawl rule a la colección de crawlrules del content source


CrawlRule crawlRule = content.CrawlRules.Create(CrawlRuleType.ExclusionRule, "http://*/forms/*");



6. Añadir propiedades



crawlRule.FollowComplexUrls = true;



7. Commit la regla en la base de datos



crawlRule.Update();

martes, 13 de julio de 2010

Instalar sharepoint 2010 con un usuario local sí, pero no


Hace unos días comentaba que nos podiamos saltar la restricción que imponian desde Microsoft en cuanto a la instalación de un MSS 2010 (Microsoft SharePoint Server 2010) y creación de una granja bajo una cuenta de administrador local. Hoy he de decir que si que es posible, pero nos encontraremos problemas respecto al servicio de búsqueda.

Al intentar configurar el servicio de búsqueda e intentar realizar alguna búsqueda me encontraba con un error del tipo: "Internal server error exception".


Estirando del hilo, surfeando por logs e intentado descrifrar el porqué y cuando se producía este error llegue a ver otro error del tipo:

EnumerateQueryComponents returned an error after enumerating 0 components. Error returned was 0x80131600. cd74d139-25c5-4db5-8c81-a9b9a6e17b1f
07/13/2010 12:39:51.68 w3wp.exe (0x14D0) 0x151C SharePoint Server Search Query Processor e2tq High Source: Microsoft.Office.Server.Search Description: No query components were found for this search application.

Entonces dije, bueno pues voy a crear añadir un query component siguiendo los pasos que se indican aquí.

Al intentar finalizar el último paso me encontré de nuevo con otra barrera. Y con el siguiente error:

Component cbfb21b3-805b-4e3e-9c37-8339756385f9-query-0 of search application 'Search Service Application' has failed to execute transition sequence 'initialize with empty catalog' due to the following error: System.ArgumentException: The SDDL string contains an invalid sid or a sid that cannot be translated.

Por último googleando un poco más y buscando el error que me había dado encontre algunos post que hacian referencia a que no es compatible el servicio de búsqueda y una granja configurada con un usuario local.







jueves, 8 de julio de 2010

Ordenar listas en MOSS 2007

Si alguna vez nos hemos fijado en una lista de links, esta incorpora una action que nos permite ordenarla. Esta action lo que nos hace es llevarnos a una application page llamada reorder.aspx.

Luego puedes utilizar el campo order para ordenar los items en una content query webpart por ejemplo.

Tirando un poco más del hilo observas que toda item de cualquier lista, contiene ese campo order.

Y aquí es donde surge la pregunta: ¿por qué los señores de Redmond no han incorporado esto a todas las listas y así poder usar esta ordenación en las content query webparts?

Pensando que ha sido un despite, nos decidimos a incorporar esta funcionalidad a todas las listas creando una custom action y añadiendola a todas las listas. Pero cuál fue nuestro despiste que vimos que esta ordenación funcionaba bien excepto para las document libraries.

Haciendo un poquito de debugging y reflectoring vimos que el problema reside en el método que usa para ordenar las listas, este método es un método de la clase SPListItemCollection, el método se llama ReorderItems.

Ahora ya habiamos cruzado ese umbral que es más facil seguir para adelante que volverse para atrás así que nos decidimos a rehacer ese algoritmo de ordenación para que funcionase también con las document libraries.

En definitiva los artefactos que hemos creado han sido:

- Una custom action que se añade a todas las listas y su correspondiente feature
- Un page adapter para capturar el submit de la página reorder.aspx y a partir de aquí llamar a nuestro nuevo algoritmo de reordenación.
- Un extensión method para SPListItemCollection que implementa el algoritmo de ordenación.

martes, 6 de julio de 2010

Instalar sharepoint 2010 con un usuario local

Por defecto, el wizard de sharepoint 2010 no nos permite crear una granja a partir de una cuenta de usuario local, pero nos podemos saltar esta protección gracias a un comando de powershell, en concreto: New-SPConfigurationDatabase. Una vez creamos la base de datos de configuración a partir de este comando, podemos arrancar de nuevo el wizard de instalación y ya nos reconocera una base de datos de configuración que habrá sido creada y configurada con nuestro usuario local.

Para más info:

http://www.dev4side.com/community/blog/2010/5/2/how-to-install-sharepoint-2010-with-a-local-account.aspx