Wednesday, September 21, 2011

SharePoint 2010 Web Content Management

Este video merece la pena ser divulgado, excelente presentación del tema.



Feliz wcm!!

AddContentDB Access Denied Error

Hola de nuevo. Se me han ido creo que aproximadamente entre probando, leyendo blogs, tomando café, y bueno, unas cuantas cosas más, unas 12 a 14 hrs de mí tiempo, tratando de hacer lo siguiente:

1. Mi cliente quiere renombrar la base de datos de contenido de la administración central: Por ejemplo de esto, SharePoint_AdminContent_66877b93-3d3a-4dd1-b90f-399670de5e7b a esto SharePoint_AdminContent, y tiene razón, ese nombre con ese GUID da escalofrios.

2. Es de un cuidado extremo esta tarea, porque entre los pasos, se debe desasociar la BDs de Contenido de nada menos y nada más que la Administración Central. Por eso hagan Backup!!

3. Pero entre tanto blog, entre tanto Foro, puedo ver de regreso a gente descuidada, que finalmente ayuda a medias.

4. Lo que ocurre es que por algún motivo al ejecutar el comando del STSADM, por ejemplo:

C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\BIN>stsa
dm -o addcontentdb -url http://centraladminsite:puerto -databasename SharePoint_AdminContent

De donde lo que se evidencia es la intención de volver a asociar la BDs de contenido nueva con el sitio de Administración Central, produce un error de Acceso negado.

El blog con los pasos pero incompleto es este: http://guru-web.blogspot.com/2007/03/renaming-central-admin-content-database.html

El foro que me motivó a la solución es este: http://www.office-outlook.com/outlook-forum/index.php/m/672431/

Pero aun se quedan incompletos, porque seguirá dando error de Acceso Negado hasta que no se detenga el servicio de Windows llamado Windows SharePoint Services Timer y se vuelva a iniciar.

Al final la administración central deberá funcionar y quedar asociada a una BDs de contenido re-bautizada, digamos con un nombre más elegante.

Felíz re-bautizo

Wednesday, September 14, 2011

SharePoint answers

Hola de nuevo. De casualidad entré a un enlace de Twitter y llegué a un sitio bastante interesante de SharePoint. Es una especie de Foro on steroids, y navegando dí con una pregunta, la cual en unos 10 minutos, lei, probé en SharePoint 2010 y pude entregarle una respuesta al autor. De paso revisen el JavaScriopt de ese genio porque está bastante bueno, es algo así como para detectar si tenes Silverligth instalado.

Question

Felíz answer!!

Monday, September 12, 2011

SharePoint Microsoft Community Specialist

Hace varios años que vengo colaborando y ayudando en muchos temas a la comunidad Microsoft. Ahora me llegan a la mente INETA, Celulas Microsoft, Influencers, y bueno, charlas y particpación en eventos, donde llama la atención el interés de Microsoft por promover sus tecnologías, pero tratando de hacerlo bien, y llegando de la mejor manera a su amplia comunidad de desarrolladores.

Ahora me llega un nuevo reto, que Microsoft lo ha llamado "Especialista de comunidad", en mí caso, por un interés grande en SharePoint, y que espero a través de estos canales de Web 2.0 seguir aportando con algo para que exista información y soluciones puntuales a problemáticas, nuevas ideas, y en general tela de donde cortar sobre la plataforma SharePoint.

Gracias a Microsoft por este nuevo reconocimiento y al buen amigo Walter Novoa.

Friday, September 09, 2011

WebPart ASCX en SharePoint 2007 con WSP Builder

Hola de nuevo. A continuación les comparto una de mis demostraciones de los pasos básicos a seguir cuando queremos crear una WebPart con un control de usuario ASCX para SharePoint 2007.

Esto tiene ventajas obvias sobre la creación de WebParts que requieren la implementación manual y agregación de cada control a renderizar y por supuesto programar a nivel de eventos en la WebPart.

