miércoles, 12 de octubre de 2011

Creando Site Columns y Content Types programáticamente

El día de hoy quiero compartir con ustedes un ejemplo de cómo crear columnas de sitio y tipos de contenido programáticamente. El objetivo final es crear un tipo de contenido que herede del tipo de contenido WorkflowTask (el que se utiliza para las tareas que se asignan en los flujos de trabajo), utilizando dos columnas de sitio, la primera será una columna que permitirá al usuario capturar su respuesta (Aprobar | Rechazar), la segunda permitirá capturar comentarios acerca de su respuesta.

Sin mucho preámbulo comencemos creando un proyecto en blanco con un elemento Feature con scope Site, al cual agregaremos un Event Receiver
Inmediatamente después comenzamos a tirar un poco de código en el método FeatureActivated para crear en primera instancia las dos columnas de sitio que utilizaremos:
SPWeb web = null;
if (properties.Feature.Parent is SPSite)
{
    SPSite sites = (SPSite)properties.Feature.Parent;
    web = sites.RootWeb;
}
else
{
    web = (SPWeb)properties.Feature.Parent;
}
if (web == null)
    return;
                
//Nombre del grupo de Content Types que crearemos
string contentTypeGroupName = "Blog - Content Types";
//Nombre del tipo de contenido que crearemos
string contentTypeName = "Blog - Response Workflow Content Type";
//Nombre del grupo de columnas de sitio que crearemos
string columnGroupName = "Blog - Site Columns";
//nombre de la columna de sitio que permitira al usuario seleccionar su respuesta (Approve | Reject)
string choiceFieldName = "ChoiceWFResponse";
//nombre de la columna de sitio que permitira al usuario capturar comentarios a cerca de su respuesta
string commentsFieldName = "CommentsWFResponse";


SPFieldMultiLineText approveRejectCommentsField = null;
SPFieldChoice approveRejectChoiceField = null;
                
/*Columna de sitio para seleccionar Aprobar o Rechazar*/
//mucho ojo! Validamos si la columa de sitio ya existe
if (!web.Fields.ContainsField(choiceFieldName))
{
    string approveReject = web.Fields.Add(choiceFieldName, SPFieldType.Choice, true);
    approveRejectChoiceField = (SPFieldChoice)web.Fields.GetFieldByInternalName(approveReject);
    approveRejectChoiceField.Group = columnGroupName;
    approveRejectChoiceField.EditFormat = SPChoiceFormatType.RadioButtons;
    approveRejectChoiceField.Choices.Add("Approve");
    approveRejectChoiceField.Choices.Add("Reject");
    approveRejectChoiceField.DefaultValue = "Approve";
    approveRejectChoiceField.Update();
}
//Si ya existe, solo obtenemos una referencia a la columna
else
{
    approveRejectChoiceField = web.Fields[choiceFieldName] as SPFieldChoice;
}

/*Columna de sitio para permitir al usuario ingresar un comentario*/
if (!web.Fields.ContainsField(commentsFieldName))
{
    string comments = web.Fields.Add(commentsFieldName, SPFieldType.Note, true);
    approveRejectCommentsField = (SPFieldMultiLineText)web.Fields.GetFieldByInternalName(comments);
    approveRejectCommentsField.Group = columnGroupName;
    approveRejectCommentsField.Update();
}
else
{
    approveRejectCommentsField = web.Fields[commentsFieldName] as SPFieldMultiLineText;
}

Una vez que las hemos creado, procedemos a crear el tipo de contenido utilizando las columnas de sitio.
//
//Ahora creamos el tipo de contenido
//

//heredamos del WorkflowTask Content Type
SPContentType workflowTaskCType = web.AvailableContentTypes[SPBuiltInContentTypeId.WorkflowTask];
SPContentType approvalRejectCType = null;
bool isUpdating = false;

//validamos si el tipo de contenido ya existe
if (web.AvailableContentTypes[contentTypeName] == null)
{
    approvalRejectCType = new SPContentType(workflowTaskCType, web.ContentTypes, contentTypeName);
    approvalRejectCType = web.ContentTypes.Add(approvalRejectCType);
    approvalRejectCType.Group = contentTypeGroupName;
}
else
{
    approvalRejectCType = web.ContentTypes[contentTypeName];
    isUpdating = true;
}

