El monstruito no soy yo, es el SharePoint

El Blog de Luis Mañez, dedicado a tecnologías MS, principalmente SharePoint y Office 365
SharePoint 2010: The content type is part of an application feature (error al borrar un Tipo de contenido)

Acabo de sufrir en “mis cannes”, este bonito error, justo cuando intentaba eliminar un tipo de contenido, que había creado una feature de una solución personalizada, que había desarrollado.

Lo primero a comprobar, que yo ya había hecho, es que ese tipo de contenido, no puede estar siendo usado en ninguna lista ni biblioteca. Además, debes comprobar que ese tipo de contenido, no sea tipo base, de algún otro contenido que sí se está usando. También puedes usar alguna herramienta del estilo SharePoint Manager, donde tienes un atributo Usage, que te dirá si se está usando en algún sitio.

Si ya has hecho esta comprobación, y aún así, te sigue dando el error, lo siguiente a comprobar (que ha sido mi salvación), es que NO tengas nada en la papelera de reciclaje. Y recuerda, que SharePoint tiene “2 papeleras”:

clip_image002[4]

clip_image002

clip_image002[7]

Tras esto, si desactivas la feature, el tipo de contenido debería de desaparecer.

Espero que os sirva, y si no, ya sabes:

Sonrisa

Saludos!!

Posted: 10/5/2012 19:14 por Luis Mañez | con no comments
Archivado en:
Office 365: Diferencias entre las funciones de Excep Web App y Excel 2010

Hoy me preguntaba cuántas funciones del Excel 2010 (el cliente, el de toda la vida), son compatibles con Excel Web App (en el Explorador). Pues bien, están perfectamente documentadas por Microsoft, y la sorpresa es que prácticamente todas las de Excel 2010, están disponibles para Excel Web App.

El listado de todas las funciones, lo tenemos aquí:

http://office.microsoft.com/en-us/web-apps-help/excel-functions-alphabetical-HA010342655.aspx

Mientras que las diferencias que nos podemos encontrar, entre usarlas en Excel 2010, o en Excel Web App, se resumen en la siguiente tabla:

image

Y también tenemos el Intellisense desde el navegador!

image

Por otro lado, os cuento algo que me ha extrañado muchísimo, y que me ha hecho perder 10 minutos de búsqueda:

Desde Excel Web App, NO se pueden añadir (ni eliminar) hojas al libro.

Por si no os lo creéis (yo no me lo creía…), aquí os dejo un post del foro de Office 365, donde un ingeniero de MS lo confirma:

http://community.office365.com/en-us/f/175/t/8239.aspx

Para añadir y eliminar hojas del libro, hay que pasar por el Excel cliente.

Saludos!!

Office 365: Añadir usuarios externos a listas de distribución

En este post vamos a ver como podemos añadir usuarios externos a la organización, en una lista de distribución.

Para ello, deberemos ser un usuario con permisos para administrar la organización. Una vez logado en OWA, nos vamos a “Opciones”:

image

Dentro de “Todas las opciones”, nos aseguramos de seleccionar “Administrar Mi organización”

image

Dentro de “Usuarios y grupos”, entramos en “Contactos externos”, y añadimos los emails externos que queremos añadir a la lista de distribución.

image

image

Una vez añadido el contacto externo, ya podemos añadirlo a nuestra lista de distribución.

image

Editamos nuestra lista de distribución, seleccionando la lista, y pulsando en “Detalles”

En la pantalla de edición de lista, pulsamos en la sección “Pertenencia”, y en el botón “Agregar”

image

En la ventana de selección de usuarios, buscamos los usuarios externos que añadimos anterioremente. Fijaros como los usuarios externos, tienen un icono diferente a los usuarios de la organización.

image

Añadimos el usuario, guardamos nuestra lista de distribución, y ya lo tenemos.

Espero que os sirva.

Saludos!!

Office 365: Desactivar conversaciones en OWA

Una de las características de OWA en Office 365, es la posibilidad de agrupar los correos, según el asunto del mismo. Es lo que se llama “Conversaciones”. Esto te agrupa aquellos emails reenviados, respuestas, etc, sobre un mail original. Me refiero a esto:

image

Sin embargo, yo no consigo acostumbrarme a esta vista, así que, si os pasa como a mi, podemos evitar esta agrupación por Conversaciones, si expandimos el menú “Ver”

image

Y desmarcamos la opción: “Usar conversaciones”

Saludos!!

Office Web Apps: Compartir documento desde Sky Drive

Como ya sabréis, desde Sky Drive, podemos usar las Office Web Applications para crear documentos Office.

En este post, vamos a ver lo sencillo que es compartir un documento.

image

Disponemos de varias opciones a la hora de compartir el documento:

  • Podemos enviarlo por correo electrónico:

image

De esta forma llega un mail al usuario, con un enlace al documento:

image

El usuario puede acceder al documento, y con una cuenta Live ID, puede editarlo y trabajar conjuntamente con su creador.

Una vez lo hemos enviado para compartir, si volvemos sobre la opción “Compartir”, podemos editar los permisos que queremos que tenga el usuario al que se lo hemos enviado:

image

También podemos volver a compartir con otras personas.

  • Compartir en redes sociales: Podemos vincularnos a diferentes redes sociales, y compartir el archivo en ellas. Aquí tenemos el listado completo de todas las redes compatibles: https://profile.live.com/cid-bbe19230d69f94c5/Services/ Por ejemplo, si me vinculo con Facebook, tenemos:

image

Y aparece publicado en mi muro:

image

  • Compartir mediante vínculo. Podemos crear un vínculo para compartir el archivo, con 3 niveles de permisos:

image

No sé a vosotros, pero a mi me encanta la facilidad de trabajo con las Office Web Apps, y podemos compartir archivos a través de un servicio como Sky Drive.

Saludos!!

Office 365: Compartir documentos para descarga en tu sitio público

Supongamos que tenemos nuestra web pública, creada con Office 365. Sería algo así:

image

Ahora imaginemos que queremos colocar varios documentos, para descarga de cualquier usuario que visite la web (casos de éxito, fichas de producto, portfolio, etc).

Para ello, podemos usar la biblioteca de documentos, que viene por defecto en nuestro sitio, o podemos crear nuestra propia biblioteca. Yo he creado una nueva biblioteca de documentos, llamada “Casos de exito”, y he subido un par de archivos, que quiero publicar para que pueda descargarlos cualquier usuario que visite mi web pública.

image

El siguiente paso, es hacer visibles esos documentos. Por desgracia, no existe un webpart de biblioteca, al estilo de los sitios de grupo, pero sí tenemos la posibilidad de crear hipervínculos a los documentos.

Por ejemplo, vamos a editar la página principal, y añadir una zona de Casos de éxito

