miércoles, 28 de enero de 2009

OwnerEventHandler 1.0.0

Recientemente he publicado en codeplex el proyecto “OwnerEventHandler”. Consiste en una solución sharepoint que despliega un eventhandler para controlar las modifiocaciones de los elementos o documentos.

OwnerEventHandler permite que los usuarios tenga permisos de colaborador en las listas o librerías pero solo puedan modificar o editar los documentos de los que son propietarios.

La ventaja de este proyecto es que tiene múltiples utilidades con ciertos cambios en el código. Por ejemplo: podríamos utilizarlo para cambiar los permisos de los elementos, de manera que cada usuario pudiera ver los elementos que haya subido, o incluso podrías hacer que solo los pudieran editar un grupo de usuarios encargados de la supervisión.

El proyecto está compuesto de una solución WSP “OwnerEventReceiver”, que contiene una feature a nivel de sitio “OwnerItemEventReceiver”. El eventHandler está alojado en la librería OwnerEventHandler.dll.

Para registrarlo en una librería o biblioteca podemos utilizar "Event handler explorer”.

El código es bastante sencillo, consiste en un EventHandler que captura el evento ItemAdded para modificar los permisos de manera que todos los miembros excepto el propietario tengan permisos de lectura.

 

public class OwnerEventItemEventReceiver : SPItemEventReceiver
    { 
         public override void ItemAdded(SPItemEventProperties properties)
        {
            try
            {
                SPUser currentUser = properties.ListItem.ParentList.ParentWeb.CurrentUser;

                using (SPWeb webOrigUser = properties.OpenWeb())
                {
                    SPUserToken token = webOrigUser.AllUsers["SHAREPOINT\\system"].UserToken;
                    using (SPSite site = new SPSite(properties.SiteId, token))
                    {
                        using (SPWeb currentWeb = site.OpenWeb(properties.RelativeWebUrl))
                        {

                            try
                            {
                                DisableEventFiring();

                                SPList sourceList = currentWeb.Lists[properties.ListId];
                                SPListItem itemAdded = sourceList.GetItemById(properties.ListItem.ID);
                                if (!itemAdded.HasUniqueRoleAssignments)
                                {
                                    itemAdded.BreakRoleInheritance(true);
                                    itemAdded.ParentList.ParentWeb.Dispose();
                                }

                                SPRoleAssignmentCollection roleAssignmentCollection = itemAdded.RoleAssignments;
                                foreach (SPRoleAssignment roleAssignment in roleAssignmentCollection)
                                {
                                    roleAssignment.RoleDefinitionBindings.RemoveAll();
                                    roleAssignment.RoleDefinitionBindings.Add(currentWeb.RoleDefinitions.GetByType(SPRoleType.Reader));
                                    roleAssignment.Update();
                                }

                                SPRoleDefinition reviserRoleDefinition = currentWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
                                SPRoleAssignment reviserRolePropietario = new SPRoleAssignment(currentUser);
                                reviserRolePropietario.RoleDefinitionBindings.Add(reviserRoleDefinition);
                                itemAdded.RoleAssignments.Add(reviserRolePropietario);

                                itemAdded.Update();
                            }
                            catch (Exception ex1)
                            {
                                properties.ErrorMessage = ex1.Message;
                                properties.Status = SPEventReceiverStatus.CancelWithError;
                                System.Diagnostics.Trace.Write("Exception OwnerEventHandler.OwnerEventItemEventReceiver.ItemAdded.1: {0}", ex1.Message);
                            }
                            finally
                            {
                                EnableEventFiring();
                            }

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                properties.ErrorMessage = ex.Message;
                properties.Status = SPEventReceiverStatus.CancelWithError;
                System.Diagnostics.Trace.Write("Exception OwnerEventHandler.OwnerEventItemEventReceiver.ItemAdded: {0}", ex.Message);
            }
        }

    }

 

Lo primero que hacemos es obtener el token del usuario system, esto es parecido a ejecutar “SPSecurity.RunWithElevatedPrivileges”.

A continuación abrimos una referencia a la colección y al sitio, hacemos esto en lugar de utilizar el del SPItemEventProperties debido a que las referencias que mantiene el elemento añadido referencian al usuario que añadió el elemento, por lo que a la hora de modificar los permisos puede que no tenga permisos de Adminsitrador.

Después recorremos todas las configuraciones de permisos del elemento añadido y las editamos de manera que los miembros solo puedan leer.

Por último añadimos al usuario propietario el control total sobre el elemento.

lunes, 26 de enero de 2009

Implementación de Contentypes

Los contentypes serán uno de nuestros elementos en nuestros desarrollos sobre Sharepoint.

Para ver una introducción acerca de los contentypes y cómo manejarlos desde la interfaz gráfica podéis leer el post “Tipo de Contenido en SharePoint” de Jorge Diéguez.

En este post nos centraremos en la definición de contentypes mediante features creadas con “Herramientas para el desarrollo en Sharepoint”.

Empezaremos por definir nuestro contentype desde la interfaz gráfica. Con esto conseguiremos que Sharepoint cree la definición del contentype por nosotros. Para extraer esa definición a xml utilizaremos alguna de las herramientas disponibles como: Sharepoint Manager, FieldsExplorer o Feature Generator.

Para el ejemplo crearemos en Sharepoint un contenttype para almacenar los datos de los empleados. Definimos entonces el contentype Empleados con las columnas: Nombre, apellidos, número empleado.

Una vez creado el tipo de contenido, abriremos el Visual Studio y crearemos una solución con las extensiones de VSeWSS. Crearemos un proyecto del tipo “Empty” y añadiremos un elemento del tipo “ContentType”. Al añadir el elemento Visual studio nos preguntará sobre que tipo primario queremos que herede nuestro contentype. En este caso elegiremos “Item” o “elemento”, aunque podremos elegir cualquiera de los primarios que nos aparezca en la lista.

Sobre la vista VSeWSS veremos una nueva Feature, en mi caso con el nombre “EmpleadosContentType”.

Abriremos a continuación el fichero Xml que nos a generado las extensiones. En mi caso “EmpleadosContentype.xml”. Veremos que tenemos una definición de un contentype que hereda del tipo primario “Item”.

Este xml será el que defina nuestro contentype. En la sección fieldrefs añadiremos todas las referencias a los tipos de columnas o “Site columns” definidas previamente. En caso de tener que utilizar nuevos tipos de columnas las podremos definir mediante el tag “Field” bien en este fichero o en otro de esta u otra feature. Cada site column tiene un GUID único, por lo que para referenciarla utilizaremos este valor especificado en el atributo “ID”. En caso de utilizar columnas estándar definidas por Sharepoint, tendremos que buscar sus GUID’s y no será necesario tener que definirlas de nuevo.

Para obtener toda esta información utilizaremos Sharepoint Manager 2007. Navegaremos a nuestra colección y desplegaremos el elemento “Content types” alojado en la raíz de la colección. A continuación seleccionaremos la pestaña “Schema Xml”.

Esto nos mostrará la definición de nuestro content type en xml. Copiaremos el Xml generado y lo pegaremos en nuestro fichero XML dentro del tag “Elements”. Sharepoint Designer nos mostrará el xml de la instancia, por lo que tendremos que realizar algunos ajustes sobre el xml.

Para asegurarnos que las modificaciones tienen la estructura correcta, activaremos la validación del intellisense.

A continuación moveremos todos los elementos Field fuera del tag contentype y quitaremos todos los atributos subrayados como no reconocidos por el intellisense.

A continuación crearemos un elemento “FieldRef” por cada campo del contentype con los GUID de los campos que desplazamos previamente.

En mi ejemplo queda un xml como el siguiente:

<?xml version="1.0" encoding="utf-8"?>

<Elements Id="ad412d2a-bf6b-4ebe-bcd8-fb32fd01347f" xmlns="http://schemas.microsoft.com/sharepoint/">

<ContentType ID="0x0100D4030561D9561C4BB0330408060E5817" Name="Empleado" Group="Tipos de contenido personalizados">

<FieldRefs>

<FieldRef ID="{4a722dd4-d406-4356-93f9-2550b8f50dd0}" Name="FirstName" />

<FieldRef ID="{06b22ccb-9e3d-41d4-884f-4faf85d8c934}" Name="Apellidos" />

<FieldRef ID="{b0f31712-0348-4248-9fde-1cb33839da68}" Name="NumeroEmpleado" />

</FieldRefs>

</ContentType>

<Field ID="{c042a256-787d-4a6f-8a8a-cf6ab767f12d}" Name="ContentType" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="ContentType" Group="_Hidden" RowOrdinal="0" Type="Text" DisplayName="Tipo de contenido" ReadOnly="TRUE" Sealed="TRUE" ColName="tp_ContentType" PITarget="MicrosoftWindowsSharePointServices" PIAttribute="ContentTypeID" />

<Field ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="Title" Group="_Hidden" Type="Text" DisplayName="Título" Required="TRUE" FromBaseType="TRUE" ShowInNewForm="TRUE" ShowInEditForm="TRUE" />

<Field ID="{4a722dd4-d406-4356-93f9-2550b8f50dd0}" Name="FirstName" SourceID="http://schemas.microsoft.com/sharepoint/v3" StaticName="FirstName" Group="Columnas de calendario y contacto principal" DisplayName="Nombre" Type="Text" />

<Field Type="Text" DisplayName="Apellidos" Required="FALSE" MaxLength="255" Group="Columnas personalizadas" ID="{06b22ccb-9e3d-41d4-884f-4faf85d8c934}" SourceID="{d0b52269-2cb7-4c94-83c9-d40cf4207783}" StaticName="Apellidos" Name="Apellidos" />

<Field Type="Text" DisplayName="Numero Empleado" Required="FALSE" MaxLength="255" Group="Columnas personalizadas" ID="{b0f31712-0348-4248-9fde-1cb33839da68}" SourceID="{d0b52269-2cb7-4c94-83c9-d40cf4207783}" StaticName="Numero_x0020_Empleado" Name="Numero_x0020_Empleado" />

</Elements>

 

Ahora solo nos queda desplegar nuestra solución y activar la feature. Pero antes de hacer esto, como lo que estamos haciendo con nuestra feature es volver a definir un contentype que ya tenemos instanciado con el mismo GUID, nos aseguraremos de eliminarlo y las site columns definidas. Si no queremos hacer esto, podremos cambiar el nombre y los GUID del contenttype y de las sitecolumns

Para generear el XMl también podría haber utilizado “Fields Explorer” que nos permite exportar rápidamente los contentypes y site columns ya definidos.

viernes, 23 de enero de 2009

¿Cumpliste los objetivos?

Es lo que toca este mes, revisar objetivos. Este año parece que mucha gente no los está cumpliendo o si los cumple da igual, porque no hay dinero. ¿Pero no se supone que los objetivos son acerca de como lo hayas hecho el 2008?. ¿Para que sirven los objetivos o pagas de beneficios y demás?.

A mi entender los objetivos deben plantearse como un aliciente para que los empleados se involucren más en la compañía y para que tanto empresa como empleado evolucionen en el mismo camino, “Yo te ayudo, pero tú me ayudas a mí”. Evidentemente si lo haces bien deberías merecerte una subida de sueldo o un incentivo, pero es que el trabajo deberíamos hacerlo siempre bien, el cliente siempre debería estar contento con nosotros. Por lo tanto los objetivos deben ir más allá, deben de promover actitudes y actividades que hagan que el empleado y la empresa sean diferenciales del resto.

En mi caso no he cumplido objetivos porque me lo propuse así desde el principio, en mi caso estaban mal planteados. Es decir se daba importancia a aspectos que deberíamos tener y se premiaban actividades que realmente no aportaban mucho a la empresa y al resto de compañeros.

Al menos este año en nuestra empresa parece que se han dado cuenta y lo han intentado solucionar para 2009. Aparte de las certificaciones, se valoran aspectos como dar charlas o gravarlas (antes no valía con grabarlas!!), dar cursos, workshops o similares, mantener un blog (esta la tengo asegurada). En resumen, este 2009 habrá que arrimar el hombro para ayudar a nuestra empresa a ser más atractivos.

¿y tú qué tal este año?.

jueves, 22 de enero de 2009

Documentación Microsoft Dynamics NAV 2009

Microsoft ha publicado varias guías para el desarrollo, instalación y administración de Nav2009. podéis descargarlo en “Microsoft Dynamics NAV 2009 Developer and IT Pro Help”.

Os recomiendo algunos post como: “Microsoft Dynamics NAV Team Blog”, “Clausl's Dynamics NAV Blog”, “Freddys Blog”, “Waldo’s blog”, “Kine’s blog

martes, 20 de enero de 2009

MCTS en MOSS2007 Application Development

Un poco tarde, pero al fin me saqué la certificación 70-542 “MCTS Microsoft Office SharePoint Server 2007 ― Application Development”.

Volviendo al tema de las certificaciones, en este caso aunque no terminas siendo un experto al menos tienes una visión general de las funcionalidades de MOSS. Recomiendo haber realizado antes la certificación 70-541 que te permite entender como funcionan las tripas de sharepoint.

viernes, 16 de enero de 2009

Introducción a las Visual extension for Sharepoint

Las VSeWSS (Visual extension for Sharepoint) consisten en unas extensiones para Visual Studio para el desarrollo de soluciones y elementos de Sharepoint. Las VSeWSS nos ayudarán a construir los esqueletos de nuestras soluciones, features, webparts y sobre todo nos ahorrará trabajo a la hora de crear el fastidioso manifest de las soluciones.

Aunque existen otras soluciones similares como WspBuilder, VseWSS será una solución muy válida para nuestros proyectos.

Para utiliza VSeWSS crearemos un proyecto del tipo “Sharepoint”. Al seleccionar esta categoría veremos que podremos crear varios tipos de proyecto como: Definiciones de listas y sitios, webparts o proyectos vacíos para agregar lo que querramos.

Todos los proyectos que realicemos con VseWSS estarán compuesto por los ficheros propios que agreguemos y los que definan una solución de Sharepoint. Dentro de la solución se dividirá en varias features. Una solución de Sharepoint consiste en un fichero con extensión WSP que contiene todos los ficheros que creemos, sus definiciones y donde se alojarán al desplegarse la solución. Al agregar una solución a la granja estaremos almacenando el fichero en la bbdd de configuración. A continuación podremos desplegarla en los frontales que deseemos. Al desplegarla, Sharepoint copiará por nosotros los ficheros en todos los frontales y copiará las definiciones que correspondan. Si disponemos de una Web Application extendida solo tendremos que desplegarla en una de ellas ya que Sharepoint se encargará de replicarla.

Para este ejemplo crearemos un nuevo WebPart. Al seleccionarlo nos creará los ficheros para definir el webpart y los necesarios para crear la solución de sharepoint. Los ficheros de la definición de la solución y features están alojados en la carpeta “pkg” que no está agregada al proyecto. Para verla seleccionaremos la vista “Mostrar todos los ficheros”. Al hacerlo veremos la estructura del paquete una vez lo hayamos generado o previsualizado. Estos ficheros además los mantendrá el propio Vsewss automáticmanete, por lo que no tendremos que tocar nada manualmente a no ser que querramos hacer cosas avanzadas.

Solution.xml

Es un fichero propio de VSEWSS y contiene la definición de la solución describiendo que features se van a utilizar y que elementos la componen. Para construir el fichero de solución utiliza el guid indicado en el nodo xml “Element”, por lo que todos nuestros ficheros deben contener un nodo “Element” con un guid. Si no lo indicamos Vsewss construirá una feature por cada uno de los ficheros, y tendremos que modificar los ficheros a mano para volver al esado anterior.

Manifest.xml

Contiene la descripción que utilizará Sharepoint a la hora de desplegar la solución para saber dónde irá alojado cada fichero que componga la solución.

Feature.xml

Contiene la definición de las feature.

Al construir la solución Visual studio compilará los ficheros agregados en la solución. Para crear la solución de Sharepoint tendremos que seleccionar las opciones de las extensiones “Package” o “Deploy”. Esto nos creará por un lado todos los ficheros de definición de la solución y features y por otro lado los ficheros “*.wsp” que corresponde a la solución. El fichero wsp lo creará en el directorio bin.

Para crear los ficheros solution.xml, manifest.xml y las features podremos realizarlo construyendo el paquete o desde la vista “WSSP View” accesible desde el menú “View->Other Windows->WSSP View”. Esta ventana mostrará la estructura de nuestra solución.

Además de crear WebParts podremos añadir a nuestra solución otro tipo de elementos como: Definiciones de listas, contentypes, even handlers, field controls, …

Uno de los elementos más interesantes que podemos añadir es el “Template”. Esto nos creará una carpeta Template, de manera que vsewss nos copiará automáticamente al directorio “12\Template” de Sharepoint todos los ficheros que agreguemos en este directorio. Básicamente lo que hace con el elemento “Template” es mantener la sección “TemplateFiles” del fichero manifest de la solución.

Para crear una nueva feature podremos hacerlo manualmente o desde la vista “WSS View” en el botón superior “Create new feature”.

Una vez hayamos creado y compilado nuestra solución podremos desplegarla seleciconando la opción “Deploy” accesible al seleccionar con el botón derecho el fichero de proyecto de Visual Studio. Para desplegar una solución antes tendremos que indicar a Visual Studio sobre que web application lo haremos. Para hacerlo seleccionaremos la propiedades del proyecto y en la pestaña “Debug” marcaremos la opción “Start browser at URL”.

Al desplegar la solución veremos en la barra inferior de Visual Studio el progreso del despliegue. Además de la acción de despliegue podremos retraer la solución o copiar los ficheros de forma rápida mediante la opción “Quick Deploy”.

Nota: Para que podamos desplegar la solución debemos tener permisos de administración de la granja con el usuario logado.

Al trabajar con vsewss puede que nos den algunos errores al desplegar la solución muy distintos a los que nos daría si lo hiciéramos a mano.

caracteres no válidos en la ruta

Esto se produce al hacer instalaciones con idiomas distintos. Una solución es cambiar en las variables de entorno del servidor las rutas “Temps” y “Temp” por un directorio que no dependa del idioma, por ejemplo “C:\Temp”.

Could not load file or assembly

Esto se produce cuando hacemos referencia a un assembly que no está registrado en el GAC. Solo tenemos que agregarlo al GAC.

This solution contains two assemblies with the same name

Se produce cuando hemos registrado la dll manualmente en el gac. Solo hayque desinstalarla y deplegar de nuevo.

Más información acerca de errores comunes con vsewss: http://blog.csdn.net/timewolf/archive/2008/07/23/2694607.aspx

miércoles, 14 de enero de 2009

This Page has been modified since you opened it

El webpart que estaba construyendo estaba extendiendo las funcionalidades de búsqueda de MOSS y al hacer un submit a la página de resultado me daba el error “This Page has been modified since you opened it. You must open the page again.” o “Se ha modificado esta página desde que la abrió. Debe volver a abrirla.”. Lo curioso es que encima no dejaba ninguna marca en el log de Sharepoint ni de windows, por lo que no sabes exactamente que está pasando.

Al final después de mucho batallar, me fijé que el control estándar que estaba extendiendo llamaba a dos funciones javascript al hacer el submit

… onclick="ResetPageHashCode();WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions( …

Al principio no le dí mucha importancia, pero justo cuando estaba probando con Fidler para comparar lo que enviaba el control estándar con el mío, me di cuenta que borrando el valor del parámetro post “MSO_PageHashCode” dejaba de dar el error. Qué curioso!!!, resulta que mirando el código de la función “ResetPageHashCode” borra este elemento de la página antes de hacer un submit.

Efectivamente añadiendo esta llamada antes de hacer un submit conseguí arreglar mi control, aunque en mi caso tuve que tocarla ya que no me llegaba a funcionar del todo:

function ResetPageHashCode()
{
var f = document.forms[0];
if (null != f && null != f.elements['MSO_PageHashCode'])
f.elements['MSO_PageHashCode'].value = "";

_spFormOnSubmitCalled = false;
}

<asp:Button ID="ASB_BS_SRCH_1" runat="server" Text="Buscar" CssClass="boton" OnClientClick="ResetPageHashCode();Buscar();" />

No puedo asegurar que sea la solución para todos los casos en los que ocurre este error ya que se proponen muchas soluciones, pero en mi caso ha funcionado.

Otras soluciones a este error:

Resolution: MOSS: This Page has been modified since you opened it. You must open the page again.

SharePoint Errors, Warnings and Problems Collection

This Page has been modified since you opened it. You must open the page again.

Finally: A Federation Search results page that doesn't give me the need to "Refresh Page" before I can see the results

martes, 13 de enero de 2009

Herramientas para el desarrollo en Sharepoint

Existen muchas herramientas para el desarrollo con Sharepoint, tener una referencia acerca de las más importantes nos ahorrará tiempo y facilitará el trabajo. A continuación veremos las que considero más importantes o imprescindibles:

 

Sharepoint Designer

Será la herramientas que utilizaremos para ayudarnos a construir los diseños de nuestros webparts, páginas, masterpage, etc.

Sharepoint Designer es la evolución del FrontPage, aunque ha mejorado muchísimo.

En los siguientes post encontrareis ejemplos acerca de cómo utilizarlo:

 

VSeWSS

Consisten en extensiones de Visual Studio para Sharepoint. Nos permiten crear los siguientes elementos:

· Definición de sitio

· Definición de listas, templates, site columns

· WebParts

· Features

Su principal ventaja es que crea una solución con los elementos del proyecto. Además podemos desplegar la solución de forma automática desde visual studio.

Empty Project

Consiste en un proyecto al que podemos agregar varios tipos de elementos Sharepoint.

Esta herramienta nos crea las estructura básica de la definición pero no la crea completamente, por lo que tendremos que terminarla manualmente editando los XMl’s

Si queremos agregar varios elementos dentro del directorio Template,( como por ejemplo un control de usuario), agregaremos un elemento del tipo “Template”.

Además para crear la solución de Sharepoint tendremos que desplegar el proyecto sobre una colección, una vez desplegada dispondremos del fichero WSP en la carpeta Debug o Release.

Ventana de exploración de la solución

Desde la ventana “WSP View” podremos visualizar la estructura de nuestra solución.

Dispondremos además de una carpeta “Pkg” no incluida en la solución donde almacenará los ficheros de definición de la solución Sharepoint. En caso que tengamos que cambiar la estructura o los nombres de los ficheros podremos retocar estos ficheros manualmente para que siga funcionando la generación automatica de la solución.

Sharepoint Solution Generator

Consiste en un asistente para crear proyectos basados en VseWSS con la definición actual de los elementos creados en nuestro portal de pruebas. Nos permite crear definiciones de sitio y de listas.

¿Para qué lo usaremos?

Lo utilizaremos para crear las soluciones de los proyectos. La definición de los elementos lo crearemos con otras herramientas.

 

SPALM - SharePoint 2007 SoftwareFactoryLite

Consiste en una extensión de Software Factory para Visual Studio. Permite gestionar el ciclo de vida de las soluciones Sharepoint mediante su integración con TFS.

SPALM estructura las aplicaciones de SharePoint en tres bloques, en función de la tipología de artefacto que contienen(Contenido, Configuración, Customizacion):

Automatiza la definición de elementos Sharepoint. Dispone además de interfaces para facilitar la definición.

¿Para qué lo usaremos?

Lo utilizaremos en proyectos complejos con varias personas en el equipo.

WspBuilder

Consiste en una aplicación de consola para crear de forma rápida soluciones Sharepoint. Dispone además de un plugin para Visual Studio 2008 que nos permite automatizar la creación de elementos como:

· Features

· Event Handlers

· Templates

· WebParts

· Custom Fields

· Web Service

· Otros…

¿Para qué lo usaremos?

Lo utilizaremos de forma similar a las extensiones VseWss.

 

Sharepoint Manager 2007

Herramienta para administrar las propiedades de los elementos de la granja.

Con Sharepoint Manager podremos editar las propiedades y características directamente en la bbdd de configuración. También podremos obtener la definición de xml de los elementos.

Lo malo es que necesitamos ejecutarlo con las credenciales del usuario con permisos a la bbdd de configuración.

 

Imtech Fields Explorer

Imtech Fields Explorer es en una herramienta desarrollada por Waldek Mastykarz. Con esta herramienta podremos:

· Exportar la definición a XML de nuestros conten types y site columns.

· Crear page layouts a partir de content types

· Crear Wrapper class en C#

Dispone además de un plugin para Visual Studio 2008. Lo malo es que solo funciona con MOSS.

Características

Exportar la definición a XML de nuestros conten types y site columns.

Podemos navegar por la jerarquía de contenttypes y exportar a xml su definición.

Esto es especialmente útil cuando estamos construyendo una feature a partir de nuestro sitio de pruebas.

Crear page layouts a partir de content types

Field Explorer automatiza la creación de page layouts de nuestros content types.

Crear Wrapper class en C#

Podemos crear clases en C# con los GUIDs de los campos de nuestros contentypes y listas. Esto está bien cuando tenemos un único entorno, para poderlo aplicar con una solución que esté con varios entornos (desarrollo, integración, etc.) podemos crear una dll con el mismo nombre para cada entorno, de manera que el proyecto solo se compile una vez independientemente de donde se despliegue.

¿Para qué lo usaremos?

Usaremos principalmente la generación de wrappers de nuestros elementos.

La definición del XML de los elementos lo utilizaremos para ayudarnos a crear las soluciones de VseWSS.

Feature Generator

Herramienta todavía en desarrollo que nos permite crear las definiciones de distintos tipos de elementos de Sharepoint a partir de un sitio existente. Tiene algunos fallos pero permite crear definiciones de varios elementos al mismo tiempo.

¿Para qué lo usaremos?

Lo utilizaremos para definir los xml de los elementos que componen nuestra solución.

 

U2U CAML Query Builder

La utilizaremos para construir nuestras consultas CAML. Es importante que al probarlo quitemos los nodos “Query” que nos genera.

¿Para qué lo usaremos?

Lo utilizaremos para crear nuestras consultas CAML.

SharePoint Content Deployment Wizard

Con esta herramienta podremos exportar el contenido de nuestro sitio para moverlo a otra instalación.

http://www.codeplex.com/SPDeploymentWizard

 

NET Reflector

Herramienta imprescindible que nos permitirá desensamblar las librerías de .net y entender el funcionamiento de las páginas, controles y webparts estándar.

domingo, 11 de enero de 2009

Ajax sobre Sharepoint

Continuando con la temática de este mes acerca de dar una introducción al desarrollo sobre Sharepoint, nos queda por ver como montar Ajax en Sharepoint.

Ya se ha hablado mucho sobre este tema por lo que me limitaré a dejar una referencia rápida:

Lo primero será instalar las extensiones de AJAX, si tenemos el Framework 3.5 no será necesario instalarlo, en caso contrario tendremos que descargar el kit “ASP.NET 2.0 AJAX Extensions”.

Una vez instalado tendremos que configurar nuestro web.config:

Verificaremos el nº de versión de la librearía “System.web.extension”, para verlo podremos visualizarlo desde el GAC en “c:\windows\assembly”.

A continuación abriremos nuestros web.config, por defecto están alojados en la carpeta “c:\inetpub\wwwroot\wss\VirtualDirectories”.

1. Añadiremos un nuevo sectionGroup en la zona configSections:

<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication"/>
        <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
          <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="Everywhere" />
          <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
          <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" allowDefinition="MachineToApplication" />
        </sectionGroup>
      </sectionGroup>
    </sectionGroup>

2.Añadimos una sección controls en la sección “pages”:

<pages>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </controls>
</pages>

3. Añadimos el siguiente assemblie en la sección de assemblyes:

<assemblies>
       <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</assemblies>

4. Registramos los manejadores:

<httpHandlers>
      <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
</httpHandlers>

6. Añadimos el módulo de Ajax en la sección httpModules:

<httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </httpModules>

7. Permitimos que los controles incluidos en la librería de Ajax puedan ejecutarse en Sahrepoint:

<SafeControls>
      <SafeControl Assembly="System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI" TypeName="*" Safe="True" />
</SafeControls>

Una vez registrado, verificaremos que todo funciona correctamente. Si nos hemos dejado algo o lo hemos registrado mal puede que nos de un error de ASP.NET al entrar en cualquier página del web application.

Nos quedaría por registrar el scriptmanager en las páginas para que podamos utilizar los controles de Ajax. Podremos hacerlo de varias formas:

  • Incluyéndolo en la masterpage
  • Auto-registrándolo desde un webpart.

Incluyéndolo en la masterpage

Consiste en modificar la masterpage para incluir el scriptmanager. Este caso es válido siempre que tengamos la misma masterpage en todos los subsitios, en caso de tener una jerarquí de sitios muy grande y que encima no hereden del padre tendremos que recurrir al autoregistro desde el propio webpart.

En el post anterior “Modificar la apariencia de nuestro sitio” vimos como modificar nuestra masterpage (por lo que no detallaremos como realizar la modificación).

Abriremos entonces la masterpage, y añadiremos el siguiente código cerca de la definición de <WebPartPages:SPWebPartManager>  :

<asp:ScriptManager runat="server" ID="ScriptManager1"></asp:ScriptManager>

Si quisiéramos utilizar el control UpdatePanel tendremos que registrar el siguiente script en la página:

<script type='text/javascript'>_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;</script>

Auto-registrándolo desde un webpart

Si queremos asegurarnos que nuestro webpart con ajax va a funcionar desde cualquier página podremos recurrir a registrar el scriptmanager mediante programación añadiendo el siguiente código en el evento Oninit:

 

protected override void OnInit(EventArgs e) {

base.OnInit(e);

//get the existing ScriptManager if it exists on the page

_AjaxManager = ScriptManager.GetCurrent(this.Page);

if (_AjaxManager == null)   {

//create new ScriptManager and EnablePartialRendering

  _AjaxManager = new ScriptManager();

  _AjaxManager.EnablePartialRendering = true;

// Fix problem with postbacks and form actions (DevDiv 55525)

Page.ClientScript.RegisterStartupScript(typeof(AjaxBasePart), this.ID, "_spOriginalFormAction = document.forms[0].action;", true);

//tag:"form" att:"onsubmit" val:"return _spFormOnSubmitWrapper()" blocks async postbacks after the first one

//not calling "_spFormOnSubmitWrapper()" breaks all postbacks

//returning true all the time, somewhat defeats the purpose of the _spFormOnSubmitWrapper() which is to block repetitive postbacks, but it allows MS AJAX Extensions to work properly

//its a hack that hopefully has minimal effect

if (this.Page.Form != null)   {

string formOnSubmitAtt = this.Page.Form.Attributes["onsubmit"];

if (!string.IsNullOrEmpty(formOnSubmitAtt) && formOnSubmitAtt == "return _spFormOnSubmitWrapper();")  {

this.Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";

  }

//add the ScriptManager as the first control in the Page.Form//I don't think this actually matters, but I did it to be consistent with how you are supposed to place the ScriptManager when used declaritevly

this.Page.Form.Controls.AddAt(0, _AjaxManager);

               }

            }

}

WebPart de contenido con formato

En este post veremos cómo definir nuestro propio WebPart de contenido con un formato diferente al habitual de tablas. Todo esto sin tirar una línea de código ya que solo nos centraremos en definir cómo presentar el contenido.

Supongamos que disponemos de una lista de Sharepoint con las noticias de la intranet y queremos disponer de una vista de las últimas noticias en la página principal.

Lo primero que haremos será abrir una página de nuestro sitio con Sharepoint Designer y agregaremos un DataFormWebPart. Seleccionaremos nuestra lista de noticias y los campos que queremos visualizar. En este ejemplo he creado una lista del tipo “Anuncios”.

Para agregar el DataFormWebPart realizaremos lo siguiente:

En vista diseño, en el menú “Insertar” seleccionaremos “Controles de Sharepoint” y luego “Vista de datos”.

A continuación iremos a la ventana de “biblioteca de orígenes de datos” seleccionaremos la lista de la que queremos obtener la información y pulsaremos en la opción “Mostrar datos”.

Esta opción nos mostrará los campos disponibles en la lista. Seleccionaremos los campos que deseamos visualizar en nuestra vista (o los que deseamos disponer) y seleccionamos “Insertar los campos seleccionados como” y “Vista de varios elementos”.

Una vez agregado cambiaremos la forma de presentar el contenido modificando el XSL del DataFormWebPart. Seleccionaremos el WebPart con Sharepoint Designer y visualizaremos el código de la página. Buscaremos la sección “<xsl:template name="dvt_1.rowview">” que corresponde al código que renderizará el WebPart para cada ítem de la lista de noticias, y tocaremos la sección “<xsl:template name="dvt_1">” que corresponde con la cabecera y la definición de la tabla.

Solo tendremos que adaptar estas secciones para que muestre el contenido con el formato que deseemos.

En mi ejemplo he dejado el siguiente código en el DataFormWebPart:

<xsl:template name="dvt_1">

<xsl:variable name="dvt_StyleName">Table</xsl:variable>

<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>

<table border="0" width="100%" cellpadding="2" cellspacing="0">

<tr valign="top">

<xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">

<th class="ms-vh" width="1%" nowrap="nowrap"></th>

</xsl:if>

</tr>

<xsl:call-template name="dvt_1.body">

<xsl:with-param name="Rows" select="$Rows"/>

</xsl:call-template>

</table>

</xsl:template>

<xsl:template name="dvt_1.body">

<xsl:param name="Rows"/>

<xsl:for-each select="$Rows">

<xsl:call-template name="dvt_1.rowview"/>

</xsl:for-each>

</xsl:template>

<xsl:template name="dvt_1.rowview">

<tr>

<xsl:if test="position() mod 2 = 1">

<xsl:attribute name="class">ms-alternating</xsl:attribute>

</xsl:if>

<td>

<table>

<tr>

<td class="ms-vb" style="font-weight:bold">

<a>

<xsl:attribute name="href" >

<xsl:value-of select="concat('/Lists/Noticias/DispForm.aspx?ID=', @ID)"></xsl:value-of>

</xsl:attribute>

<xsl:value-of select="@Title"/>

</a>

</td>

</tr>

<tr>

<td class="ms-vb" style="font-style:italic">

<xsl:value-of select="@Resumen" disable-output-escaping="yes"/>

</td>

<td class="ms-vb">

<xsl:value-of select="ddwrt:FormatDate(string(@Created), 3082, 5)"/>

</td>

</tr>

</table>

</td>

</tr>

</xsl:template>

Al final conseguimos el siguiente aspecto:

 

Fijaros que el tag “<xsl:value-of select>” renderiza un campo, variable o función de XSL.

Para conseguir que el título vaya al Dispform del ítem, he agregado el siguiente códogio:

<a>

<xsl:attribute name="href" >

<xsl:value-of select="concat('/Lists/Noticias/DispForm.aspx?ID=', @ID)"></xsl:value-of>

</xsl:attribute>

<xsl:value-of select="@Title"/>

</a>

Mediante xsl he modificado el atributo href del hyperlink para que contenga la url compuesta al concatenar la url del formulario DispForm con el ID del ítem actual.

Una vez finalizada la edición de nuestro webpart lo exportaremos a un fichero del tipo “.webpart”. Esto lo podemos hacer guardamos la página y seleccionando la opción “exportar” accesible desde el navegador en modo edición.

O bien desde Sharepoint Designer seleccionaremos el WebPart en modo diseño u seleccionaremos “Archivo”, “Exportar”, Guardar elemento web en”, “Archivo”.

El archivo Webpart que nos genere contendrá la definición del webpart de contenidos con nuestro xsl formateado. Ahora solo tendremos que subirlo a nuestra colección desde la opción de “Elementos web” en la página de configuración del sitio y ya estará disponible para agregarlo en cualquiera de nuestras páginas.

Si quisiéramos moverlo a otro colección o web application, solo tendríamos que abrir el fichero Webpart generado y editar el parámetro “ListID” con el GUID de la instancia de nuestra lista.

sábado, 10 de enero de 2009

Modificar la apariencia de nuestro sitio

Continuando con el hilo de los post anteriores “Quick reference Sharepoint” hablaremos ahora de una de las cosas que tendremos que hacer tarde o temprano en un proyecto con Sharepoint, modificar la apariencia de nuestro sitio.

Sharepoint nos proporciona varios mecanismos que aprovechan la infraestructura de ASP.NET 2. : Los temas, masterpages, las colecciones de hojas de estilo y de imágenes, los elementos de navegación.

Masterpage

Las masterpages consisten en plantillas que definen cómo se distribuirá el contenido en una página pero sin llegar a conocer el contenido ni su comportamiento. Sharepoint nos proporciona varias masterpage en función del tipo de plantilla de sitio que elijamos.

Para alojar los ficheros masterpage disponemos de una galería por cada colección de sitios, lo podemos encontrar en la conficugarción del sitio raíz en la opción “Páginas maestras” o en la ruta “/_catlagos/masterpage/”.

Si abrimos Sharepoint Designer y observamos la página default.aspx, veremos cómo está haciendo referencia a la masterpage por defecto mediante la url “~masterurl/default.master”. El path “~masterurl” indica el path a la galería de páginas maestras.

<%@ Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=12.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" meta:webpartpageexpansion="full" meta:progid="SharePoint.WebPartPage.Document" %>

En el siguiente artículo encontramos la distribución de cada uno de los contentplaceholder de la masterpage por defecto: Default content placeholders in a SharePoint master page

Provisionando una masterpage

Para modificar una masterpage tenemos varios mecanismos:

· Convirtiendo el fichero en unghosted

· Provisionando la masterpage en la galería de páginas maestras.

· Alojando la masterpage en la definición de la plantilla de sitio

· Desde una feature

Convirtiendo el fichero en unghosted

Esta es la manera más fácil y rápida, consiste en crear una instancia del fichero en la bbdd de contenidos de manera que en lugar de instanciarse desde el sistema de ficheros del frontal se instancia a partir de la bbdd de contenidos.

Esta es una práctica poco recomendable para implantaciones serias, solo las utilizaremos en prototipos. En el artículo Ghosted o unghosted, ¿Quien corre mas? podéis encontrar los motivos por los que no son recomendables las ficheros unghosted.

Provisionando la masterpage en la galería de páginas maestras.

Consiste en cargar un fichero masterpage directamente en la galería de páginas maestras. Esta galería consiste euna librería de documentos , por lo quela podremos provisionar manualmente o mediante features o código.

Alojando la masterpage en la definición de la plantilla de sitio

Consiste en definir una masterpage para todos los sitios que se creen a partir de una plantilla, de manera que no haya que subirla manualmente en cada colección.

En el siguiente artículo encontramos un tutorial acerca de cómo hacerlo: How to Create and Store Master Pages on the Server for Use with Site Collections

Desde una feature

Para provisionarlo desde una feature:

<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="
http://schemas.microsoft.com/sharepoint/">
    <Module Name="AddMasters" Url="_catalogs/MasterPage" >
        <File Url="MyDefault.master" Type="GhostableInLibrary"
          IgnoreIfAlreadyExists="True">

        </File>
        <File Url="custom.master" Type="GhostableInLibrary"
          IgnoreIfAlreadyExists="True"/>

        </File>
  </Module>
</Elements>

Podemos encontrar un ejemplo en: Create a Feature: Master Pages for Site Collections

Establecer la masterpage

A la hora de provisionar los ficheros debemos pensar que cada sitio tiene su propia galería de páginas maestras, por lo que podemos hacer que cada sub-sitio tenga su propia apariencia.

Para establecer la masterpage por defecto del sitio podemos o bien indicarlo con Sharepoint Designer seleccionando el fichero y con el botón derecho “Establecer como página principal predeterminada”, o bien utilizando Sharepoint Manager seleccionando el sitio y editando la propiedad “CustomMasterUrl”.

Mediante programación podemos hacer lo siguiente:

CurrentWeb.MasterUrl = "/_catalogs/masterpage/MyDefault.master";
CurrentWeb.CustomMasterUrl = "/_catalogs/masterpage/custom.master";
CurrentWeb.Update();

Si tenemos habilitada la característica de publicación

Dispondremos de funcionalidades adicionales que nos facilitarán el mantenimiento de estilos en una jerarquía de sitios grande.

Dispondremos de la opción “Página maestra” en la página de configuración del sitio en la sección “Aspecto”, desde donde podremos establecer la masterpage por defecto. Además disfrutaremos de la posibilidad de herencia de de manera que se apliquen los cambios a todos los subsitios.

Distribución de contentplaceholder

Cuando hagamos personalizaciones que cambien drásticamente la apariencia lo más fácil es mantener los placeholders estándar para que no se produzca ningún error inesperado, pero los podremos mantener ocultos mediante la propiedad “visibility”.

Masterpage de Application pages

Las páginas del tipo Application pages no podrán utilizar la masterpage default.master. Por defecto utilizan Application.master alojada en la ruta “_layout”.

Hojas de estilo

Sharepoint utiliza por defecto la hoja de estilos CORE.css en el directorio “12\Templates\Layouts\{Idioma}\Styles”. No es recomendable editar directamente este fichero ya que es bastante complejo, es común para todos los sitios y puede que se pierdan los cambios al instalar actualizaciones.

Para establecer nuestras propias hojas de estilo podremos indicarlo mediante el tag de la masterpage “<SharePoint:CssLink>”. Podemos establecer distintas hojas de estilo mediante este elemento y su propiedad “DefaultUrl” donde indicaremos la url de nuestra hoja de estilo.

<SharePoint:CssLink runat="server" DefaultUrl="<% $SPUrl:~SiteCollection/_layouts/styles/prueba.css%>" />

También podemos especificar más hojas de estilos mediante el uso de “<SharePoint:CssRegistration>” que registrará las hojas de estilo en orden alfabético antes de renderizar las hojas primarias, por defecto y altérnate.

En el siguiente artículo podemos encontrar una completa referencia sobre los estilos por defecto: CSS Reference Chart for SharePoint 2007

Si tenemos habilitada la característica de publicación

Desde la opción “Página maestra” en la sección “Aspecto” de la página de configuración del sitio podremos indicar nuestros propios ficheros de hoja de estilo sin tener que modificar la masterpage y podremos aplicarlo a todos los subsitios.

Dispondremos además una librearía de hojas de estilo donde almacenar nuestras css y poder establecerlas en la opción mencionada anteriormente.

Desde la masterpage también podremos utilizar los elementos “<SharePoint:CssLink>” y “<SharePoint:CssRegistration>” pero indicando en la url que utilice las hojas de estilo de la galería de estilos.

<SharePoint:CssRegistration name=”<% $SPUrl:~SiteCollection/Style Library/~language/Core Styles/ prueba.css%>” runat=”server”/>

Temas

Nos permiten cambiar la apariencia de nuestros sitios sin cambiar la distribución ni realizar modificaciones en las páginas. Los temas permiten cambiar el estilo, los colores y las imágenes asociadas a los estilos.

Para cambiar el tema de nuestro sitio podremos realizarlo desde el navegador en la opción “Tema del sitio” en la página de configuración del sitio.

Para crear nuevos temas podemos fijarnos de los existentes y extenderlos o adaptarlos. En la carpeta “12\Template\themes” estarán alojados todos los temas disponibles. Copiais una carpeta de un tema existente y lo renombráis pero en mayúsculas. Dentro existirá un fichero con extensión “.inf” lo renombrais (también en mayúsculas” con el mismo nombre que la carpeta que habéis creado. Abrís el fichero “.inf” y modificáis los títulos.

A continuación ya podéis editar vuestro tema incluyendo imágenes y hojas de estilo.

Una vez terminado tendréis que registrar el estilo en el fichero “\12\TEMPLATE\LAYOUTS\{Idioma}\SPTHEMES.XML”.

En el siguiente enlace podréis encontrar un ejemplo más detallado: http://www.sharepointblogs.com/tigirry/archive/2007/07/03/custom-site-theme-for-sharepoint-2007-moss-2007-and-wss-3-0.aspx

miércoles, 7 de enero de 2009

Habilitar intellisense para Xml de definición de Sharepoint

Uno de los problemas que nos encontramos al desarrollar componentes para Sharepoint es que no disponemos de una herramienta gráfica completa para definirlos, de manera que tenemos que ser nosotros los que editemos manualmente los xml de definición de nuestras features, contentypes, esquemas, etc...

Utilizaremos la ayuda de intellisense de Visual Studio para componer estos Xml’s. Para habilitarlo abriremos nuestro xml y en la ventana de propiedades en la propiedad “Schemas” seleccionaremos el icono de más detalle “…”.

Al seleccionarlo se abrirá una ventana con los esquemas predefinidos para el esquema “http://schemas.microsoft.com/sharepoint “.

A continuación dejaremos solo el fichero wss.xsd alojado en el directorio de sharepoint “Template\xml\wss.xsd”. Para desmarcar los ficheros seleccionaremos el valor “Automatic” en la columna “Use”.

Una vez seleccionado aceptamos las modificaciones y ya podremos disfrutar de la ayuda de Microsoft para completar nuestro xml.

lunes, 5 de enero de 2009

Novedades en Windows SharePoint Services 4.0?

Recientemente Michael Greth ha publicado dos post donde nos comenta algunas de las novedades que incorporará WSS 4.

Custom List Views and WSS 4.0’s XSLT-based List View

Custom Field Types and WSS 4.0’s XSLT-based Field Type

Según comenta Michael Greth, Microsoft ha publicado varios artículos (The CustomListView rule in Pre-Upgrade Checker can warn that customized list views that will not be upgraded y La regla CustomFieldType en Comprobador previas a la actualización en el Service Pack 2 de Windows SharePoint Services 3.0 puede advertir que campo personalizado no se actualizarán tipos) acerca de posibles errores con los list view y algunos customfields al actualizar a la nueva versión de Sharepoint Service.

De estos artículos Michael saca las siguientes conclusiones acerca de la siguiente versión WSS 4:

  • El List View WebPart evoluciona a una nueva versión XSLT-based List View Web Part con nuevas funcionalidades como la mejora en la personalización con Sharepoint Designer, formatos condicionales y mejoras en la experiencia del desarrollo con XSLT.
  • Aparecerá un nuevo tipo de campo llamada XSLT-based field type.

Bueno, veremos que pasa en estos meses que llegan, lo que si es seguro es que todos estamos deseando tener en nuestras manos la nueva versión.