if (!isUpdating)
{
    //agregamo la columna de Seleccion
    SPFieldLink approveRejectFieldRef = new SPFieldLink(approveRejectChoiceField);
    approveRejectFieldRef.Required = true;
    approveRejectFieldRef.DisplayName = "Approve or Reject the task";
    approvalRejectCType.FieldLinks.Add(approveRejectFieldRef);

    //agregamo la columna de Comentarios
    SPFieldLink commentsFieldRef = new SPFieldLink(approveRejectCommentsField);
    commentsFieldRef.DisplayName = "Comments";
    approvalRejectCType.FieldLinks.Add(commentsFieldRef);
}
else
{
    //Actualizamos la columna de Seleccion
    SPFieldLink approveRejectFieldRef = approvalRejectCType.FieldLinks[approveRejectChoiceField.Id];
    approveRejectFieldRef.Required = true;
    approveRejectFieldRef.DisplayName = "Approve or Reject the task";

    //Actualizamos la columna de Comentarios
    SPFieldLink commentsFieldRef = approvalRejectCType.FieldLinks[approveRejectCommentsField.Id];
    commentsFieldRef.DisplayName = "Comments";
}

//actualizamos el tipo de contenido
approvalRejectCType.Update(true);

Hacemos Deploy de nuestro proyecto y validamos que se hayan creado las columnas de sitio y el tipo de contenido


Listo!

Pueden descargar el código de aquí

Happy Coding!

martes, 20 de septiembre de 2011

Reemplazando el diagrama de Workflow en SharePoint 2010 usando un Delegate Control

Como sabemos, los controles delegados (Delegate Controls) son básicamente contenedores que encapsulan contenido y que SharePoint permite substituir este contenido con contenido personalizado diferente a la implementación predeterminada. Una de sus funciones primordiales es proveer de una manera fácil de hacer Branding de los sitios SharePoint. SharePoint define varios controles delegados dentro de la master page v4.


En este post, les propongo usar esta característica para sustituir (y mejorar) la manera predeterminada en que se muestran los diagramas de los flujos de trabajo en la página de detalle del flujo de trabajo en SharePoint 2010.


Y poder adicionarle un poco de vida!


Primero se debe crear un proyecto nuevo y vacío (obviamente de SharePoint 2010)

Agregamos un usercontrol, en el cual vamos a escribir el código aspx que sustituirá al diagrama de flujo. De hecho este user control tendra el mismo contenido que el WorkflowStatus.ascx, y solo agregaremos una referencia a un archivo js que será el encargado de manipular el diagrama de Visio utilizando la API de Visio Services.

Agregamos una nueva Feature con Scope Site a la solución, la cual se encargará de desplegar el elemento que crearemos en el siguiente paso

La magia viene aquí; agregamos un nuevo elemento a la solución de tipo Empty Element y agregamos la siguiente definición:

El valor del atributo Id y el atributo Sequence son importantes ya que el Id debe coincidir con la definición del control que queremos reemplazar, y el valor de la propiedad Sequence debe ser menor a la especificada en la definición original del control para que tenga precedencia sobre este. A continuación como fue definido originalmente el control en la feature VisioWebAccess

Si quieren saber como poder agregar este tipo de mejoras a los diagramas de Visio, pueden checar dos de mis anteriores posts:

Anticipando algunas de sus posibles preguntas:
Porque utilizar un delegate control solo para adicionar la referencia a un archivo js?
Se podría haber agregado la referencia a este archivo .js desde la Master Page, incluso se puede sustituir el archivo workflowstatus.js que es el que se encarga de manera predeterminada del dibujado de todos los diagramas de Visio para los flujos de trabajo, sin embargo esto es muy invasivo ya que sería un cambio global y de la manera que este post propone el cambio sería a nivel de Sitio, es decir, lo menos invasivo posible.

Happy Coding!

martes, 6 de septiembre de 2011

Descargar los prerequisitos de SharePoint 2010 offline

Como muchos de ustedes saben, el nuevo instalador de SharePoint 2010 nos permite instalar los prerequisitos que nos hagan falta antes de comenzar con el proceso de instalación, lo que es bastante cómodo si recordamos la forma manual que se utilizaba para instalar SharePoint 2007.


Sin embargo hay algunos escenarios en el mundo real en los cuales no podemos utilizar esta ventajosa herramienta, específicamente me refiero al siguiente escenario:

Estamos haciendo un despliegue de una granja SharePoint en un ambiente (Desarrollo, QA, Producción, DRP, etc.) en el cual no tenemos acceso a internet y aunque hemos suplicado por él, el equipo de Seguridad no lo permitiría jamás.

Luego entonces lo que necesitamos hacer es descargar en una máquina en la cual si tengamos acceso a internet, todos los componentes de prerequisitos para SharePoint 2010 y posteriormente copiar esos archivos a cada uno de los servidores en los que haremos el despliegue de la granja.

ü  SQL Server 2008 Native Client (sqlncli.msi)
ü  Microsoft Chart Controls for the Microsoft .NET Framework 3.5 (MSChart.exe)
ü  Microsoft .NET Framework version 3.5 SP1 (dotnetfx35.exe)
ü  Windows PowerShell 2.0 (Windows6.0-KB968930-x64.msu)
ü  KB976394 (Windows6.0-KB976394-x64.msu)
ü  KB976492 (Windows6.1-KB976462-v2-x64.msu)
ü  Windows Identity Foundation (WIF) for Windows Server 2008 R2 (Windows6.1-KB974405-x64.msu)
ü  Microsoft Sync Framework Runtime (Synchronization-v2.0-x64-ENU.msi)
ü  Microsoft Filter Pack 2.0 (FilterPack64bit.exe)
ü  Microsoft SQL Server 2008 Analysis Services ADOMD.NET (SQLSERVER2008_ASADOMD10.msi)
ü  SQL Server 2008 R2 November CTP Reporting Services Add-in (rsSharePoint.msi)
ü  Microsoft Server Speech Platform (SpeechPlatformRuntime.msi)
ü  Speech recognition language for English (MSSpeech_SR_en-US_TELE.msi)

Listado de requisitos de software para SharePoint 2010

No obstante, esta solución es demasiado manual y nos consume demasiado tiempo, (el Facebook no se actualiza solo, o si?)

Por lo que les recomiendo utilicen mejor, el script “Download-All_SP2010_PreReqs.ps1” que forma parte de la utilería AutoSPInstaller, la cual podemos descargar de Codeplex, y que nos permite hacer esa descarga de manera automática hacia una carpeta para posteriormente copiarlos hacia los servidores que no tienen acceso a internet.

Al ejecutarlo nos pedirá la ruta en la cual se descargaran todos los componentes, la indicamos y hacemos click en OK

El script comienza a trabajar

Y ya solo nos resta esperar a que se terminen de descargar todos los componentes, los cuales quedarán en la carpeta "PrerequisiteInstallerFiles".

Espero que este tip les sirva.

Happy Configuring

domingo, 14 de agosto de 2011

MOSS MA not found

Aprovecho este espacio para dejar constancia de otro de los posibles inconvenientes a los que nos enfrentamos al tratar de desplegar el servicio de profile (UPS – User Profile Service) de manera completa en SharePoint 2010.


El error: “MOSS MA not found”, algo más que confuso y hasta cierto punto gracioso, obviamente no la primera vez que te enfrentas a él.

Cuando aparece: Cuando se está creando o editando la conexión hacia el AD (Directorio Activo), después de hacer click en OK.

Resolución: Si alguno de los servicios de Forefront están detenidos, entonces primero debes asegurarte que se inicien, yo personalmente recomiendo que no traten de iniciar los servicios manualmente, sino desde el Sitio Central de Administración de SharePoint. Si los servicios de Forefront están ya iniciados, pues…. entonces reinícienlos :), esto debería permitirles editar o crear su conexión sin que se vuelva a presentar el error.



lunes, 8 de agosto de 2011

Unable to connect to the Synchronization Service

Si ustedes como yo, son uno más de los desafortunados a los que les ha tocado pagar todos los pecados de sus vidas anteriores, con el servicio de User Profile Synchronization que esta a nuestra disposición en SharePoint 2010. Tal vez ya se hayan encontrado con varios de esos "comunes", y hasta cierto punto aceptados,  errores de configuración.

El día de hoy quiero dejar precedente de uno de los últimos con los que he tenido que lidiar. El mensaje de error es el mismo que intitula este post y se presenta al intentar abrir la herramienta que acompaña al servicio de sincronización, me refiero al FIM Client (Forefront Identity Manager), el cual se encuentra usualmente en la siguiente ruta:

%programfiles%\Microsoft Office Server\14.0\Synchronization Service\UIShell\miisclient.exe