El ejemplo hace uso de Visul Studio .NET 2008, WSPBuilder y MOSS 2007. Esto también podría hacerse para WSS 3.0 sin ningún problema. WSPBuilder es la herramienta recomendada para las tareas de desarrollo sobre SP 2007.


Thursday, September 08, 2011

SharePoint en el lado del cliente - JQuery

Suelo hablar poco de las tecnologías y menos tratar de filosofar, prefiero remitirlos a los "gurus" y por supuesto a algún buen libro.

Lo real es que SharePoint 2010 cuenta con capacidad directa para soportar cosas bien interesantes, entre las que podemos citar el uso de JQuery, REST, JSON, modelo de objetos del lado del cliente, entre otros aspectos interesantes que nos estan beneficiando directamente a los desarrolladores.

A continuación les dejo un sencillo ejemplo que tiene por objetivo leer información de una lista de tipo calendario y presentar las fechas de cumpleaños y festivos qe ahi se han definido, haciendo uso de un poco de JQuery.

< script type="text/javascript" >
$(document).ready(function()
{
$.getJSON("http://urlsitosharepoint/_vti_bin/ListData.svc/Calendario",function(data) {
var count = 0;
var fechaActual=new Date();
var diaActual = fechaActual.getUTCDate()-1;
var mesActual = fechaActual.getMonth()+1;
var anioActual = fechaActual.getFullYear();
var eventos = "false";
$('#resultarea').text("");

$.each(data.d.results, function(i,result) {

var tmpInicio = eval(result.HoraDeInicio.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));

var dia = tmpInicio.getUTCDate()-1;
var mes = tmpInicio.getMonth()+1;
var anio = tmpInicio.getFullYear();

if(diaActual==dia && mesActual == mes && anioActual==anio)
{

html = "
Hoy " + result.Título +"
";
$('#resultarea').append($(html));
eventos="true";
}

});

if(eventos == "false")
{
$('#resultarea').text("Sin eventos el día de hoy");
}


});

});< /script >< div id="resultarea" >< / div >
< div >< a href="/Lists/Calendario/calendar.aspx">Ver todos < / a >

Lo primero que se debe notar es la llamada a ListData.svc, ahi prácticamente está lo interesante que ofrece SP 2010. Para no decir más revisen aquí.

Luego JQuery llega al rescate, como ha venido haciéndolo desde hace un tiempo acá, y bueno nos provee el mecanismo getJSON para comunicarnos con el servidor así.

