Social Icons

viernes, 3 de diciembre de 2010

Copiando ListViewWebParts entre diferentes sitios con sus correspondientes vistas personalizadas

Por un segundo he dudado si escribir el resto del post en el título.

En otro ejemplo de lo que ahora he dado en llamar Guerrilla Coding gracias a mis asombrosos conocimientos de la lengua que se habla en la pérfida Albión ahora puedo usar palabras como guerrilla en un par de horas tuve que hacer un programita para copiar cientos de páginas llenas de ListViewWebparts cada uno con su vista personalizada. Yo no sé vosotros, pero yo cada vez que tengo que tocar el ListViewWebpart me pongo a temblar...

Los ListViewWebparts crean en la lista de la que son "hijos" una vista Oculta cuando nosotros personalizamos la vista del webpart. Esto implica que para copiar los webparts a otro sitio tendremos que copiar las vistas en la lista del sitio de destino y apuntar al webpart a la nueva vista, no sé si me explico bien... mejor pondré un trozo de código...

Aquí lo que hago es copiar los webparts de cada fichero de origen al de destino, y les doy un tratamiento especial si son ListViewWebpart para esta aplicación es suficiente.

private static void CopyWebParts(SPFile origFile, SPFile destFile)
        {
            SPLimitedWebPartManager origWpm = origFile.GetLimitedWebPartManager(PersonalizationScope.Shared);
            SPLimitedWebPartManager destWpm = destFile.GetLimitedWebPartManager(PersonalizationScope.Shared);

            DeleteWebparts(destWpm);

            foreach (Microsoft.SharePoint.WebPartPages.WebPart webpart in origWpm.WebParts)
            {
                Microsoft.SharePoint.WebPartPages.WebPart newWp;

                if (webpart is ListViewWebPart)
                    newWp = UpdateListViewWebPart(webpart as ListViewWebPart, origFile.GetWeb(), destFile.GetWeb());
                else
                    newWp = webpart;

                destWpm.AddWebPart(newWp, Common.ConvertToString(newWp.ZoneID), newWp.ZoneIndex);
            }

            try
            {
                destFile.Publish("Added Web Parts");
                destFile.Approve("Web Part additions approved");
            }
            catch { }
        }

        private static ListViewWebPart UpdateListViewWebPart(ListViewWebPart webpart, SPWeb origWeb, SPWeb destWeb)
        {
            ListViewWebPart newWebPart = webpart; //yeah I know.

            string oldListName = webpart.ListName;
            string oldViewGuid = webpart.ViewGuid;

            SPList OrigList = origWeb.Lists.GetList(new Guid(oldListName), true);
            
            SPList DestList = destWeb.Lists[OrigList.Title];

            SPView OrigView = OrigList.GetView(new Guid(oldViewGuid));
            SPView DestView = DestList.Views.Add(string.Empty, OrigView.ViewFields.ToStringCollection(), OrigView.Query,
                OrigView.RowLimit, OrigView.Paged, OrigView.DefaultView);
            DestView.Hidden = OrigView.Hidden;
            DestView.Scope = OrigView.Scope;
            DestView.ApplyStyle(destWeb.ViewStyles.StyleByID(Convert.ToInt32(OrigView.StyleID)));

            DestView.Update();

            newWebPart.ViewGuid = DestView.ID.ToString("B").ToUpper();
            newWebPart.ListName = destWeb.Lists[OrigList.Title].ID.ToString("B").ToUpper();


            return newWebPart;
        }
Y, contra todo pronóstico, funcionó... Espero no tener que tocar estos webparts otra vez en mucho tiempo.
Publicar un comentario

lunes, 22 de noviembre de 2010

Code Snippets en C# y ¿Por qué mi binding TwoWay no funciona?