Y el cual nos ayuda a rastrear que hace y la mayoria del tiempo los errores que se presentan en este servicio.
Unable to connect to the Synchronization Service

Como siempre, mi primera recomendación es que respiren profundo.

Como en pocas ocasiones, el mensaje de error que se muestra es perfectamente claro y muy conciso.

  1. Revisen si el servicio esta ejecutándose en el servidor desde el cual están intentando acceder al FIM Client, si el servicio no esta iniciado, es imposible abrir el FIM Client.
  2. Revisen si el usuario con el que se está ejecutando este utilería pertenece al grupo de FIMSyncAdmins, el cual se crea cuando se provisiona el servicio de sincronización y al cual, en teoría, el usuario con el cual se ejecuta el servicio es agregado automáticamente.

Si estas dos sugerencias ya las han revisado y asegurado que se cumplen, es posible que estén en el mismo escenario que el mío, y es que, acabando recién de provisionar el servicio de sincronización UPS (User Profile Synchronization), cuando me disponía a utilizar el FIM client, para mi sorpresa apareció este error .

La raíz y solución del contratiempo: como bien mencioné, al provisionar el servicio, este asigna los permisos y roles necesarios a la cuenta de servicio, entre ellos, se asigna al grupo FIMSyncAdmins. Solo que para que estos permisos sean efectivos es necesario efectuar un logoff y posteriormente un logon. Eso es todo!

Happy configuring!

Etiquetas

SharePoint 2010 (38) Microsoft (32) Desarrollo SharePoint (31) Gerardo Reyes Ortiz (27) SharePoint (20) SharePoint 2013 (18) Errores SharePoint (12) México (10) PowerShell (9) Silverlight (8) Visio Services (7) Features (6) MVP (6) Silverlight 3 (6) WebCast (6) Workflows (6) Configuracion SharePoint 2010 (5) D.F. (5) API REST (4) Configuracion SharePoint 2010; (4) Troubleshooting (4) Visual Studio 2010 (4) Visual studio (4) WSS (4) Web parts (4) Apps (3) Comunidad SharePoint (3) Configuración SharePoint 2013 (3) ODATA (3) SharePoint Server (3) SharePoint; Instalación SharePoint; Troubleshooting; Search Service (3) Silverlight 3.0 (3) Silverlight Toolkit (3) WebParts (3) javascript (3) jquery (3) Eventos SharePoint (2) Office 2010 (2) PeoplePicker (2) REST (2) SQL Server (2) Scripting (2) Search Service Application (2) SharePoint Designer (2) UPA (2) UPS (2) Workflows SharePoint (2) host header (2) Apps Development (1) Big Bang (1) CAS (1) CSOM (1) Codeplex (1) CompartiMOSS (1) Configuracion SharePoint 2010; Errores SharePoint (1) Configuracion SharePoint 2010; SharePoint 2010 (1) Custom Actions (1) Custom Editor Parts (1) Delegate Controls (1) Deployment (1) DisableLoopbackCheck (1) Document Library (1) Entrevista (1) Examenes de Certificación (1) Extract WSP (1) FBA (1) FS4SP (1) Fakes (1) Fast Search Server 2010 For SharePoint (1) Fiddler (1) HTTP.SYS (1) HTTPS (1) JSON (1) Language Pack's (1) Latam (1) MAXDOP (1) MCSM (1) MSExpertos (1) MVC (1) Microsoft México (1) Microsoft; Codeplex; Screencast; (1) My Sites (1) SQL Server 2012 (1) SQL Server Reporting Services (1) Screencast (1) Screencast; (1) Service Applications (1) Service Pack (1) SharePoint 2007 (1) SharePoint 2010 SP 1 (1) SharePoint API (1) SharePoint Conference (1) SharePoint Emulators (1) SharePoint Farm (1) SharePoint Health Analyzer (1) SharePoint Magazine (1) SharePoint Online (1) SharePoint Search (1) SharePoint Test (1) SharePoint; Desarrollo SharePoint (1) Shims (1) Simposio (1) Simposio Latinoamericano (1) SkyDrive Pro (1) Soporte Microsoft (1) Templates (1) Tip (1) VSeWSS (1) Virtual Machine (1) Visual Studio 2012 (1) WCF (1) WSS; IIS 7 (1) Web API (1) Web Content Management (1) Web Services (1) Windows 8 (1) Windows Live ID (1) Xml (1) appcmd (1) iOS (1) jqGrid (1) onload function (1)