image

Antes de añadir los enlaces, volvemos a la biblioteca de documentos, y copiamos el acceso directo a cada documento que queremos:

image

Volvemos a editar la página, y para cada documento creamos un Hipervínculo, desde la Ribbon.

Elegimos la opción de Sitio Web, y pegamos el enlace al documento (y editamos el texto a mostrar)

image

Nota: Como veis en la imagen, tenemos la opción de vincular un documento de la biblioteca “Mis Documentos”, que nos pone fácil la selección del documento, y no hay que ir copiando y pegando links. Sin embargo, si vamos a tener muchos documentos, y de varios “tipos”, probablemente sea más fácil de administrar, si creamos varias bibliotecas.

Aceptamos, guardamos la página, y ya tenemos preparado nuestra sección de casos de éxito.

image

Nota: Con este método, el link será un enlace a ver el documento en el navegador, si lo que queremos es que el usuario descargue el archivo directamente, tendremos que editar el enlace, para que apunte sólo al documento. Sería: sitio_web + nombre_biblioteca + nombre_documento. En este sentido, el enlazar documentos desde la biblioteca de Mis documentos, es más sencillo, ya que el hipervínculo que crea, es de esta forma.

Como vemos, los sitios públicos de Office 365, todavía necesitan alguna vuelta más, pero al menos, tenemos varios “workarrounds”, para poder hacer lo que necesitamos.

Saludos!!

SharePoint 2010: Usando el AjaxControlToolkit

Hace un tiempo me preguntaron si sería posible usar el AjaxControlToolkit dentro de SharePoint 2010.

Mi respuesta rápida fue que sí, que tan sólo bastaría con descargar el AjaxControlToolkit de la versión basada en el .NET Framework 3.5, que es la base de SharePoint 2010.

Sin embargo, cuando me puse a ello, no fue tan sencillo. Al parecer, las últimas versiones del AjaxControlToolkit, aún estando basadas en .NET 3.5, no son compatibles con SharePoint.

Finalmente, conseguí hacerlo funcionar, siguiendo las indicaciones de este post:

Ajax Control Toolkit with SharePoint 2010

Una vez conseguí hacerlo funcionar, me pregunté si sería viable en Office 365, y no, no lo es. Como no tenía muy claro el motivo de que no funcionase, rebusqué bastante por la web, hasta que me encontré un comentario del inmenso Wictor Willen en un post que trataba el tema.

Según comenta el propio Wictor aquí:

“Hi, this is not a bug. It’s a feature of the Sandbox. The SB creates its own copy of the Page object and “copies” some information from the real Page object to the SB page object – but not everything such as the ScriptMgr reference etc.”

Y para acabar, después de mis peripecias, mi recomendación se orienta más a no usar los controles del Toolkit, y tirar más hacia jQuery, y su extensión jQuery.UI

Saludos!

SharePoint 2010: Estableciendo las RSS por defecto de un sitio público

Lo que se pretende conseguir en este post, es que los “detectores” de fuentes RSS de los navegadores web, detecten la RSS de nuestro sitio público, que queremos establecer por defecto.

Me refiero a que, por ejemplo, si entramos en un sitio público de SharePoint, no tengamos desactivado, lo siguiente:

image

Antes de empezar con el cómo, os paso un link de cómo configurar las RSS en SharePoint 2010 (algo sencillísimo). Este link además, incluye cómo hacerlo por power-shell:

http://get-spscripts.com/2010/11/enabling-and-configuring-sharepoint-rss.html

A partir de aquí, tendremos la opción de RSS en la configuración de cualquier lista/biblioteca de SharePoint:

image

image

Volviendo a nuestro objetivo, conviene aclarar, que, para que un navegador detecte la fuente RSS, se utiliza el siguiente código HTML:

   1: <link rel="alternate" 
   2:     type="application/rss+xml" 
   3:     title="Tasks" 
   4:     href="/_layouts/listfeed.aspx?List=845f5cb5%2D09dd%2D4930%2D8534%2D61110a2df788" />

SharePoint ya se encarga de añadir ese HTML, siempre que estemos navegando por una lista/biblioteca que tenga las RSS activadas, tal y como vemos en esta imagen:

image

Sin embargo, no ocurre así cuando estamos en un sitio de publicación. En estos sitios, lo normal es activar las RSS de la biblioteca de páginas, ya que será lo que más interesa al usuario final.

En estos casos, cuando el usuario navega por páginas de la biblioteca de páginas, SharePoint no incluye el HTML de la RSS, y el usuario, se lleva la sensación de que no hay ninguna fuente RSS.

Podemos solucionarlo de forma muy sencilla, editando la MasterPage del sitio de publicación, e incluyendo ese HTML. Sin embargo, para este post, vamos a resolverlo de forma algo más “elegante”, a través de una Feature, que hará uso de los controles delegados de SharePoint.

Para saber qué es un Control delegado, podemos revisar los siguientes enlaces:

  1. Blog del CIIN: http://geeks.ms/blogs/ciin/archive/2011/10/22/sharepoint-2010-controles-delegados-i.aspx
  2. Blog Chris O’Brien http://www.sharepointnutsandbolts.com/2007/06/using-delegate-control.html

Nosotros vamos a “sobrescribir” el control delegado: “AdditionalPageHead”, que se sitúa dentro del HEAD de la página.

Primero de todo, vamos a crear un User Control, que sustituirá el Control delegado. Podéis ver aquí la estructura del proyecto SharePoint, y el código del control.

image

   1: <%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
   2: <%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   3: <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   4: <%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   5: <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
   6: <%@ Import Namespace="Microsoft.SharePoint" %> 
   7: <%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
   8: <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SetDefaultRssLinkControl.ascx.cs" Inherits="Spartans.Sharepoint.DefaultRss.ControlTemplates.Spartans.Sharepoint.DefaultRss.SetDefaultRssLinkControl" %>
   9: <link rel="alternate" 
  10:     type="application/rss+xml" 
  11:     title="Fuentes RSS" 
  12:     href="http://team.heroes.lab/_layouts/listfeed.aspx?List=%7B845F5CB5%2D09DD%2D4930%2D8534%2D61110A2DF788%7D&Source=http%3A%2F%2Fteam%2Eheroes%2Elab%2FLists%2FTasks%2FAllItems%2Easpx"  />

En el href del control, pondremos el link de la fuente RSS. Dicho link es muy sencillo de averiguar, basta con acceder a la biblioteca, y usar el botón RSS:

image