Bien, respecto al problema de los bindings TwoWays, hoy he aprendido que no funcionan por arte de magia, si no que cada propiedad tiene que implementar la notificación de cambio de propiedad... vamos lo que viene a ser la INotifyPropertyChanged. No es muy complicado, pero se tarda un poco más que en declarar la propiedad con notificación, por cierto viene todo bien explicado aquí, y esto nos lleva al tema de los Code Snippets.

Lo de crear Code Snippets (Fragentos de Código) es una de esas cosas que siempre he dejado para aprender más tarde y al final nunca he aprendido... hasta hoy, que tenía que hacer un objeto con más de treinta propiedades que lanzasen el PropertyChanged y no he podido retrasarlo más.

Para aumentar mi productividad he perdido un poco el tiempo y me he creado un Code Snipplet para las propiedades que implementan el INotifyPropertyChanged, lo he llamado propNot en otro alarde de originalidad sin precedentes.
Para ello, en Visual Studio me fui a Tools y desde allí al Code Snippets Manager. Una vez allí seleccioné C# y luego copié habilmente la dirección de la carpeta de los Code Snippets de usuario (My Code Snippets).


Me situé en esa carpeta, creé un fichero .snippet y escribí esto:
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
  <Header>
   <Title>propNot</Title>
   <Shortcut>propNot</Shortcut>
   <Description>Code snippet for properties with NotifyPropertyChanged</Description>
   <Author>Chan</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>
  <Snippet>
   <Declarations>
    <Literal>
     <ID>privName</ID>
     <Default>privName</Default>
     <ToolTip>Private name of the property</ToolTip>
    </Literal>
    <Literal>
     <ID>pubName</ID>
     <Default>pubName</Default>
     <ToolTip>Public name of the property</ToolTip>
    </Literal>
    <Literal>
     <ID>type</ID>
     <Default>string</Default>
     <ToolTip>Type of the property</ToolTip>
    </Literal>
   </Declarations>
   <Code Language="csharp"><![CDATA[private $type$ $privName$;
        
    public $type$ $pubName$
    {
     get { return $privName$; }

     set
     {
      $privName$ = value;
      // Call NotifyPropertyChanged when the property is updated
      NotifyPropertyChanged("$pubName$");
     }
    }]]>
   </Code>
  </Snippet>
 </CodeSnippet>
</CodeSnippets>

