April 2012 - Artículos
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:

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”

Y desmarcamos la opción: “Usar conversaciones”
Saludos!!
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.

Disponemos de varias opciones a la hora de compartir el documento:
- Podemos enviarlo por correo electrónico:

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

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:

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:

Y aparece publicado en mi muro:

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

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!!
Supongamos que tenemos nuestra web pública, creada con Office 365. Sería algo así:

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.

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

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

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)

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.

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!!
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!
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:

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:


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:

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:
- Blog del CIIN: http://geeks.ms/blogs/ciin/archive/2011/10/22/sharepoint-2010-controles-delegados-i.aspx
- 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.

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:

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:

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

Espero que os sirva.
Un saludo!!
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í:

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:


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:

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.

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.

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:

Si tenemos una solución con mucho desarrollo personalizado, seguro que agradecemos este orden.
Espero que os sirva.
Saludos!!
30