Lo siguiente que debemos decirle a SharePoint, es que utilice nuestro control, en lugar del control delegado. Para ello, creamos un nuevo item de tipo “Empty element”, y editamos el fichero Elements.xml:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:   <Control Id = "AdditionalPageHead" 
   4:            Sequence="50" 
   5:            ControlSrc="~/_ControlTemplates/Spartans.Sharepoint.DefaultRss/SetDefaultRssLinkControl.ascx" />
   6: </Elements>

Si desplegamos nuestra feature, y volvemos a nuestro sitio de publicación, tenemos:

image

y esto es así, porque nuestro código HTML, se ha ampliado en el HEAD, con el código HTML

image

Espero que os sirva.

Un saludo!!

Posted: 5/4/2012 15:35 por Luis Mañez | con no comments
Archivado en: ,
SharePoint 2010: Organizando webparts de la solución y vigilando las entradas SafeControl

Si tu solución de SharePoint posee varios webparts, quizá quieras considerar lo que os cuento en breve, de cara a tener una organización de los items del proyecto algo más limpia, y evitar entradas SafeControl innecesarias en el web.config.

Imaginemos que nuestra solución tiene 3 webparts visuales, añadidos a través de la plantilla de Visual Studio. Quedaría algo así:

image

Para empezar, fijaros en los NameSpaces que tenemos, para cada webpart:

   1: namespace Spartans.Sharepoint.OrganizedWebparts.VisualWebPart3
   2: //...
   3: namespace Spartans.Sharepoint.OrganizedWebparts.VisualWebPart2
   4: //...
   5: namespace Spartans.Sharepoint.OrganizedWebparts.VisualWebPart1

Un poco “feo” bajo mi punto de vista. Además, si nos vamos a las propiedades de cada webpart, y nos fijamos en la colección de Safe Control Entries:

image

image

Vemos que tenemos una entrada SafeControl, y lo mismo para el resto de webparts. Esto hará, que al desplegarlo, tengamos 3 entradas en nuestro Web.Config:

   1: <SafeControl Assembly="Spartans.Sharepoint.OrganizedWebparts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=76693daf4f35b7d3" Namespace="Spartans.Sharepoint.OrganizedWebparts.VisualWebPart1" TypeName="*" Safe="True" SafeAgainstScript="False" />
   2: <SafeControl Assembly="Spartans.Sharepoint.OrganizedWebparts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=76693daf4f35b7d3" Namespace="Spartans.Sharepoint.OrganizedWebparts.VisualWebPart2" TypeName="*" Safe="True" SafeAgainstScript="False" />
   3: <SafeControl Assembly="Spartans.Sharepoint.OrganizedWebparts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=76693daf4f35b7d3" Namespace="Spartans.Sharepoint.OrganizedWebparts.VisualWebPart3" TypeName="*" Safe="True" SafeAgainstScript="False" />

¿No sería más limpio organizar los Namespaces de forma algo más lógica, y sólo tener una entrada a nivel de web.config, que incluya todos los webparts de nuestra solución?

Vamos a ello !!

Primero de todo, ya que los webparts visuales se basan en controles de usuario, y es posible que nuestra solución tenga otros controles de usuario, vamos a añadir la carpeta mapeada de SharePoint “ControlTemplates”, y creamos una carpeta para todos nuestros controles:

image image

Ahora vamos a mover los controles de usuario que usan los webparts visuales, a esa carpeta. Y ya que estamos, vamos a cambiar el Namespace de los 3 controles, para que todos pertenezcan al mismo Namespace.

   1: namespace Spartans.Sharepoint.OrganizedWebparts.Web.UI

Recordar que al cambiar el Namespace, también lo tenemos que hacer en el fichero .ascx, en el atributo “Inherits” de la directiva “Control”:

   1: <%@ Control 
   2:     Language="C#" 
   3:     AutoEventWireup="true" 
   4:     CodeBehind="VisualWebPart3UserControl.ascx.cs" 
   5:     Inherits="Spartans.Sharepoint.OrganizedWebparts.Web.UI.VisualWebPart3UserControl" %>

Ahora tenemos que cambiar algunas cosas de los webparts.

Primero de todo, ya que no queremos varias entradas SafeControl en el web.config, las eliminamos de las propiedades.

image

Lo siguiente es re-apuntar a la nueva ubicación de los controles:

   1: [ToolboxItemAttribute(false)]
   2: public class VisualWebPart3 : WebPart
   3: {
   4:     // Visual Studio might automatically update this path when you change the Visual Web Part project item.
   5:     private const string _ascxPath = @"~/_CONTROLTEMPLATES/OrganizedControls/VisualWebPart3UserControl.ascx";
   6:  
   7:     protected override void CreateChildControls()
   8:     {
   9:         Control control = Page.LoadControl(_ascxPath);
  10:         Controls.Add(control);
  11:     }
  12: }

Y ya que nos ponemos, vamos a cambiar el Namespace de los webparts, y agruparlos en el mismo:

   1: namespace Spartans.Sharepoint.OrganizedWebparts.Web.UI.Webparts

Al cambiar el Namespace, tenemos que actualizar también el fichero .webpart

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <webParts>
   3:   <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
   4:     <metaData>
   5:       <type name="Spartans.Sharepoint.OrganizedWebparts.Web.UI.Webparts.VisualWebPart1, $SharePoint.Project.AssemblyFullName$" />
   6:       <importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
   7:     </metaData>
   8:     <data>
   9:       <properties>
  10:         <property name="Title" type="string">Oraganized webparts VisualWebPart1</property>
  11:         <property name="Description" type="string">This is webpart 1, from Organized webparts sample</property>
  12:       </properties>
  13:     </data>
  14:   </webPart>
  15: </webParts>

Para acabar, nos falta configurar la solución para que genere una única entrada de SafeControl en el web.config. Para ello, vamos a utilizar el editor del Manifest del paquete de nuestra solución. Este editor, permite combinar el XML que ha autogenerado Visual Studio, con nuestros propios valores insertados en el cuadro de texto.

image

Añadimos nuestra entrada de SafeControl:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Solution xmlns="http://schemas.microsoft.com/sharepoint/">
   3:   <Assemblies>
   4:     <Assembly Location="Spartans.Sharepoint.OrganizedWebparts.dll" DeploymentTarget="GlobalAssemblyCache">
   5:       <SafeControls>
   6:         <SafeControl Assembly="Spartans.Sharepoint.OrganizedWebparts" Namespace="Spartans.Sharepoint.OrganizedWebparts.Web.UI.Webparts" TypeName="*" />
   7:       </SafeControls>
   8:     </Assembly>
   9:   </Assemblies>
  10: </Solution>

