Microsoft.SharePoint.Utilities: el namespace que vale su peso en oro (1)
15.12.10 / Comments (0) / by Unknown
Quien más quien menos conoce el cajón de sastre llamado SPUtility y sus métodos miscelánicos. Ahora os propondré un viaje en distintos capítulos por algunas otras clases de indiscutible utilidad. Hoy para empezar:
SPHttpUtility o cómo olvidarse para siempre de string.Replace
La intención de esta clase estática es proveer de métodos también estáticos para la codificación y decodificación de strings durante el procesamiento de peticiones web. Lo más interesante es:
string ConvertSimpleHtmlToText(string html, int maxLength)
Convierte una cadena html (por ejemplo, de un campo de rich text o un PublishingContent) a texto plano, eliminado los tags HTML. ¿A que te estás dando de cabezazos?
string HtmlEncode(string valueToEncode)
Codifica una cadena de texto para ser incluída en markup HTML, es decir, reemplaza " / ' / < / > / & por " / ' / < / > / & . Opcionalmente tenemos también el HttpUtility.HtmlEncode . A ver, que el Regex que implementaste está muy bien pero...
string HtmlDecode(string valueToDecode, bool decodeNbsp)
El correspondiente método de decodificación. "decodeNbsp" a true para si deseamos decodificar también los a espacios.
string HtmlEncodeAllowSimpleTextFormatting(string valueToEncode)
Codifica una cadena para aparecer entre merkup HTML pero además sustituye los espacios y saltos de línea por y <br/> (eso sí, codificados a &nbsp; y <br>).
string UrlKeyValueEncode(string keyOrValueToEncode)
Codifica una clave o valor de una querystring para construir una URL, es decir, escapa los caracteres no admitidos por un querystring. El HttpUtility.UrlEncode de toda la vida.
string UrlKeyValueDecode(string keyOrValueToDecode)
Decodifica una clave o valor de querystring.
string EcmaScriptStringLiteralEncode(string scriptLiteralToEncode)
Veamos, ésta no es de utilidad inmediata pero en algunas funcionalidades de SP, hay que transferir strings a traves de JavaScript (ECMAScript), para lo cual algunos caracteres necesitan ser codificados a formato Unicode (\u00XX). Este método proporciona dicha codificación.
POSTEADO EN: Modelo de objetos, SharePoint 2007, SharePoint 2010, Utilidades Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
SharePoint 2007: Reemplazar master page en páginas de aplicación
10.12.10 / Comments (0) / by Unknown
La application.master que viene de serie en las páginas del directorio _layouts es una cruz que nos tortura constantemente a los desarrolladores de SharePoint. Es única por servidor, no está soportado el modificarla y, para colmo, las páginas de aplicación que la usan son múltiples y habituales (newsbweb.aspx, createpage.aspx, mysubs.aspx,...). Con lo cual, es frecuente el requerimiento de que estas páginas dispongan de un look&feel como mínimo parecido al del resto de páginas del sitio (ya sean páginas de publicación o páginas de formulario -DispForm.aspx, EditForm.aspx,...-, a las que no hay problema para asignarles una master page). Y con toda la razón del mundo, porque el aspecto de esas páginas canta como una almeja.
A riesgo de meter la pata en el hoyo de lo "not supported", voy a proponer un mecanismo, a mi juicio bastante limpio, para reemplazar la master page en tiempo de ejecución para esas páginas. Está comprobado con muchas de las páginas de aplicación, aunque no garantiza su efectividad en el 100% de ellas. Y no, no hay ningún HttpModule de por medio.
Si implementamos un page adapter para estas páginas de layout, podemos tener control de sus propiedades en runtime. Ahora sólo quedaría modificar la propiedad MasterPage, el pequeño inconveniente es que sólo puede modificarse antes o durante del método OnPreInit() y que ese método no existe en un control adapter. Bueno, un vistazo al ciclo de vida de los controles ASP.NET, y veremos que existe un evento DeterminePostBackMode() invocado justo antes de OnPreInit. Este evento procesa los datos enviados por postback a la petición actual, estableciendo el valor IsPostBack y devolviendo la colección de valores recibidos. Sí, sí, muy bien. Pero de lo mío, ¿qué? Bien, pues si el page adapter sobreescribe este evento, llama al base (importante no olvidarlo) y luego modifica la propiedad MasterPageFile, bingo! Tenemos una página de aplicación con la master page deseada.
/// <summary>
/// Adapter for SharePoint layout pages to replace their masterpage
/// </summary>
public class CustomLayoutPageAdapter : PageAdapter
{
public override System.Collections.Specialized.NameValueCollection
DeterminePostBackMode()
{
NameValueCollection result = base.DeterminePostBackMode();
try
{
Page page = this.Control as Page;
page.MasterPageFile = "/_catalogs/masterpage/XXXXXX.master";
}
catch { }
return result;
}
}
Ahora sólo queda utilizar este page adapter, creando un fichero my.compat.browser en App_Browsers con una definición <adapter> para cada página de aplicación que queramos reemplazar. ¿Engorroso? Depende, esto nos asegura que estaremos reemplazando la master page sólo en las páginas que queremos y no a lo loco, en todo el back-office de SharePoint. Ejemplo:
<adapter controlType="Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage,
Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral,
PublicKeyToken=71e9bce111e9429c" adapterType="MyNamespace.CustomLayoutPageAdapter,
MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXX" />
¿Cómo obtengo el tipo correspondiente a una página de aplicación? Normalmente se ve fácil consultando el código fuente de la página y identificando su clase codebehind. Aquí van una cuantas páginas típicas y sus tipos:
createpage.aspx
Microsoft.SharePoint.Publishing.Internal.CodeBehind.CreatePagePage, Microsoft.SharePoint.Publishing, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
mysubs.aspx
Microsoft.SharePoint.ApplicationPages.MySubsPage, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
sitesubs.aspx
Microsoft.SharePoint.ApplicationPages.SiteSubsPage, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
newsbweb.aspx
Microsoft.SharePoint.ApplicationPages.SubNewPage, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
checkin.aspx
Microsoft.SharePoint.ApplicationPages.CheckIn, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
userdisp.aspx
Microsoft.SharePoint.ApplicationPages.UserDisplayPage, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
regionalsetng.aspx
Microsoft.SharePoint.ApplicationPages.RegionalSettingsPage, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
subchoos.aspx
Microsoft.SharePoint.ApplicationPages.SubChoosPage, Microsoft.SharePoint.ApplicationPages, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
Pero esto no es todo. Es muy importante notar que, si reemplazamos una application.master por una master page nuestra, es probable que las páginas de aplicación a las que hemos lobotomizado empiecen a echar en falta placeholders y controles, con la consecuente eclosión de fuegos artificiales diversos. Solución: localizar cuáles son esos placeholders y añadirlos a nuestra masterpage. Esto no es ciencia exacta: debemos testear cada página a la cual estamos aplicando este fix y asegurarnos que funciona correctamente. Dejadme solo apuntar que para la mayoría de páginas de aplicación, el PlaceHolderFormDigest es necesario.
<asp:ContentPlaceHolder id="PlaceHolderFormDigest" runat="server">
<SharePoint:FormDigest ID="FormDigest1" runat=server/>
</asp:ContentPlaceHolder>
Y nada más, si alguien aplica este método y quiere dar feedback sobre él, soy todo oídos.
POSTEADO EN: Application Pages, Fixes, Masterpages, SharePoint 2007 Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
Mis blogs de cabecera
30.11.10 / Comments (2) / by Unknown
- blog de Ángel Suarez, de Ángel Suárez "Guisu", el "outsider" de las tecnologías punteras, los frameworks sociales y los meollos con tramitación electrónica. Altamente recomendable para amantes de la cecina.
- CRM a diario, de Daniel Sabater, eminencia de Microsoft Dynamics capaz de convertir CRM en todo aquello que siempre soñaste y nunca te atreviste a pedir.
- SharendiPointy y El blog de David Martos, de David Martos, el "capo" tecnológico de todo aquello que tiene que ver con Microsoft, betas, lanzamientos y retos imposibles. Cuando os parezca que pisáis territorio virgen, entrad en su blog y comprobaréis que David ya estuvo allí.
- El blog de Jordi Ruiz, de Jordi Ruiz, el único "jedi" con midiclorianos de Resharper en su cuerpo y cuyo esqueleto está formado con patrones de diseño en lugar de huesos.
- elblogdeluru y Amigo mío Siempre estas Programando en .NET, del omnipresente Luis Ruiz Pavón, cuya fama le precede; no hay tecnología que se resista a su virtuosismo: ASP.NET, VSTO, SharePoint, EntLib.... y el único combustible que necesita son cañas y tapas.
- Ignasi Tebé SharePoint Blog, de Ignasi Tebé, implacable exprimidor de posibilidades para SharePoint, producto que muy pronto ofrecerá un nuevo esquema de pricing basado en tres licencias: Standard, Enterprise y Tebé.
- Madeinmind, de Maria Bellmunt, la diosa del "branding" y de los retos de diseño. "Imposible" y "nunca" no están en su diccionario. En su lugar, encontraréis "flor" y "nube".
- Maximo Castagno, de Maximo Castagno, nuestro catedrático en user experience, cuyas reflexiones sobre usabilidad son firmes pasos hacia la victoria sobre el caos en las UI, la sinrazón funcional... en definitiva, todo lo que habita en el cerebro de los desarrolladores.
Y, aunque lejos, sigue cerca nuestro:
- Developing is painful, de José Manuel Sánchez "Er Chan", talento fuera de serie que lleva el desarrollo y la integración con tecnologías Microsoft en las mismas venas, además de maestro en el uso del estilo tachado de la ironía.
Espero no dejarme ninguno y poder editar la entrada pronto para añadir más. Y yo creo que por hoy, como dijo aquél, ya está bien de... en fin, de eso.
POSTEADO EN: Links, Off-Topic, Spenta Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
Could not load file or assembly 'Microsoft.SharePoint.ApplicationPages PublicKeyToken=71e9bce111e9429c' o el arte de la colleja bien dada
26.11.10 / Comments (0) / by Unknown
Could not load file or assembly 'Microsoft.SharePoint.ApplicationPages PublicKeyToken=71e9bce111e9429c'
Este error no solo trae de cabeza a mucha gente:
http://social.technet.microsoft.com/Forums/en/sharepointgeneral/thread/e7463fba-1d31-4198-87b8-29cf107906dd
http://blog.dennus.net/2009/06/
http://www.tech-archive.net/Archive/SharePoint/microsoft.public.sharepoint.windowsservices/2008-06/msg00048.html
http://www.solomon-strutz.com/wordpress/?p=83sino
sino que además no dispone de un fix consensuado. Parece que al aparecer este mensaje, SharePoint entra en un estado de encallamiento que le impide resolver correctamente el ensamblado: reciclar el app pool igual ayuda, un iisreset o dos más pueden funcionar, quizá un reboot de la máquina... veis por donde voy, no? SharePoint necesita una colleja, un capón, un meneo; en definitiva, una acción humana que le haga ser capaz de nuevo de encontrar la DLL. Sirva esta entrada para sugerir una más a las anteriores citadas; como mínimo, ha funcionado en un caso donde no habían funcionado recycles e iisresets en solitario.
- Mover el Microsoft.SharePoint.ApplicationPages.dll de _app_bin (del directorio de la aplicación web que está fallando) a otro sitio cualquiera.
- iisreset
- Cargar una página de /_layouts . Aparecerá de un error distinto.
- Volver a poner Microsoft.SharePoint.ApplicationPages.dll en _app_bin
- iisreset
- Cargar de nuevo la página de /_layouts .
Si todo ha funcionado como debería, habréis descolocado a SharePoint con un buen capón de padre y la página debería verse correctamente de nuevo.
POSTEADO EN: Application Pages, Fixes, IIS, SharePoint 2007 Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
Emergencia: no se propagan los perfiles de usuario a la User Information List
24.11.10 / Comments (0) / by Unknown
provocar cierto grado de pánico) un campo de un usuario (el e-mail, por ejemplo) en el contexto de un sitio,
es decir a través de un objeto SPUser, que obtiene la información desde la lista interna de WSS / SharePoint
Foundation "User Information List". El problema es que el origen de ese campo no está en esa lista sino en el
repositorio de perfiles de usuario (User Profiles de MOSS 2007 / SharePoint Server), ya sea importado de un origen de datos, como Directorio Activo, o bien gestionado manualmente desde los perfiles de SSP / User Profile Service Application. Y la sincronización entre perfiles de usuario y "User Information List" es, como ya todos sabemos, muy suya.
Sobre la teoría de cómo funciona la sincronización entre ambos repositorios y cómo forzar la propagación de los campos, existen unos cuantos artículos bastante clarificadores, entre ellos éste de Mirjam van Olst:
http://www.sharepointchick.com/archive/2009/06/17/user-profiles-and-the-user-information-list-or-userinfo-table.aspx
También merecen una ojeada:
http://blogs.technet.com/paulpaa/archive/2009/10/01/user-profile-information-not-updated-on-site-collection-s-people-and-group.aspx
http://www.21apps.com/sharepoint/user-profiles-why-do-my-changes-not-show-in-other-sites/
Pero vamos a ponernos en el caso de que nada de los descrito en ellos funcione. No conseguimos propagar de ninguna manera el valor de los campos a la "User Information List" y los nervios aumentan. Necesitamos una solución de emergencia; encendemos el reflector con la Power-señal, PowerShell lo ve y acude a nuestro rescate.
Primero: abrir consola de PowerShell y cargar las librerías de SharePoint. Reminder para hacerlo:
SharePoint 2007
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
Sharepoint 2010Segundo: manipular manualmente el elemento de la lista "User Information List" mediante object model, usando operaciones que recomiendo os acostumbréis a usar asiduamente por su sencillez e inmediatez.
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
$site = new-object Microsoft.SharePoint.SPSite("http:/{el_sitio}")Donde xx será el ID del elemento (usuario), que podemos consultar en cualquiera de las URL
$web = $site.OpenWeb()
$list = $web.Lists["User Information List"]
$item = $list.GetItemByID(xx)
http://el_sitio/_layouts/people.aspx o http://el_sitio/_catalogs/users/detail.aspx . Si pasamos por encima
del enlace de cada elemento veremos una URL del estilo http://el_sitio/_layouts/userdisp.aspx?ID=xx
$item["EMail"] = "elcorreo@eldominio.com"
$item["JobTitle"] = "cargo"
$item[...] = ...
$item.Update()Con esto, el SPUser dispondrá del campo actualizado inmediatamente. Solucionado; gracias PowerShell. Respecto a la propagación del campo desde perfiles de usuario, tranquilos, en un periodo de 24 horas, tarde o temprano se acabará produciendo automáticamente.
Anexo: entre los campos de un item de tipo usuario tenemos los siguientes:
Internal name - Display name
Title - Name
Name - Account
EMail - Work e-mail
Notes - About me
SipAddress - SIP Address
IsSiteAdmin - Is Site Admin
Deleted - Deleted
Picture - Picture
Department - Department
JobTitle - Title
IsActive - Is Active
FirstName - First name
LastName - Last name
WorkPhone - Work phone
Office - Office
UserName - User name
WebSite - Web site
SPSResponsibility - Responsibilities
ID - ID
POSTEADO EN: Fixes, PowerShell, SharePoint 2007, SharePoint 2010, User Profiles Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
MSDN publica "Real World Branding with SharePoint 2010 Publishing Sites" de Andrew Connell
19.11.10 / Comments (0) / by Unknown
En este caso, un extenso artículo de Connell arremangado y en faena con el branding de sitios de publicación en SharePoint 2010, está recién publicado en MSDN y listo para vuestro deleite. Me encanta que consista en un práctico hands-on-lab que describa hasta el más mínimo detalle cómo customizar un portal para dotarlo de una "real-world interface". Algo que muchos de nosotros llevamos haciendo desde SP 2007 con sangre, sudor y lágrimas; por eso siempre te ilumina el corazoncito ver que Andrew también trastea con el PlaceHolderLeftNavBar y con el SiteMapPath. Grande.
http://msdn.microsoft.com/en-us/library/gg430141.aspx
Dos observaciones extraídas de él:
1) El uso (desconocido hasta ahora para mí) de la clase CSS s4-notdlg , que puede aplicarse a cualquier elemento HTML que deseemos que NO aparezca en los diálogos modales de SP 2010. Se acabó el tener que hacer apaños con clases CSS o plantearse incluso el uso de master pages reducidas.
2) Andrew Connell maqueta (o por lo menos nos propone con su ejemplo maquetar) prototipos HTML enteros de la página. ¿Es esta la mejor opción para afrontar el branding de un sitio? Dejadme empezar el debate y poner en tela de juicio si es necesario construir de entrada un HTML ficticio para elementos de SharePoint como el cuadro de búsqueda, el breadcrumb, la barra de navegación, el Welcome, y un largo etc., cuando luego, al integrarlo en una master page y en un layout real, ese HTML ficticio será reemplazado por el real de SharePoint y probablemente (muy probablemente) habrá que hacer ajustes de alineación, tipografías, márgenes... ¿No sería mejor construir el HTML ya directamente sobre una master page y un layout ya reales, jugar con SharePoint Designer y los controles de servidor reales? Pregunta capciosa donde las haya.
Sea como sea, artículo de cabecera. "Andrewcito de mi vida, tu eres sharepointer como yo..."
POSTEADO EN: Artículos, Branding, MSDN, Publishing, SharePoint 2010 Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
SharePoint, InfoPath y "Network problems are preventing this file from being opened"
16.11.10 / Comments (0) / by Unknown
El detalle del mensaje:
InfoPath cannot create a new, blank form.
InfoPath cannot open the form. to fix this problem, contact your system administrator.
Network problems are preventing this file from being opened. If this problem persists, contact your network administrator.
Bien; existe un elevado porcentaje de probabilidad de que algo de lo siguiente ocurra:
- Forms Services no esté configurado en vuestro entorno: http://technet.microsoft.com/en-us/library/cc262263(office.12).aspx
- Shared Services Provider no esté configurado en vuestro entorno: http://technet.microsoft.com/en-us/library/cc262649(office.12).aspx
- No esté habilitado Session State en vuestro entorno: http://technet.microsoft.com/en-us/library/cc263527(office.12).aspx#section2
POSTEADO EN: Fixes, Forms Services, InfoPath, SharePoint 2007 Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
Error en vti_setuppath al modificar plantillas de sitio en soluciones sandboxed
8.11.10 / Comments (2) / by Unknown
Veamos: en un proyecto cualquiera usamos soluciones sandboxed (WSP's que viven en la Solution Gallery de nuestra colección de sitios: _catalogs/solutions) que contienen una plantilla de web. Estos WSP los obtenemos haciendo "Guardar sitio como plantilla" y constituyen el "código fuente" del sitio. El ciclo es: despliego el WSP, creo un sitio con la plantilla de sitio contenida en el WSP, hago las modificaciones manuales pertinentes y guardo de nuevo el sitio a WSP. Todo esto sin abrir Visual Studio. Maravilloso.
...hasta que llegamos a la novena iteración del ciclo. La solución sandboxed se sube, se activa, procedemos a crear el sitio y ¡crac! rotura fibrilar con el siguiente diagnóstico:
11/05/2010 12:31:38.57 powershell.exe (0x22A8) 0x20B8 SharePoint Foundation General 72lu High Cannot find doc C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\Template\global\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\v4.master 11/05/2010 12:31:38.57 powershell.exe (0x22A8) 0x20B8 SharePoint Foundation General 8yrn Medium Instantiating module "_catalogsmasterpage_global": File could not be added at URL "v4.master": Error 477317568
11/05/2010 12:31:38.57 powershell.exe (0x22A8) 0x20B8 SharePoint Foundation General 8e2s Medium Unknown SPRequest error occurred. More information: 0x80070002
11/05/2010 12:31:38.96 powershell.exe (0x22A8) 0x20B8 SharePoint Foundation Feature Infrastructure 889y High The element of type 'Module' for feature 'XXXXXXXXXModules' (id: 70a2c4f1-8cbf-4e3b-8d52-120e5be61a77) threw an exception during activation: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
Feo, ¿verdad? Error al desplegar el fichero v4.master y el origen parece ser una ruta que contiene todas las contrabarras del universo y más. ¿Alguien ha contado cuántas? 256. ¿Alguno ve la relación cabalística? Novena exportación del sitio; 2 ^ (9 - 1) = 256. ¿Será posible? Afortunadamente guardo las versiones de los WSP anteriores y puedo investigar los cambios. Abro el WSP y localizo en el Elements.xml de la susodicha feature XXXXXXXXXModules un elemento <Module> del estilo:
<Module Name="_catalogsmasterpage_global" HyperlinkBaseUrl="http://xxxxxxxxx/" Url="_catalogs/masterpage" RootWebOnly="FALSE" Path="Files\_catalogs\masterpage">El metadato "MetaInfo" contiene una ristra de pares nombre/valor que se provisionarán en la colección Properties del SPListItem correspodiente al fichero desplegado. Ahí vemos como la propiedad "vti_setuppath", que indica la ruta relativa donde encontrar el fichero físico para un templated document (como parece ser nuestro caso), contiene ese path relativo con las 256 contrabarras. Y comparando con los WSP antiguos se corrobora como, a cada nueva exportación, el número de contrabarras se duplica. Hasta que por fin, irremediablemente, se supera lo que parece ser el tamaño máximo permitido. Pasmante.
<File Url="v4.master" Type="GhostableInLibrary" Path="v4.master">
<Property Name="ID" Value="2" />
<Property Name="ContentTypeId" Value="0x01010500AA46D280A9395F49A0AD56DEF3BFAA2F" />
<Property Name="ContentType" Value="Master Page" />
<Property Name="_ModerationStatus" Value="0" />
<Property Name="FileDirRef" Value="xxxxxxxxxxx" />
<Property Name="FSObjType" Value="0" />
<Property Name="FileLeafRef" Value="v4.master" />
<Property Name="MetaInfo" Value="2;#vti_parserversion:SR|14.0.0.4762
Order:SW|200.000000000000

vti_folderitemcount:IW|0
FSObjType:SW|0
FileDirRef:SW|
MyWork/_catalogs/masterpage
vti_charset:SR|utf-8
vti_author:SR|SHAREPOINT\\system
vti_setuppath:SR|global\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\v4.master

UIVersion:SW|4
MetaInfo:SW|2;#vti_parserversion:SR|14.0.0.4762\r\nvti_folderitemcount:IR|0\r\nvti_charset:SR|utf-8\r\nvti_author:SR|SHAREPOINT\\\\administrator\r\nvti_setuppath:SR|global\\\\v4.master\r\nUIVersion:SR|4\r\nvti_cachedneedsrewrite:BR|false\r\nvti_generator:SR|Microsoft SharePoint\r\nvti_foldersubfolderitemcount:IR|0\r\nvti_modifiedby:SR|SHAREPOINT\\\\administrator\r\nvti_cachedhastheme:BR|false\r\nvti_cached
customprops:VX|vti_title\r\nContentTypeId:SW|0x010105001BB704A689F80A4D8AF430B26FD34F6C
\r\nvti_cachedtitle:SR|<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>\r\nvti_metatags:VR|HTTP-EQUIV=X-UA-Compatible IE=8 GENERATOR Microsoft\\\\ SharePoint progid SharePoint.WebPartPage.Document HTTP-EQUIV=Content-Type text/html;\\\\ charset=utf-8 HTTP-EQUIV=Expires 0\r\nvti_title:SR|<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>\r\nvti_cachedbodystyle:SR|<body scroll="no" onload="if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();" class="v4master">\r\n
vti_cachedneedsrewrite:BR|false
vti_generator:SR|Microsoft SharePoint
vti_foldersubfolderitemcount:IW|0
vti_cachedhastheme:BR|
false
vti_cachedcustomprops:VX|vti_title
vti_modifiedby:SR|
SHAREPOINT\\system
ContentType:SW|Master Page
ContentTypeId:SW|0x01010500AA46D280A9395F49A0AD56DEF3BFAA2F

FileLeafRef:SW|v4.master
vti_cachedtitle:SR|<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>
vti_metatags:VR|HTTP-EQUIV=X-UA-Compatible IE=8 GENERATOR Microsoft\\ SharePoint progid SharePoint.WebPartPage.Document HTTP-EQUIV=Content-Type text/html;\\ charset=utf-8 HTTP-EQUIV=Expires 0
vti_title:SR|<asp:ContentPlaceHolder id="PlaceHolderPageTitle" runat="server"/>
vti_cachedbodystyle:SR|<body scroll="no" onload="if (typeof(_spBodyOnLoadWrapper) != 'undefined') _spBodyOnLoadWrapper();" class="v4master">
" />
<Property Name="Order" Value="200.000000000000" />
<Property Name="UIVersion" Value="4" />
</File>
</Module>
Menuda papeleta. ¿Y ahora qué? Alguien diría: "Eso te pasa por ir a lo fácil; si hubieras trabajado con una plantilla de sitio en Visual Studio tendrías absoluto control sobre ella y no dependerías del proceso de exportación de SharePoint, que salta a la vista que tiene aún algún aspecto por pulir". Desoigo esos "telodijes" e intento buscar una solución que no implique rehacer todo de arriba a abajo.
¿Modificar el WSP? Fácil decirlo pero difícil llevarlo a la práctica. Visual Studio 2010 permite importar los WSP en proyectos. Así hago; el proyecto se importa correctamente y puedo ver el immenso listado de features y artifacts exportados. Pero al compilar:
Error 3 Both "_catalogsmasterpage_global" and "_catalogsmasterpage_global1" contain a file that deploys to the same Package location: XXXXXXXXXX_Feature2\Files\_catalogs\masterpage\v4.master C:\XXXXXXXX\Package\Package.package XXXXXXXXX
Cierto, en el WSP la página maestra v4.master se está provisionando dos veces. ¿Debo extirpar una de ellas? Empezar a meter bisturí en Visual Studio no parece que vaya a ayudarme a solventar el tema sino más bien lo contrario. Empieza a cobrar fuerza la opción de editar directamente el WSP, eliminar todas las contrabarras y volver a generarlo. Abrirlo es fácil, modificar el fichero Elements.xml también pero volver a construir el WSP ya no tanto. Para no eternizar esta entrada, enlazaré al post Cómo modificar y recrear manualmente un WSP en que encontraréis detalles sobre cómo hacerlo.
Resultado: con el WSP modificado se puede volver a activar la solución y crear un sitio. Hurra. Vamos a comprobar ahora si exportando de nuevo el sitio a WSP, SharePoint sigue en sus trece. Efectivamente; volvemos a tener dos contrabarras.
vti_setuppath:SR|global\\v4.master
Es decir, que dentro de otras 9 exportaciones volveremos a estar en las mismas. ¿Existe una forma de evitar esto? ¿Se corregirá en algún Cumulative Update o hotfix? ¿Significa mientras tanto que hay que prescindir de las soluciones sandboxed para sitios que deben modificarse muy a menudo? Preguntas que quedarán sin respuesta por lo menos a día de hoy en esta entrada.
POSTEADO EN: Fixes, Sandboxed solutions, SharePoint 2010, WSP Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
Cómo modificar y recrear manualmente un WSP
8.11.10 / Comments (0) / by Unknown
Contexto: debo modificar un WSP ya creado. Es una modificación muy sencilla, no requiere añadir ni eliminar ficheros, simplemente editar uno de ellos. No tengo DDF, no tengo proyecto de Visual Studio, no puedo dedicar mucho tiempo a ello. Todo ventajas.
Mark Rackley (http://www.sharepointhillbilly.com/archive/2010/02/16/rebuilding-a-.wsp-file-in-4-easy-steps.aspx) acude al rescate y nos ofrece la guía mínima de pasos para "tunear" un WSP con éxito (que complemento con mis humildes aportaciones):
- Renombrar el fichero WSP a CAB (Cabinet file).
- Extraer todo el contenido preservando la estructura de carpetas(utilizando 7Zip, WinRar o el mismo Windows, que permite consultar y extraer de ficheros CAB).
- Modificar los ficheros necesarios del contenido (con extrema precaución si se trata de XML de definición de features, manifests, etc.)
- Obtener el fichero DDF de forma automatizada (aquí la clave de todo este post) mediante la útil herramienta DDFGenerator . Simplemente ejecutar desde línea de comandos y especificar como único parámetro la ruta local donde está descomprimido el contenido de nuestro WSP. Esto generará un "solution.ddf" dentro de esa carpeta.
- Editar el fichero solution.ddf para corregir lo siguiente:
1) En las directivas iniciales .Set incluir:
.Set CabinetNameTemplate=NombreDeNuestraSolucion.wspLa primera línea para hacer que el fichero se genere con el nombre deseado; la segunda para evitar que se genere partido en distintos ficheros.
.Set MaxDiskSize=CDROM
2) Repasar las rutas relativas generadas en el DDF; si alguna de ellas contiene espacios en nombres de fichero o carpeta, debe ser puesta entre comillas (")
- Ejecutar la herramienta makecab.exe (Windows)
makecab.exe /F solution.ddfEt voilà, dentro de una subcarpeta cuyo nombre es un numérico aparecerá el fichero WSP generado con nuestras modificaciones.
Los más aventurados que deseen añadir o eliminar ficheros pueden proceder a manipular el fichero solution.ddf a placer.
POSTEADO EN: SharePoint 2007, SharePoint 2010, WSP Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
Provisionar web parts dentro del contenido de una página de publicación
4.11.10 / Comments (0) / by Unknown
Primero: el webpart se define con un GUID (con el prefijo "g_" y con "_" como separador de bloques de guid), se establece webpart order = 0 y webpart zone id = "wpz". Por ejemplo:
<AllUsersWebPart WebPartZoneID="wpz" WebPartOrder="0" ID="g_e7a3c67e_a141_46cf_9640_cbd9e398a444">
Después: en el HTML del campo PublishingPageContent se define un <div> con el GUID como id. Ese GUID tiene un prefijo (en el caso que he probado es "vid_") y va dentro de otro div que le da un estilo CSS, pero lo mejor para obtener el publishing page content exacto sería incrustando el webpart a mano y consultando el HTML fuente. Saldrá algo parecido a:
<div class="ms-rtestate-read ms-rte-wpbox" contenteditable="false">
<div class="ms-rtestate-notify ms-rtestate-read e7a3c67e-a141-46cf-9640-cbd9e398a444" id="div_e7a3c67e-a141-46cf-9640-cbd9e398a444">
</div>
<div id="vid_e7a3c67e-a141-46cf-9640-cbd9e398a444" style="display: none">
</div>
</div>
POSTEADO EN: Publishing, SharePoint 2010, Web Parts, WSP Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati
TaxonomySession con propiedades vacías en SharePoint 2010
4.11.10 / Comments (0) / by Unknown
- Que el servicio "Managed Metadata Web Service" de "Services on server" se encuentre Started.
- Que el application pool de IIS asociado a este servicio (normalmente el "SharePoint Web Services") y el site de IIS correspondiente esten arrancados.
No está mal la ayudita, ¿eh?
Edición 15/12/2011: Ayer con mi compi Luis Ruiz Pavón descubrimos otra manera de reproducir este error: cuando se ejecutan las llamadas al object model de SharePoint con un usuario que no tiene ningún permiso sobre el Managed Metadata Service Application. Para solucionar esto, debemos ir a "Manage Service Applications", seleccionar el Managed Metadata Service y acceder a "Permissions" en la ribbon. Ahi deberemos dar de alta el usuario y asignarle Full Permissions.
POSTEADO EN: Fixes, SharePoint 2010, Taxonomías Enviar por correo electrónico Escribe un blog Compartir en X Compartir con Facebook
Enviar entrada a: Digg + Del.icio.us + Google Bookmarks + Reddit + Technorati