Probado y funcionando, tanto el binding TwoWay como los Code Snippets. Ahora que sé cómo se hace lo voy a hacer muy a menudo. --EDITO-- Mentí, no los hago a menudo porque soy MUY flojo, pero sí que uso mucho este otro snippet:
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
 <CodeSnippet Format="1.0.0">
  <Header>
   <Title>INotify region with the necessary methods to implement the interface</Title>
   <Shortcut>inotifyregion</Shortcut>
   <Description>Creates region with the necessary methods to implement the interface INotifyPropertyChanged</Description>
   <Author>Jose Sanchez</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>
  <Snippet>
   <Declarations />
   <Code Language="csharp"><![CDATA[#region INotifyMethods
        // Declare the event
        public event PropertyChangedEventHandler PropertyChanged;

        // Create the OnPropertyChanged method to raise the event
        protected void NotifyPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
        #endregion]]>
   </Code>
  </Snippet>
 </CodeSnippet>
</CodeSnippets>
Publicar un comentario

martes, 9 de noviembre de 2010

Cambiando el NewValue en el PropertyChangedCallback

Normalmente no escribo sobre Silverlight, básicamente es por dos razones, la primera es que todo viene perfectamente explicado en un montón de blogs justo al contrario que SharePoint y la segunda es porque tampoco trabajo tanto con Silverlight como para encontrarme problemas. Era perfecto hasta que lo conocí, como tantas otras cosas...


Últimamente estoy teniendo que usar bastante esta tecnología casi nueva para mí y ya desfasada para Microsoft y se me plantean dudas, como por ejemplo la de hoy.

Estaba creando un botón para añadirlo a una DataGrid como DataGridTemplateColumn y necesitaba crearme una DependencyProperty para poder hacer el Binding, hasta aquí todo más o menos claro, pero en el último momento cuando ya me veía victorioso me surgió una duda... si la propiedad (una URL en este caso) no cumple con los requisitos que yo quiero ¿Cómo hago para modificar el NewValue en el mismo PropertyChangedCallback?

El truco está en llamar a SetValue, que no dispara el evento, porque si no obviamente crearíamos un bucle infinito. Algo así.
public string CommentsURL
{
    get { return (string)GetValue(CommentsURLProperty); }
    set { SetValue(CommentsURLProperty, value); }
}

public static readonly DependencyProperty CommentsURLProperty =
    DependencyProperty.Register("CommentsURL", typeof(string), typeof(ButtonComments),
    new PropertyMetadata(new PropertyChangedCallback(ChangedURL)));

private static void ChangedURL(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    try
    {
        string url = e.NewValue.ToString().Split(',')[0];
        new Uri(url);
        d.SetValue(e.Property, url);

        (d as ButtonComments).IsEnabled = true;
    }
    catch
    {
        (d as ButtonComments).IsEnabled = false;
    }
}
Nótese la sutileza del código siempre intentando evitar una excepción antes de que se produzca.


Al final, por si alguien siente curiosidad, el webpart ha quedado así:


"Los intelectuales arreglan los problemas, los genios los evitan."
Publicar un comentario

martes, 26 de octubre de 2010

SharePoint y RPM de New Relic

Acabo de instalar en uno de mis servers de demo una copia del RPM de New Relic para ver cómo se comportaba con SharePoint y qué es lo que hacía.

Increiblemente se ha instalado sin ningún problema y ha empezado a funcionar cosa poco común cuando tratamos de SharePoint.

Tras instalarlo, la versión gratis por supuesto, y registrarlo me dieron una licencia gold 8 días para que probase el producto en toda su plenitud por lo que a los pocos minutos de desplegar en mi servidor ya tenía disponibles un buen montón de estadísticas y gráficas que me confirmaban otra vez que mis web services son lentos y que los tiempos de respuesta de MOSS recién despertado de un IISRESET no son los mejores del mundo.


Me han gustado bastante las gráficas relativas al rendimiento del sistema. Nunca antes fue tan sencillo para un empleado demostrar que el server es lento y que hay que ampliarlo y en qué parte, bien sea el SQL, la RAM o la CPU se les ha olvidado el disco duro.


Para los que duden en probarlo les puedo asegurar que (en mi entorno) tanto SharePoint, como los web services, como los reporting services como todo lo demás están funcionando perfectamente, o por lo menos tan bien como antes acabo de encontrar, gracias al RPM un error en un report, ya voy a estar dándole la vara al de BI.

En fin, que como lo mío es quejarme y esta vez no he podido no comento más de este producto, que además no me pagan.


Con los servidores públicos tan gordotes que he tenido bajo mi bota y ahora tengo que hacer click muy rápido para hacer como si hubiese tráfico...

Menos pelo, menos poder, de toda la vida.
Publicar un comentario

viernes, 17 de septiembre de 2010

Lambdas, Method Extensions y RunWithElevatedPrivileges

A estas alturas ya no es un problema para nadie abrir un sitio como administrador independientemente del usuario que este logueado, sin embargo, quiero proponer una función que me parece bastante útil.
/// 
        /// Returns a NEW site with full permissions
        /// 
        public static SPSite OpenSiteWithElevatedPrivileges(this SPSite site)
        {
            SPSite newSite = null;

            SPSecurity.RunWithElevatedPrivileges(() => newSite = new SPSite(site.ID));

            return newSite;
        }
Resulta cómodo, ¿no? A mí me gusta hacer
SPSite site = SPContext.Current.Site.OpenSiteWithElevatedPrivileges();
¿Qué opináis?
Publicar un comentario

miércoles, 15 de septiembre de 2010

Microsoft Charts Controls y MOSS2007

Hacía ya bastante tiempo que sabía de la existencia de estos controles, pero nunca se me había planteado la necesidad de usarlos. Las dos veces que he tenido que hacer graficas las he creado a mano poniendo puntos en un bmp (que es lo más simple)
Sin embargo ahora en Manigent tenemos que hacer un montón de gráficas complejas… pensé en usar Excel Services, pero no tenía sentido mandar datos del modelo de objetos a un libro de Excel y crear la gráfica desde ahí por lo que al final me decidí por usar los controles de .Net

Para ello seguí los pasos de este blog para instalar todo lo necesario en el entorno de desarrollo:
Por supuesto, no leí las instrucciones si no que directamente me puse a crear un webpart.
Lo primero que hice fue referenciar la librería System.Web.DataVisualization que estaba instalada en C:\Program Files\Microsoft Chart Controls\Assemblies\

Y con eso ya puedes crear el webpart en visual studio. El código que usé era una adaptación de un ejemplo que venía en las demos de la documentación:
public class ControlAssessmentChart : Microsoft.SharePoint.WebPartPages.WebPart
    {
        Chart Chart1 = new Chart();

        protected override void CreateChildControls()
        {
            Chart1.Width = 400;
            Chart1.Height = 300;
            Chart1.RenderType = RenderType.ImageTag;

            Chart1.Palette = ChartColorPalette.BrightPastel;
            Title t = new Title("StratEx Testing Chart", Docking.Top,
                new System.Drawing.Font("Trebuchet MS", 14, System.Drawing.FontStyle.Bold)
                , System.Drawing.Color.FromArgb(26, 59, 105));
            Chart1.Titles.Add(t);
            Chart1.ChartAreas.Add("Test 1");

            // create a couple of Test
            Chart1.Series.Add("Test 1");
            Chart1.Series.Add("Test 2");

            //ChartType can also be added to the series
            // add points to Test 1
            Chart1.Series["Test 1"].Points.AddY(5);
            Chart1.Series["Test 1"].Points.AddY(8);
            Chart1.Series["Test 1"].Points.AddY(12);
            Chart1.Series["Test 1"].Points.AddY(6);
            Chart1.Series["Test 1"].Points.AddY(9);
            Chart1.Series["Test 1"].Points.AddY(4);

            // add points to Test 2
            Chart1.Series["Test 2"].Points.AddY(2);
            Chart1.Series["Test 2"].Points.AddY(6);
            Chart1.Series["Test 2"].Points.AddY(18);
            Chart1.Series["Test 2"].Points.AddY(16);
            Chart1.Series["Test 2"].Points.AddY(21);
            Chart1.Series["Test 2"].Points.AddY(14);

            Chart1.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
            Chart1.BorderColor = System.Drawing.Color.FromArgb(26, 59, 105);
            Chart1.BorderlineDashStyle = ChartDashStyle.Solid;
            Chart1.BorderWidth = 2;

            Chart1.Legends.Add("Legend1");

            Chart1.Legends["Legend1"].Enabled = true;

            Controls.Add(Chart1);
        }
    }
Tras crear el webpart, intenté ejecutarlo en sharepoint y recibí el error:

[HttpException (0x80004005): Error executing child request for ChartImg.axd.]

Para solucionarlo seguí el consejo de este foro y añadí la línea:
<add path="ChartImg.axd" verb="GET,HEAD" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
En el web.config (dentro de <system.web><httpHandlers>)
Acto seguido volví a intentar ver el webpart, pero me encontré con que:

[DirectoryNotFoundException: Invalid temp directory in chart handler configuration [c:\TempImageFiles\].]

Para solucionar este tuve que hacer caso a este post y añadir:
<add key="ChartImageHandler" value="storage=file;timeout=20;" />
En el web.config dentro de <appSettings>

Finalmente lo conseguimos.
RadarStackedBarStackedColumn
Estas gráficas corresponden a un mismo set de datos (diferente al del ejemplo) solo cambiando el parámetro ChartType de las series.

Parece potente, a ver como rinde en producción…
Publicar un comentario

martes, 14 de septiembre de 2010

Vuelvo a la carga

Ya hace un montón de meses que no escribo en el blog. Dado el abultadísimo número de visitas de este blog me atrevo a decir sin equivocarme que si estás leyendo esto ya sabes que es porque me he mudado a Londres. El cambio ha sido grande pero, aprovechando que he sobrevivido, he decidido volver a retomar el blog, no ya con fuerzas renovadas si no, más bien, con las pocas fuerzas que me quedan.

Por cierto, lo del número de visitas lo digo con cariño porque tener una audiencia como la que tengo me permite en cada post que escribo poder recordar las caras de las personas que lo van a leer y sentirme un poco entre amigos por muy lejos que esté.

En otro orden de cosas, como sigo siendo un visionario, pero según la primera definición de la RAE, he decidido hacer un blog gemelo en inglés. Mi idea es comparar la repercusión de los posts en los dos idiomas por un lado, y por otro practicar traduciendo mis pensamientos al inglés… A ver como traduzco lo de “visionario”. No vayais al otro blog buscando una traducción del chiste porque no lo voy a traducir…


El nuevo blog está aquí: Developing is Painful in English Too. Como podéis deducir del nombre del blog, el cambio de país no ha empañado ni un ápice mi optimismo. De hecho, Londres se me parece tanto a España que ya no me van quedando dudas de que el problema soy yo.

En el ámbito tecnológico sigo un paso por detrás y estoy trabajando a tope con MOSS 2007, lo que me vendrá muy bien para no tener que crear un nuevo tag en el blog para SharePoint 2010.

Y ahora me voy al blog inglés a crear allí una entrada de presentación no sin antes deciros:


Bienvenidos todos de nuevo a Developing is Painful.
Publicar un comentario

lunes, 22 de febrero de 2010

Búsqueda por propiedades administradas desde parámetros en la URL

Para hacer mi nube de tags mi objetivo primario era trabajar lo menos posible aprovechar al máximo las posibilidades que nos brinda MOSS y para lograrlo, en tema de búsquedas, es primordial encontrar la forma de pasarle tu consulta a la página de resultados de búsqueda en la URL.


Al principio me desanimé bastante porque yo quería usar una clave al estilo k= o s= para las propiedades administradas, pero como seguramente habrás notado no la hay.


Por cierto aprovecho para enumerar los parámetros que conozco y así no se me olvidan:



  • k: Es la consulta en texto libre que mandamos al motor,


    • /Results.aspx?k=Hola

  • s: Es el ámbito en el que vamos a buscar nuestra consulta,


    • /Results.aspx?k=Hola&s=Todos%20los%20sitios

  • v: Orden de resultados,


    • Results.aspx?k=Hola&s=Todos%20los%20sitios&v=date (o también relevance)

  • start: Número del primer elemento que se mostrará en los resultados (útil para paginar),


    • /Results.aspx?k=Hola&s=Todos%20los%20sitios&&v=relevance&start=21

Con esto ya tenemos para ir tirando, pero no me servía de nada para mi nube de tags. ¿Qué podía hacer? pues le pregunté a mi compañero Igor, que está haciendo un proyecto de búsquedas facetadas. Inmediatamente me dio la solución.


Para buscar por propiedades administradas tan solo tenemos que hacer la consulta de este modo:


k=PropiedadAdministrada:Valor


Qué fácil va a ser ahora apuntar las consultas mediante links aprovechando el motor de búsquedas de MOSS y qué poco trabajo me costó preguntar.

Publicar un comentario

miércoles, 17 de febrero de 2010

Errores en el rastreo de sitios de SharePoint

Este post va a ser cortito, a ver si me da tiempo a escribirlo antes de que termine el rastreo :)

De la misma forma que MOSS devuelve cabeceras extrañas a veces cuando intentamos abrir con el SharePoint Designer un sitio al que hemos personalizado profundamente el fichero web.config hoy me ha pasado que al intentar hacer un rastreo completo de uno de los sitios en los que trabajo SharePoint se me ha revelado y en el registro de rastreo, tras la URL de mi sitio me daba el siguiente error:

Se recibió un estado HTTP no reconocido. Compruebe si se puede tener acceso a la dirección URL con Internet Explorer. (HttpStatusCode Found The request failed with the error message: -- <html><head><title>Object moved</title></head><body> <h2>Object moved to <a href=/_layouts/3082/error.aspx?ErrorText=Failed%20to%20Execute%20URL%2E">http://<maquina>/_layouts/3082/error.aspx?ErrorText=Failed%20to%20Execute%20URL%2E>here</a>.</h2> </body></html> –.)

Como me ha sonado a error del designer y no tenía ganas de ponerme a buscar qué era lo que estaba provocando el error pues he hecho el procedimiento estandar en estos casos, que es extender la aplicación web a otro puerto y copiarle el web.config de la aplicación web de administración.

¿Feo? puede ser, ¿Efectivo? eso seguro.

Publicar un comentario

jueves, 11 de febrero de 2010

Mantenimiento de página de elemento Web o Web Part Page Maintenance

Ya se que todo esto ha salido en mil blogs y que cada vez que ha salido ha sido replicado a su vez en mil foros 1000x1000 que gracias a mi pasarán a ser 1000x1000 + 1x0, pero el caso es que a mi se me sigue olvidando y para no volver a perder ni un segundo más en encontrarlo lo posteo. Además estoy seguro de que a más de uno también le pasa.

Se trata de una página que proporciona SharePoint y que sirve para enumerar los webparts que hay ejecutándose en una página, tanto los que se ven como los que cerraste en lugar de eliminarlos y se te quedaron ahí ad eternum.

Esto sirve muy bien si eres un manazas y agregas un webpart que cuelga la página o bien que hace que sea imposible la edición y no puedes borrarlo por el método tradicional de Edición –> Eliminar.

Gracias a esta página y sin olvidarnos de pulsar antes el botón desproteger, nos será muy facil librarnos de esos webparts que nadie puede ver, pero que nosotros sabemos que están ahí o bien de esos otros que son tan visibles que ocultan al resto.

Mantenimiento de página de elementos Web

Y ahora viene el motivo del post y de varios minutos perdidos tontamente por internet.

¿Cómo llegamos a esta página? Pues es muy simple, a la URL de nuestra página que está dando el error o bien que queremos auditar le añadimos ?contents=1

?contents=1

Es muy simple, pero como tampoco es una cosa que haga todos los días pues siempre se me olvida.

Y ya para rematar el post, no me puedo resistir…

¡Los suspiros son aire y van al aire!
¡Las lágrimas son agua y van al mar!
Dime, blogger, cuando un webpart se cierra
¿sabes tú adónde va?

Pues a la página de mantenimiento de webparts, Gustavo que eres muy antiguo.

Publicar un comentario

miércoles, 20 de enero de 2010

Spenta en FITUR 2010

Compartiendo stand con Lionbridge hemos estado (y seguiremos también mañana) mostrando nuestra solución CSP for Tourism y las integraciones que hacemos entre los portales de SharePoint y Freeway que permiten la publicación de contenidos en varios idiomas de forma completamente transparente para el administrador del portal.

Además nos hemos llevado la Surface, con una pequeña mejora que permite identificar el idioma preferido del usuario y mostrar el interfaz "localizado".

Todo multilenguaje, todo turístico, todo dinámico y yo el de siempre... Vaya pinta de vender lavadoras

Si tenéis un rato libre pasaos por allí y Marco os hará un par de demos o tres, y si no podéis aquí os dejo un par de links, aunque con los links no podreis jugar con la Surface :)

Saludos.
Publicar un comentario

lunes, 18 de enero de 2010

Viajando en el tiempo con una nube de tags

Vaya tela, escribo este post para tapar un poco el de antes y me sale este título, no tengo remedio, soy un impresentable.

Bueno, a lo que vamos. Estamos haciendo unos desarrollos para hacer de MOSS un facebook ¿ahora que ya está aquí SP2010? sí ahora.Y entre otras cosas como comentarios a las publicaciones y valoraciones se nos requería una nube de tags.

Delante de un Croissant a la plancha nos planteamos la estrategia para realizar semejante proeza sin par y se nos ocurrió que para llevar el conteo de ocurrencias de cada tag en la web íbamos a tener una lista en el sitio raíz y allí actualizaríamos cada vez que alguien hiciese checkin del elemento. En nuestro caso nos venía de perlas suscribirnos al evento ItemCheckedIn porque lo que necesitamos categorizar taggear pa ti y pa mi son páginas de publicación, pero ¿Cómo puedo actualizar los valores de la lista de tags? Si simplemente sumo uno a la lista de tags y no borro el antiguo no tendré una lista consistente… Necesitamos saber cuál había marcado justo antes del checkin.

Pues nos creamos un método extensor basado en las versiones anteriores del elemento y podremos conocerlo sin problemas.

public static string PreviousValueInHystory(this SPListItem item, string fieldName)
{
Object obj = null;

if (item.Versions.Count > 0)
obj = item.Versions[0][fieldName];

if (obj == null)
return string.Empty;
else
return string.IsNullOrEmpty(obj.ToString()) ? string.Empty : obj.ToString();
}

Por cierto, si os suscribís al ItemCheckedIn tendreis que cambiar el Versions[0] por Versions[1] porque el cero será el que acabáis de crear en el mismo momento de llamar al método.

Publicar un comentario

Training Ignite de SharePoint 2010… Yo también estuve allí

Y fue del 16 al 18 de diciembre y todavía no lo he puesto… La culpa la tiene Luis que no me ha pasado las fotos hasta hace unos días.

En realidad he estado tentado de no publicar nada ya porque me daba vergüenza después de tanto tiempo, pero como nunca he tenido demasiada...

El caso es que yo cuando empecé a programar con SharePoint leyendo blogs a como un loco, sin enterarme de la mitad de las cosas en mi cuarto de Dos Hermanas (Sevilla) jamás,pero jamás del verbo NUNCA, se me pasó por la cabeza que alguna vez pudiese yo conocer en persona a Gustavo Vélez. ¿Marcará esto el fin de una etapa en mi vida?

Gustavo fue mi maestro en SPS2003 y en MOSS2007 de forma remota y ahora lo ha sido de forma presencial de SharePoint 2010.

Bueno, a medias con Juan Carlos González que también me estuvo mentoreando presencialmente en SP2010, y del que no tengo queja alguna, más bien al contrario.

El curso fue breve pero intenso y de él no puedo contar nada ya que está sujeto a NDA, sin embargo si que puedo decir que todo lo que se dijo allí está en:

Que digo yo que para qué tanto NDA si el contenido ya ha sido publicado…

Como no podía ser de otra forma encontré el momento para sacarme una foto con los ponentes y Luis, que todavía no es MVP pero dentro de nada yo apuesto a que lo será, y como me hace mucha ilusión y el blog es mío pues la subo:

Chan - Juan Carlos Gonzalez - Gustavo Velez - Luis Ruiz

Por si alguien no conoce a tan celebérrimos huespedes de este blog, en la foto somos, de derecha a izquierda para que el burro quede al final Luis Ruíz, Gustavo Vélez, Juan Carlos González y yo yo Chan, no Er, que me llamo Chan y me llamar Er Chan pero nunca Er a secas (fin de disambiguation).

Por cierto que Juan Carlos subió más fotos del evento en su post (mucho más ajustado en plazos de entrega que el mío, donde va a parar) aquí.

Publicar un comentario