Si hacemos el Deploy de la solución, ya vemos que tenemos una única entrada SafeControl en el web.config:

   1: <SafeControl Assembly="Spartans.Sharepoint.OrganizedWebparts, Version=1.0.0.0, Culture=neutral,     PublicKeyToken=76693daf4f35b7d3" 
   2:     Namespace="Spartans.Sharepoint.OrganizedWebparts.Web.UI.Webparts" 
   3:     TypeName="*" 
   4:     Safe="True" 
   5:     SafeAgainstScript="False" />

Al indicar el TypeName como “*”, estamos incluyendo todos los controles de ese Namespace (todos nuestros webparts de la solución).

Si además, vemos nuestra DLL con algún “Decompiler” (Reflector, ILSpy, JustDecompile…), vamos que nuestro namespaces, webparts y controls, están ordenaditos:

image

Si tenemos una solución con mucho desarrollo personalizado, seguro que agradecemos este orden.

Espero que os sirva.

Saludos!!

30

Posted: 3/4/2012 8:30 por Luis Mañez | con no comments
Archivado en:
Office 365: No me aparecen los tipos de contenido de Excel, PowerPoint y OneNote

Sinceramente, desconozco el motivo, pero mi SharePoint Online no viene por defecto con los tipos de contenido de Office (excepto Word, que es el tipo por defecto para las bibliotecas de documentos).

En este post he encontrado la solución, aunque no la explicación:

http://office.microsoft.com/en-us/sharepoint-online-enterprise-help/add-multiple-office-templates-to-a-document-library-HA102409514.aspx

Tras seguir los pasos, que básicamente consiste en crear un nuevo tipo de contenido personalizado, que hereda de documento, y configurar sus propiedades avanzadas, donde en la plantilla a utilizar, la damos un fichero en blanco de tipo Office que queramos.

En ese mismo post, pone la siguiente nota:

“if your organization is using SharePoint Online/Microsoft Office 365, and you use the Microsoft Office Web Applications instead of Microsoft Office client programs, you must follow the steps in this article to enable users to create multiple Microsoft Office document types in a document library from within the browser.”

Esto pretende ser la explicación de por qué no aparecen esos tipos de contenido por defecto. Pero como os digo, pues no lo tengo muy claro, ya que en mi caso, usamos los clientes de Office. Al menos hasta donde yo lo entiendo.

Sea como sea, por lo menos tenemos una solución. Yo lo he hecho con OneNote, y funciona bien:

image

Si alguien sabe el motivo, que lo deje como comentario y actualizaré el post. Yo voy a seguir indagando.

Saludos!!

SharePoint 2010: Cacheando webparts visuales con OutputCache

¿Te va lento tu sitio de SharePoint? … menuda preguntita

Si la respuesta es que sí, o al menos, crees que sí, es posible que este post te pueda ayudar. Ojo, no voy a preguntar, cómo has llegado hasta esa “lentitud”, y ya te aseguro, que habrá muchas más soluciones, pero aquí vamos a ver una posible solución, bastante rápida de probar, y de deshacer en caso de que no te sirva.

Otra condición para que te pueda ser útil tu post, es que tu desarrollo haga uso de UsersControls de asp.net (si tienes webparts visuales, tienes UserControls Sonrisa)

Y la última condición, es la de siempre, cuando se trata de Cache, y es que la información que muestras en ese caso, no necesitas que sea “tiempo real”

Un caso concreto, bastante típico, es cuando has desarrollado algún control para una navegación personalizada. Es muy posible que tengas algoritmos recursivos complejos, que penalizan el rendimiento, y también es muy posible, que ese menú, cambie muy de vez en cuando.

Al lío. Partimos de un visual webpart. Si queremos cachear el contenido que genera ese user control, es tan sencillo como usar la directiva OutputCache sobre el .ascx:

   1: <%@ OutputCache Duration="10" VaryByParam="None" %>

El atributo Duration indica el tiempo que se cacheará el contenido, y se expresa en segundos. El atributo VaryByParam, ahora luego lo explicaremos. De momento lo dejamos a “None”, que indica que no se tenga en cuenta (es obligado indicar algún valor).

Para probar que se cachea, vamos a añadir una etiqueta a nuestro control, que muestre la hora actual:

   1: public partial class CachedWebPartUserControl : UserControl
   2: {
   3:     protected void Page_Load(object sender, EventArgs e)
   4:     {
   5:         String message = String.Format("Time: {0}", DateTime.Now);
   6:         lblInfo.Text = message;
   7:     }
   8: }

Hacemos el deploy y lo añadimos a una página.

image

No se puede ver, pero cuando refresco el navegador, el valor sigue siendo el mismo, hasta dentro de 10 segundos, que se refresca a la hora actual. Funciona!! Sonrisa

¿Y que ocurre si mi webpart, muestra datos en función de algún parámetro que llega por QueryString? Pues para eso, podemos utilizar el VaryByParam, indicando el nombre del parámetro que viaja en la querystring:

   1: <%@ OutputCache Duration="10" VaryByParam="option" %>

Si modificamos ligeramente el código del usercontrol con:

   1: protected void Page_Load(object sender, EventArgs e)
   2: {
   3:     string option = Request.QueryString["option"];
   4:  
   5:     if (String.IsNullOrEmpty(option))
   6:     {
   7:         option = "A";
   8:     }
   9:  
  10:     String message = String.Format("QuestyString option: {1}. Time: {0}", DateTime.Now, option);
  11:     lblInfo.Text = message;
  12: }

Y volvemos a probar, veremos que en este caso, el contenido se cachea según el valor de la querystring “option”. Por ejemplo, cargamos la página por primera vez, y obtenemos:

QuestyString option: A. Time: 3/23/2012 6:29:54 PM

Si acto seguido (antes de que pasen los 10 segundos), cargamos la página de nuevo, pero pasando por querystring: “?option=B”, tenemos:

QuestyString option: B. Time: 3/23/2012 6:29:58 PM

Fijaros que todavía no se han cumplido los 10 segundos, y vemos un valor actualizado con la “option=B”.

Te recomiendo que le eches un vistazo a todas las posibilidades de la directiva OutputCache, ya que tiene más opciones que quizá te interesen (por ejemplo, cachear, no en función de un parámetro, sino del valor que tome otro control: listbox, textbox, etc).

Para acabar, otra recomendación importante, es que antes de hacer nada, midas que es lo que está causando ese mal rendimiento. Porque: ¿seguro que va lento? ¿seguro que es un problema de tu código? (igual es la red, o que el servidor está mal dimensionado, o la instalación, o la alineación de Júpiter con Saturno…)

Para medir esto, podemos utilizar 2 objetos:

Lecturas recomendadas:

Articulos panel del desarrollador (Por Gustavo Velez):

http://www.gavd.net/servers/sharepointv4/spsv4_item.aspx?top=4&itm=972

http://www.gavd.net/servers/sharepointv4/spsv4_item.aspx?top=art&itm=1417

