jueves, 12 de febrero de 2009

Error wizard sharepoint

Tras instalar el SP1 de MOSS 2007 en una granja de servidores e intentar pasar el wizard de configuración me he encontrado con la siguiente excepción:

Microsoft.SharePoint.Administration.SPUpdatedConcurrencyException was thrown. Additional exception information: An update conflict has occurred, and you must re-try this action. The object DiagnosticsService Parent=SPFarm Name=SharePoint_Config is being updated by Domain\User, in the w3wp process, on machine SERVER. View the tracing log for more information about the conflict. Microsoft.SharePoint.Administration.SPUpdatedConcurrencyException: An update conflict has occurred, and you must re-try this action. The object DiagnosticsService Parent=SPFarm Name=SharePoint_Config is being updated by Domain\User, in the w3wp process, on machine SERVER. View the tracing log for more information about the conflict.

Al parecer esto sucede cuando hay un objeto bloqueado a nivel de SPFarm. Para solventar este problema hay que limpiar la cache de configuración de Windows SharePoint Services.

http://support.microsoft.com/kb/944267/en-us/

¿Y donde se encuentra esta cache?

Esta caché se encuentra en:

C:\Documents and Settings\All Users\Application Data\Microsoft\SharePoint\Config\[GUID]

La solución pasa por borrar todos los xml de esta carpeta [CUIDADO NO BORRAR EL ARCHIVO cache.ini], luego se ha de editar el archivo cache.ini y poner un 1 y guardar.

http://support.microsoft.com/kb/939308/en-us/

jueves, 5 de febrero de 2009

Copiar items y folders entre DocumentLibrary manteniendo sus campos

Me he encontrado en un proyecto en que unas librerías de sharepoint que fueron migradas de 2003 daban un error al intentar mover elementos usando el sitemanger. Vimos que esto no pasaba en las otras librerías por lo que tuvimos que hacer un script para mover documentos y folders de una librería a otra, eso sí manteniendo todos sus metadatos, aquí algunos de los pasos que hemos seguido:

1. Igualar los campos de las bibliotecas:


public static void IgualarCampos(SPDocumentLibrary origen, SPDocumentLibrary destino)
{
if (origen == null destino == null) throw new ArgumentException("Las bibliotecas destino y origen no pueden ser nulas");
try
{
List listaCamposDestino = new List();
foreach (SPField field in destino.Fields)
{
listaCamposDestino.Add(field);
}
// Compara con origen y crea las necesarias en destino
foreach (SPField field in origen.Fields)
{
SPField campoBuscado = listaCamposDestino.Find(delegate(SPField campo)
{
return campo.Id == field.Id;
});
// Si no existe lo añadimos
if (campoBuscado == null )
{
// Se crea campo en lista destino.
destino.Fields.Add(field);
}
}
}
catch (Exception ex)
{
throw ex;
}
}



2. Funciones recursivas para recorrer todos los folders y crearlos en el destino así como los items por folder:



public static void CopyFoldersAndItems(SPDocumentLibrary origen, SPDocumentLibrary destino)
{
if (origen == null destino == null) throw new ArgumentException("Las bibliotecas destino y origen no pueden ser nulas");
try
{
string urldestinofolders = destino.RootFolder.ServerRelativeUrl.ToString();
SPFolderCollection foldersdestino = destino.ParentWeb.GetFolder(urldestinofolders).SubFolders;
string urlorigenfolders = origen.RootFolder.ServerRelativeUrl.ToString();
SPFolderCollection foldersorigen = origen.ParentWeb.GetFolder(urlorigenfolders).SubFolders;
foreach (SPFile file in origen.RootFolder.Files)
{
SPFile newFile = destino.RootFolder.Files.Add(file.Name, file.OpenBinary(), file.Author, file.ModifiedBy, file.TimeCreated, file.TimeLastModified);
SPListItem newItem = newFile.Item;
foreach (SPField f in file.Item.Fields)
{
if (!f.ReadOnlyField) newItem[f.InternalName] = file.Item[f.InternalName];
}
newItem["Modificado"] = file.TimeLastModified;
newItem["Creado"] = file.TimeCreated;
newItem.UpdateOverwriteVersion();
}
CopyFoldersAndItems(foldersorigen, foldersdestino);
}
catch (Exception ex)
{
throw ex;
}
}
public static void CopyFoldersAndItems(SPFolderCollection origen, SPFolderCollection destino)
{
try
{
foreach (SPFolder folder in origen)
{
if (folder.Name != "Forms")
{
SPFolder nuevo = destino.Add(folder.Name);
foreach (SPFile file in folder.Files)
{
SPFile newFile = nuevo.Files.Add(file.Name, file.OpenBinary(), file.Author, file.ModifiedBy, file.TimeCreated, file.TimeLastModified);
SPListItem newItem = newFile.Item;
foreach (SPField f in file.Item.Fields)
{
if(!f.ReadOnlyField) newItem[f.InternalName] = file.Item[f.InternalName];
}
newItem["Modificado"] = file.TimeLastModified;
newItem["Creado"] = file.TimeCreated;
newItem.UpdateOverwriteVersion();
}
if (folder.SubFolders.Count > 0) CopyFoldersAndItems(folder.SubFolders, nuevo.SubFolders);
}
}
}
catch (Exception ex)
{
throw ex;
}
}


lunes, 2 de febrero de 2009

Obtener webparts de una página (MOSS 2007)

Aquí tenemos un ejemplo para obtener las webparts de una página de publicación,
una vez tenemos el tipo de la webpart podemos hacer un casting y acceder a sus propiedades para consultarlas y/o modificarlas.




using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls.WebParts;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using(SPSite siteCollection = new SPSite("http://localhost:44236"))
{
using(SPWeb site = siteCollection.OpenWeb())
{
using (SPLimitedWebPartManager manager = site.GetLimitedWebPartManager("Paginas/default.aspx", PersonalizationScope.Shared))
{
foreach (System.Web.UI.WebControls.WebParts.WebPart wp in manager.WebParts)
{
Console.WriteLine(wp.GetType().ToString());
}
}
}
}

Console.ReadLine();
}
}
}

Añadir link abra el panel de control en una webpart

Si nuestra webpart necesita tener configuradas ciertas propiedades podemos mostrar un link que abra el panel de control (toolpane) hasta que estas propiedades no estén configuradas. Para ello tenemos que distinguir entre dos casos: webparts que derivan de Microsoft.SharePoint.WebParts.Webpart o webparts que derivan de System.Web.UI.WebControls.WebParts.Webpart.

En el primer caso tenemos una función, ToolPane.GetShowExtensibleToolPaneEvent, que pasándole el id de nuestra webpart nos devuelve un string con la llamada javascritpt que queremos realizar, por lo que el código quedaría algo como:


public class WPPrueba : Microsoft.SharePoint.WebPartPages.WebPart
{
#region Variables
private string _propiedad;
#endregion
#region Propieades
[Browsable(true),
Category("Mis Propiedades"),
DefaultValue(""),
WebPartStorage(Storage.Shared),
FriendlyName("Propiedad"),
Description("Propiedad.")]
public string Propiedad
{
get { return _propiedad; }
set { _propiedad = value; }
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
try
{
if (Propiedad == null Propiedad == "")
{
string funcionJavaScript = ToolPane.GetShowExtensibleToolPaneEvent(this.ID);
string html = "abra el panel de herramientas";
writer.Write(html);
}
else
{
writer.Write("hello world");
}
}
catch(Exception ex)
{
}
}
#endregion
}



En el segundo caso no podemos hacer esto por lo que añadiremos el código javascript a mano:



string html = " abra el panel de herramientas";