El resto amigos creo que es muy conocido por todos, uso de JavaScript común y corriente. Interesante de todo eso la linea var tmpInicio = eval(result.HoraDeInicio.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
donde logramos tomar la columna HoraDeInicio de la lista Calendario, y bueno la muy obvia Título con el objeto pertinente del recorrido del ciclo each: result.Título.

Es evidente que esto tiene grandes ventajas, cero deploy en el servidor, cero interacción con los cara dura de IT, rapida manipulación de data sin tanto problema: solo un poco de JQUERY, JavaScript y típico HTML.

Feliz client programming.

Friday, August 05, 2011

SharePoint y OBAs Part II

De regreso y avanzando con esta serie de entradas relacionadas a soluciones de SharePoint que involucran una WebPart e interacción con un cliente Office como Excel, voy a seguir dejándoles algunos ejemplos de código que he usado para esto.

Ver Parte I

Qué se debe hacer cuando necesitamos obtener las vistas que pertenecen a una lista específica?

public IList < TGLista > GetViews(Guid idList)
{
SPWeb webList = this.GetWebByIdList(idList);
if (webList != null)
{
TGLista vista = null;
IList vistas = new List();
SPList listaTemp = null;
try
{
listaTemp = webList.Lists[idList];
foreach (SPView temp in listaTemp.Views)
{
vista = new TGLista();
vista.Id = temp.ID;
vista.Titulo = temp.Title;
vistas.Add(vista);
}
}
catch (SPException ex)
{
throw;
}
catch (Exception ex)
{
throw;
}
finally
{
if (webList != null)
webList.Dispose();
}

if (vistas != null)
{
//Hace un ordenamiento ASCENDENTE de la lista
var list = from temp in vistas
orderby temp.Titulo
select temp;
return list.ToList();
}
}
return null;
}

Nuevamente se aprecia el uso de una clase entidad para almacenar la información a pasar entre capas usando una colección genérica de dichos objetos.

Quizá lo que más rescato como buena práctica del método anterior es que si se fijan, el método recibe por parámetro el ID de la lista para la cual queremos obtener sus vistas. No el nombre de la lista (string) o su índice dentro de alguna colección, que puede ser un entero. No se recibe su GUID que es la técnica mejor considerada cuando uno quiere referirse a una lista de SharePoint. La razón que más me gusta y que resguarda las soluciones de problemas "tontos", es que aunque los usuarios finales cambien el nombre de la lista (título o caption), el ID interno se conserva, y eso ya evita que el código quede "débil". Si el usuario borra su lista, apague y vámonos, ahí no hay anda que hacer, pero bueno eso ya son situaciones que se corrigen con un buen entrenamiento y conocimiento de los usuarios de las soluciones.


Un poco de CAML, como buena práctica no le cae mal a una solución SharePoint 2007.

private SPListItem GetItemByTitle(string titulo)
{
SPWeb web = SPContext.Current.Site.RootWeb;
SPQuery query = new SPQuery();
query.Query = "" + titulo + "";
try
{
SPList list = web.Lists["Objetivos KPI"];
foreach (SPListItem item in list.GetItems(query))
{
return item;
}
}
catch (Exception ex)
{
throw;
}
return null;
}

Lo único más interesante a rescatar es el uso de la consulta CAML que lo único que hace es filtrar los ítems de la lista por un título dado. De aquí solamente quiero decirles que usen herramientas como CAML Builder

Y qué pasa cuando quiero guardar un archivo generado por la solución en una biblioteca de SharePoint?

public void SaveLibrary(string file,Stream stream,Guid idList)
{
SPFolder spFolder = null;
SPFile spFileTemp = null;
TGServices services = new TGServices();
SPListItem item = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPWeb web = this.GetWebByIdList(idList))
{
web.AllowUnsafeUpdates = true;
spFolder = web.Folders["Plantillas Excel"];
spFileTemp = spFolder.Files.Add(file, stream, true);
spFolder.Update();
item = spFileTemp.Item;
item.UpdateOverwriteVersion();
web.AllowUnsafeUpdates = false;
}
});
}
catch (SPException ex)
{
throw;
}
catch (Exception ex)
{
throw;
}
finally
{
if (stream != null)
stream.Close();
}
}

Y para usar el método anterior podría tenerse algo similar:

FileInfo fileToLibrary = null;
try
{
fileToLibrary = new FileInfo(file);
link = services.SaveLibrary(file, fileToLibrary.OpenRead(), new Guid(IdLista));
}


Lo primero que el método recibe es el nombre de un archivo por ejemplo miarchivo.xlsx. Luego lo más importante recibe un Stream, en el ejemplo anterior se muestra cómo crear dicho stream y pasárselo al método en modo openRead(). Y finalmente pasar el ID de la lista, que quizá nos sirva como fuente para obtener el sitio de ejecución del proceso.

Muy importante la línea SPSecurity.RunWithElevatedPrivileges(delegate()
porque ejecuta el proceso de guardar a la biblioteca de documentos Plantillas Excel en un modo de privilegios elevados, así no tener problemas de acceso negado si el usuario ejecutando la solución no tiene suficientes permisos sobre la biblioteca.

Y siendo el resto de código algo entendible, lo realmente importante es dejar la seguridad de la ejecución como estaba web.AllowUnsafeUpdates = false;
Eso indica que solo ese tramo del código fue elevado, el resto de la ejecución continuará con los permisos del usuario que está ejecutando la solución.


Feliz coding!!