http://www.gavd.net/servers/sharepointv4/spsv4_item.aspx?top=1&itm=1433

Serie “Developing for Perfomance” (por Tobias Zimmergren)

http://www.zimmergren.net/technical/sp-2010-developing-for-performance-part-1-developer-dashboard

Office 365: Configurando Lync 2010 para iPad

Ya hace un tiempo que tenemos disponible Lync para iPad, pero todavía no lo había probado, y la verdad, es que me ha sorprendido gratamente.

Podéis descargarlo desde iTunes (http://itunes.apple.com/us/app/microsoft-lync-2010-for-ipad/id484222449?mt=8), y es muy sencillo de configurar. Lo único que os puede marear, es en el caso de que estéis utilizando más de un dominio de Office 365: por ejemplo, el típico de “nnn.onmicrosoft.com”, y el corporativo de la empresa: “fabrikam.com”.

En este caso, tenemos que introducir 2 nombres de usuario diferentes. El primero es el del dominio “nnn.onmicrosoft.com”, mientras que el segundo, es el usuario de tu dominio corporativo: “fabrikam.com”

login_lync_ipad

Y una vez configurado, ya podemos usar lync desde el iPad:

image

Espero que os sirva.

Saludos!!

Posted: 20/3/2012 20:40 por Luis Mañez | con no comments |
Archivado en: ,,
Office 365: Provisionando PropertyBags de forma declarativa (idem para SharePoint 2010)

Seguramente, si habéis desarrollado alguna solución para SharePoint, más allá de los típicos webparts, habréis necesitado almacenar “parámetros” de configuración, por ejemplo, la URL de un servicio web en Azure, tu AppId para usar Bing Maps, etc.

Existen varias opciones para hacer esto, yo hoy os voy a hablar de usar las PropertyBags. En SharePoint, la mayoría de los objetos, tienen una propiedad “Properties” que suele ser un HashTable o un SPPropertyBag para poder almacenar propiedades en modo key-value.

Algunas clases que contienen esa propiedad son:

Si queremos provisionar valores a ese campo de forma declarativa, lo podemos hacer usando un elemento Module, de Visual Studio.

En su Elements,xml, usaremos el nodo PropertyBag. En el MSDN está perfectamente explicado el significado de cada propiedad. Yo os dejo un ejemplo de uso de todas las combinaciones posibles:

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
   3:   <!--Propiedad creada a nivel de 'site collection'-->
   4:   <PropertyBag HyperlinkBaseUrl="http://team.heroes.lab" Url="" ParentType="Web" RootWebOnly="TRUE">
   5:     <Property Name="ProductsListGuid" Value="2b2b944d-8cc8-4448-bcb2-9478d0787175" Type="string" />
   6:   </PropertyBag>
   7:   <!--Propiedad creada a nivel de sub-site-->
   8:   <PropertyBag HyperlinkBaseUrl="http://team.heroes.lab/sites/site1" Url="" ParentType="Web" RootWebOnly="FALSE">
   9:     <Property Name="ProductsListGuid" Value="2b2b944d-8cc8-4448-bcb2-9478d0787175" Type="string" />
  10:   </PropertyBag>
  11:   <!-- Propiedad creada a nivel de File, en este caso para una Master Page-->
  12:   <PropertyBag HyperlinkBaseUrl="http://team.heroes.lab/" Url="_catalogs/masterpage/default.master" ParentType="File" RootWebOnly="FALSE" />
  13:   <!-- Propiedad creada a nivel de SPListItem, item ID 23 de la lista Products -->
  14:   <PropertyBag HyperlinkBaseUrl="http://team.heroes.lab/sites/site1" Url="Lists/Products" ParentType="ListItem" ItemIndex="23">
  15:     <Property Name="DiscountPercentage" Value="10" Type="int" />
  16:   </PropertyBag>
  17: </Elements>

Con esto, al desplegar nuestra solución, provisionaremos esas Properties a nuestros elementos (webs, ficheros o items de listas).

Para acabar, un simple ejemplo de como iterar por esa bolsa de propiedades. En este caso, recorremos las Properties del SPWeb raíz:

   1: SPWeb rootWeb = SPContext.Current.Site.RootWeb;
   2:  
   3: foreach (DictionaryEntry entry in rootWeb.AllProperties)
   4: {
   5:     string property = String.Format("{0}, {1}{2}", entry.Key, entry.Value, Environment.NewLine);
   6:     txtPropertyBag.Text += property;
   7: }

Espero que os sirva.

Un saludo!!

SharePoint 2010: Cambiando el GUID de una clase que hereda de SPFeatureReceiver

Recientemente, he tenido que cambiar GUIDs, nombres y demás, a un proyecto SharePoint de Visual Studio.

Pues bien, si se cambia el GUID de una clase que es manejadora de los eventos de una Feature:

   1: /// <summary>
   2: /// This class handles events raised during feature activation, deactivation, installation, uninstallation, and upgrade.
   3: /// </summary>
   4: /// <remarks>
   5: /// The GUID attached to this class may be used during packaging and should not be modified.
   6: /// </remarks>
   7: [Guid("bbd1a0cd-e938-4483-8328-e63209dc2f1c")]
   8: public class MyProjectEventReceiver : SPFeatureReceiver
Tendremos que cambiar también el ID que aparece en las propiedades de la Feature, desde Visual Studio.

image

Sin embargo, si usamos la herramienta para generar GUIDs de Visual Studio:

image

Nos generará un GUID en mayúsculas, que si tal cual colocamos, tanto en el fichero de la clase, como en las propiedades de la feature, al desplegarlo en SharePoint, no encontraremos el pantallazo de error.

No sé si, porque me sonaba de haber leído algo parecido, o porque lo soñé, o porque ya llevo mis añitos viendo cosas “raras”, se me ocurrió que podía ser que el GUID debiera estar en minúsculas, así que, a ello fui. Y, sin cambiar nada más, la cosa funcionó!!, así que me temo que esa era la causa.

Espero que os sirva.

Saludos!!

Office 365: Branding en SharePoint Online con URLs relativas a mi colección de sitios (II)

Previously on Fringe

Digo, anteriormente vimos cómo referenciar hojas de estilos con rutas relativas a una colección de sitios de SharePoint Online, o a un sitio concreto. Sin embargo, esa misma técnica, no es aplicable si lo que queremos son añadir referencias a archivos .js.

Si intentamos hacer algo como lo siguiente:

   1: <script type="text/javascript" src="<%$SPUrl:~SiteCollection/Style Library/JQUERY/mainFunctions.js%>"></script>

Obtendremos una pantalla de error, con su correspondiente CorrelationID. En ese mismo error, ya veremos una pista de cómo resolverlo. Ya que nos dirá que debemos sustituirlo por un asp:literal.

Si le hacemos caso, y lo colocamos en el lugar adecuado, obtendremos el resultado esperado. Quedando como:

<script type="text/javascript" src='<asp:Literal runat="server" Text="<%$SPUrl:~SiteCollection/Style Library/JQUERY/mainFunctions.js%>" />'></script>

Otra opción que también parece funcionar, consiste en utilizar el control de SharePoint ScriptLink

   1: <SharePoint:ScriptLink ID="MyScriptLink1" Name="~sitecollection/Style Library/Home/JS/myscript.js" runat="server" />
Saludos!!
Office 365: Añadir opciones a un campo SPFieldChoice, no es tan evidente con la Sandbox!!

Hoy me he encontrado que algo tan “sencillo”, como añadir “options” a un campo de tipo SPFieldChoice, no es tan sencillo cuando lo hacemos en SharePoint online.

Si queremos añadir una opción más a un campo dado, el código sería tan sencillo como:

   1: try
   2: {
   3:     SPList list = SPContext.Current.Web.Lists.TryGetList("Products");
   4:  
   5:     if (list == null)
   6:     {
   7:         throw new SPException("List not found");
   8:     }
   9:  
  10:     SPFieldChoice fieldChoice = list.Fields.GetField("ChoiceColumn") as SPFieldChoice;
  11:     fieldChoice.Choices.Add("New option");
  12:  
  13:     fieldChoice.Update();
  14: }
  15: catch (Exception ex)
  16: {
  17:     TextBox1.Text = ex.ToString();
  18: }

Si eso mismo, lo desplegamos en una solución de granja, funciona perfectamente.

Sin embargo, si lo hacemos en una solución sandbox, no obtendremos ningún error, pero la opción nunca se añadirá al SPFieldChoice.

En principio, la clase SPFieldChoice es perfectamente válida en Sandboxed solutions, su propiedad Choices también lo es.

El motivo lo desconozco por completo, y además, me parece rarísimo, ya que he revisado con Reflector el código del método UpdateInternal, y me parece de lo más sencillo, así que no me explico que puede haber diferente en la dll de la Sandbox, para que no funcione.

Por suerte, sí tenemos solución, y es tan “sencilla”, como editar la propiedad SchemaXml, y añadirle el XML necesario para la nueva Opción. Aquí podemos ver un ejemplo:

   1: <Field Type="Choice" DisplayName="ChoiceColumn" Required="FALSE" EnforceUniqueValues="FALSE" Indexed="FALSE" Format="Dropdown" FillInChoice="FALSE" ID="{5a7765f4-07c7-4dd9-8237-1f73174bede0}" SourceID="{e71844c7-9724-47c7-92d1-6c279e3ad8a0}" StaticName="ChoiceColumn" Name="ChoiceColumn" ColName="nvarchar3" RowOrdinal="0" Version="3">
   2:   <Default>Option 1</Default>
   3:   <CHOICES>
   4:     <CHOICE>Option 1</CHOICE>
   5:     <CHOICE>Option 2</CHOICE>
   6:     <CHOICE>Option 3</CHOICE>
   7:     <CHOICE>New option</CHOICE>
   8:   </CHOICES>
   9: </Field>

Esto lo podemos hacer bien sencillo con LINQ to XML:

   1: //Get SPFieldChoice from desired List
   2: SPFieldChoice fieldChoice = GetChoiceColumn();
   3:  
   4: //Parse SchemaXml property as XElement
   5: XElement fieldXml = XElement.Parse(fieldChoice.SchemaXml);
   6:  
   7: //Create XElement node: <CHOICE>now</CHOICE>
   8: XElement choice = new XElement("CHOICE");
   9: choice.SetValue("Added_" + DateTime.Now.ToString());
  10: //Get CHOICES node and Add new CHOICE node
  11: fieldXml.Element("CHOICES").Add(choice);
  12: //Update SchemaXml and Field
  13: fieldChoice.SchemaXml = fieldXml.ToString();
  14: fieldChoice.Update();

Y así, podemos añadir una nueva opción a nuestro campo SPFieldChoice en soluciones Sandbox.

Saludos!!

Office 365: Error al desactivar una solución Sandbox que es una Site template

Si habéis guardado algún sitio de Office 365 como plantilla, y desplegáis la solución en otro site o colección de sitios, es posible que os encontréis un error al intentar desactivar la solución.

Seguramente os ocurrirá si habéis estado creando y eliminando sitios basados en esa plantilla.

Para poder desactivar la solución sin que os falle, primero, obviamente, tendremos que asegurarnos de que no hay ningún site existente basado en esa plantilla.

Además, y esto ya no es tan evidente, es que te asegures que no tienes nada relacionado con esa plantilla, en la papelera de reciclaje:

image

Y lo último, y nada evidente, es que compruebes esto mismo, en la “otra” papelera de reciclaje (sí, es la misma papelera, pero tiene 2 vistas diferentes, y desde el link anterior, sólo vemos una de ellas):

image

Y dentro de esta, revisa las 2 vistas disponibles:

image

Que por cierto, las 2 vistas tienen el mismo nombre, pero creo que es por una mala traducción del Inglés, ya que en inglés se llaman:

  • End user recicle bin items
  • Deleted from end user recicle bin items

Después de eliminar todo lo relacionado con esa plantilla (sitios eliminados que estaban basados en esa plantilla), ya deberías poder desactivar la solución sin problemas.

Nada más, agradecer a mi compañero Juan Moreno, que se dio unos cuantos cabezazos hasta encontrar esa “papelera escondida” Sonrisa

Saludos!!

SharePoint 2010: Liberada nueva versión de la SharePoint Software Factory

Hace un tiempo os hablé de la SharePoint Software Factory. Pues bien, hace unos días que se ha liberado una nueva versión, la 3.2

Os copio la lista de novedades, y os pongo algún pantallazo de mis favoritas Sonrisa

  • Menu "List And Doc": Linq to SharePoint (imports the schema of several lists to LINQ classes)
  • Menu "BCS": Simple BCS Model
  • Menu "BCS": Import BCS Model from Database
  • Menu "BCS": Model BCS Model with classes
  • Menu "BCS": Quick Deploy BCS Model (undeploys/deploys BCS model via powershell)
  • Menu "Security": Minimal CAS, Medium CAS, recipes for single CAS Policy Items etc.
  • Menu "ASP.NET": WCF Webservice
  • code snippets added, partly from http://spcodesnippets.codeplex.com Thx to Ayman El-Hattab (http://aymanelhattab.com)
  • Added custom FxCopDictionary to allow project specific exclusions for abbreviations, keyword, acronyns etc. Dictionary will be automatically used in Realase build configuration.

Fijaros que maravilla para generar un data context de LINQ to SharePoint:

image

Tras el asistente, nos genera, por un lado, un fichero XML de configuración del SPMetal, por si queremos repetir la generación, y por otro lado, 2 ficheros con una clase parcial para el contexto.

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <!-- 
   3: Use this file to re-import the lists for LINQ to SharePoint
   4: Imported from URL: http://team.heroes.lab/
   5: Call to SPMetal: "C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\BIN\spmetal.exe" /web:"http://team.heroes.lab/" /parameters:"E:\ORIGEN\Alejandria\Lab\SPSF.v32.ApplicationSample\Components\LinqToSharePoint1\LinqToSharePoint1Context.xml" /language:csharp /namespace:SPSF.v32.ApplicationSample.Components /code:"E:\ORIGEN\Alejandria\Lab\SPSF.v32.ApplicationSample\Components\LINQToSharePointDefinitions\LinqToSharePoint1\LinqToSharePoint1Context.designer.cs"
   6: -->
   7: <!-- Code initially generated with SharePoint Software Factory 2010, Version 3.2 , spsf.codeplex.com -->
   8: <Web
   9:     AccessModifier="Public"
  10:     Class="LinqToSharePoint1Context" xmlns="http://schemas.microsoft.com/SharePoint/2009/spmetal">
  11:     <List
  12:         Name="Announcements">
  13:         <ContentType
  14:             Name="Anuncio">
  15:             <Column
  16:                 Name="ContentType" />
  17:             <Column
  18:                 Name="Title" />
  19:             <Column
  20:                 Name="Body" />
  21:             <Column
  22:                 Name="Expires" />
  23:             <ExcludeOtherColumns />
  24:         </ContentType>
  25:         <ContentType
  26:             Name="Carpeta">
  27:             <Column
  28:                 Name="ContentType" />
  29:             <Column
  30:                 Name="Title" />
  31:             <Column
  32:                 Name="FileLeafRef" />
  33:             <Column
  34:                 Name="ItemChildCount" />
  35:             <Column
  36:                 Name="FolderChildCount" />
  37:             <ExcludeOtherColumns />
  38:         </ContentType>
  39:     </List>
  40:     <ExcludeOtherLists />
  41:     <ExcludeOtherContentTypes />
  42: </Web>
image image

También podemos añadir servicios de WCF, donde la plantilla ya prepara el package para su despliegue en el servidor de SharePoint:

image

image

Otra novedad es que se han añadido numerosos code-snippets. Aquí tenemos las categorías:

image

Destacar también que dispone de un asistente para migrar a esta última versión, proyectos realizados en la versión anterior.

Un saludo!!

SharePoint 2010: Búsqueda sin resultados, cuando sí los hay y el usuario puede verlos

Cuando se realiza una búsqueda en SharePoint, se aplica un filtrado de los resultados, según el usuario que lanza la query. Es decir, si un usuario no tiene permisos sobre una lista concreta, obviamente, los resultados que hagan referencia a esa lista, no le aparecerán al usuario.

Ahora bien, hoy me he encontrado con un caso que no cumplía esta premisa, y que puede ser bastante frecuente durante la fase de desarrollo del proyecto. Resulta que estaba lanzando una búsqueda con un usuario que era Colaborador del site, por lo que tiene permisos para ver y editar todas las listas, y sin embargo, en las búsquedas, no me devolvía ningún resultado. Sin embargo, me iba a una lista cualquiera, y podía ver y editar un item que cumplía con la query de búsqueda.

De hecho, si hacía la misma búsqueda con otro usuario colaborador, sí me salían resultados válidos. ¿¿??

Pues bien, aquí van los motivos:

  • No tenía programado ningún crawling, ni completo ni incremental. Al ser un entorno de desarrollo, lo que hago es forzar el crawl según necesito.
  • El usuario que no devolvía resultados de la búsqueda, lo había añadido al sitio, después de haber hecho el último crawl.
  • Al forzar un nuevo crawling, y probar de nuevo con el usuario que no devolvía nada, ahora, sí me devolvía los resultados de búsqueda esperados.

La conclusión es que el índice de búsquedas que monta SharePoint, copia mucha información del contenido, incluyendo, los permisos de los usuarios.

Para comprobarlo, he repetido el proceso:

  • He quitado del site a otro usuario que era colaborador
  • He forzado un nuevo crawling
  • He vuelto a añadir al usuario como colaborador
  • He realizado una búsqueda con dicho usuario, y efectivamente, no he obtenido ningún resultado de búsqueda.
  • He forzado un segundo crawling
  • Al volver a buscar con el mismo usuario, ya aparecían los resultados de la búsqueda esperados.

Moraleja:

Lleva esto en mente, y programa el crawling incremental y completo, según las necesidades de que dichos resultados estén “actualizados”. Ten en cuenta que a parte de esos permisos, también copia gran parte del contenido, por lo que es muy sencillo que elementos que hayan sido eliminados, o actualizado algún metadato, sigan apareciendo en los resultados de búsquedas con una versión incorrecta.

Saludos!!

Posted: 21/2/2012 8:39 por Luis Mañez | con no comments
Archivado en: ,
SharePoint 2010: Explicación del código de un Site template de SharePoint

Cuando creamos un nuevo sitio de SharePoint, debemos elegir una plantilla de sitio, en la que queremos basar nuestro nuevo sitio. Si lo hacemos desde la interfaz web, lo tenemos muy fácil, y tan sólo tenemos que elegirla, tal y como vemos en la imagen:

image image

Si queremos hacerlo desde power-shell, podemos usar el comando New-SPSite donde con el parámetro Template, le daremos la plantilla a utilizar. Ese parámetro, nos pide un código de plantilla. Podemos ver los códigos instalados, con otro comando de power shell:

   1: Get-SPWebTemplate

Que nos dará un listado como el siguiente (repetido para cada idioma instalado):

   1:  
   2: Name                 Title                                    LocaleId   Custom    
   3: ----                 -----                                    --------   ------    
   4: GLOBAL#0             Global template                          1033       False     
   5: STS#0                Team Site                                1033       False     
   6: STS#1                Blank Site                               1033       False     
   7: STS#2                Document Workspace                       1033       False     
   8: MPS#0                Basic Meeting Workspace                  1033       False     
   9: MPS#1                Blank Meeting Workspace                  1033       False     
  10: MPS#2                Decision Meeting Workspace               1033       False     
  11: MPS#3                Social Meeting Workspace                 1033       False     
  12: MPS#4                Multipage Meeting Workspace              1033       False     
  13: CENTRALADMIN#0       Central Admin Site                       1033       False     
  14: WIKI#0               Wiki Site                                1033       False     
  15: BLOG#0               Blog                                     1033       False     
  16: SGS#0                Group Work Site                          1033       False     
  17: TENANTADMIN#0        Tenant Admin Site                        1033       False     
  18: ACCSRV#0             Access Services Site                     1033       False     
  19: ACCSRV#1             Assets Web Database                      1033       False     
  20: ACCSRV#3             Charitable Contributions Web Database    1033       False     
  21: ACCSRV#4             Contacts Web Database                    1033       False     
  22: ACCSRV#6             Issues Web Database                      1033       False     
  23: ACCSRV#5             Projects Web Database                    1033       False     
  24: BDR#0                Document Center                          1033       False     
  25: OFFILE#0             (obsolete) Records Center                1033       False     
  26: OFFILE#1             Records Center                           1033       False     
  27: OSRV#0               Shared Services Administration Site      1033       False     
  28: PowerPointBroadca... PowerPoint Broadcast Site                1033       False     
  29: PPSMASite#0          PerformancePoint                         1033       False     
  30: BICenterSite#0       Business Intelligence Center             1033       False     
  31: SPS#0                SharePoint Portal Server Site            1033       False     
  32: SPSPERS#0            SharePoint Portal Server Personal Space  1033       False     
  33: SPSMSITE#0           Personalization Site                     1033       False     
  34: SPSTOC#0             Contents area Template                   1033       False     
  35: SPSTOPIC#0           Topic area template                      1033       False     
  36: SPSNEWS#0            News Site                                1033       False     
  37: CMSPUBLISHING#0      Publishing Site                          1033       False     
  38: BLANKINTERNET#0      Publishing Site                          1033       False     
  39: BLANKINTERNET#1      Press Releases Site                      1033       False     
  40: BLANKINTERNET#2      Publishing Site with Workflow            1033       False     
  41: SPSNHOME#0           News Site                                1033       False     
  42: SPSSITES#0           Site Directory                           1033       False     
  43: SPSCOMMU#0           Community area template                  1033       False     
  44: SPSREPORTCENTER#0    Report Center                            1033       False     
  45: SPSPORTAL#0          Collaboration Portal                     1033       False     
  46: SRCHCEN#0            Enterprise Search Center                 1033       False     
  47: PROFILES#0           Profiles                                 1033       False     
  48: BLANKINTERNETCONT... Publishing Portal                        1033       False     
  49: SPSMSITEHOST#0       My Site Host                             1033       False     
  50: ENTERWIKI#0          Enterprise Wiki                          1033       False     
  51: SRCHCENTERLITE#0     Basic Search Center                      1033       False     
  52: SRCHCENTERLITE#1     Basic Search Center                      1033       False     
  53: SRCHCENTERFAST#0     FAST Search Center                       1033       False     
  54: visprus#0            Visio Process Repository                 1033       False     

Es el Name de ese listado, el que debemos utilizar para el parámetro Template. Ejm:

   1: New-SPSite http://www.contoso.com 
   2:     -OwnerAlias "DOMAIN\jdoe" 
   3:     -HostHeaderWebApplication $w 
   4:     -Name "Contoso" 
   5:     -Template "STS#0"

Pero ¿qué significan esos códigos?

Pues bien, los Site Definition de SharePoint, se componen, entre otras cosas, de 2 ficheros .XML:

  • webTemp.xml: Existe uno por cada lenguaje instalado, y contiene las entradas de las plantillas de sitio, que luego se listan en las primeras imágenes del post.
  • ONET.xml: Contiene las configuraciones de cada plantilla, como pueden ser las listas, módulos, features a nivel site y web, etc.

Si abrimos el fichero webTemp.xml, que se almacena en \14\Template\Locale\XML\ veremos varias entradas de este tipo:

   1: <Template Name="STS" ID="1">
   2:    <Configuration ID="0" Title="Team Site" Hidden="FALSE" ImageUrl="/_layouts/images/stts.png" Description="A site for teams to quickly organize, author, and share information. It provides a document library, and lists for managing announcements, calendar items, tasks, and discussions." DisplayCategory="Collaboration" >    </Configuration>
   3:    <Configuration ID="1" Title="Blank Site" Hidden="FALSE" ImageUrl="/_layouts/images/stbs.png" Description="A blank site for you to customize based on your requirements." DisplayCategory="Collaboration" AllowGlobalFeatureAssociations="False" >    </Configuration>
   4:    <Configuration ID="2" Title="Document Workspace" Hidden="FALSE" ImageUrl="/_layouts/images/stdw.png" Description="A site for colleagues to work together on a document. It provides a document library for storing the primary document and supporting files, a tasks list for assigning to-do items, and a links list for resources related to the document." DisplayCategory="Collaboration" >    </Configuration>
   5: </Template>

Pues bien, si volvéis a fijaros en los códigos de las Template, veréis que se forman como:

   1: Name + # + ID configuración

¿Y cómo se relaciona con el fichero ONET.xml (que es el que contiene la chicha de la definición del Site)?

Pues bien, lo primero es que dentro del directorio \14\Tempate\SiteTemplates, tendremos una carpeta con el nombre del atributo Name del nodo Template. Es en esa carpeta, dentro de la subcarpeta \XML, donde encontraremos el ONET.xml. Si vemos ese fichero, veremos que hay una parte de Configurations, donde coinciden los IDs de cada nodo Configuration del webTeml.xml

   1: <Configurations>
   2:   <Configuration ID="-1" Name="NewWeb" MasterUrl="_catalogs/masterpage/v4.master" />
   3:   <Configuration ID="0" Name="Default" MasterUrl="_catalogs/masterpage/v4.master">
   4:     <Lists>
   5:       <List FeatureId="00BFEA71-E717-4E80-AA17-D0C71B360101" Type="101" Title="$Resources:core,shareddocuments_Title;" Url="$Resources:core,shareddocuments_Folder;" QuickLaunchUrl="$Resources:core,shareddocuments_Folder;/Forms/AllItems.aspx" />
   6:         ...
   7:     </Lists>
   8:     <Modules>
   9:       <Module Name="Default" />
  10:     </Modules>
  11:     <SiteFeatures>
  12:       <!-- BasicWebParts Feature -->
  13:       <Feature ID="00BFEA71-1C5E-4A24-B310-BA51C3EB7A57" />
  14:     </SiteFeatures>
  15:     <WebFeatures>
  16:       <!-- TeamCollab Feature -->
  17:     </WebFeatures>
  18:   </Configuration>
  19:   <Configuration ID="1" Name="Blank" MasterUrl="_catalogs/masterpage/v4.master">
  20:     ...
Saludos!!
Posted: 16/2/2012 15:08 por Luis Mañez | con no comments
Archivado en:
Más artículos Página siguiente >