SandcastleGUI

Today I discovered a cool tool for Sandcastle that can do your life a bit more wonderful. SandcastleGUI by Stephan Smetsers I think that he is an authentic geek … he says to me “The tool was made during one weekend while watching a Stargate episode… 🙂 I went nuts about the failing NDOC-program so I started using Sandcastle. Sadly no GUI was available, so I had to make one myself…. I never intented it to be distributed on the net….. but… look what responses it gave me….. very nice.”


This product is an userinterface for the Microsoft’s Sandcastle that creates help documentation for .NET assemblies.
SandcastleGUI has several additions made to the default Sandcastle generated output, such as:

– Support for online MSDN-links.
– Documenting of specified namespaces instead of entire assemblies.
– Multiple outputtypes (website and/or .CHM-file).
– Custom copyright line.
– Custom company logo.
– Custom product information.


 

Las WebParts en WSS3 y MOSS 2007 (4)

Otra de las mejoras importantes al usar las WebParts de ASP.Net 2.0 es la comunicación entre webparts, ya que ahora pasa a ser un proceso mucho menos tedioso que con las webparts de WSS2.


 ¿Qué necesitamos?


Lo primero que necesitamos es ver que información es la que queremos intercambiar entre las dos webparts, con las webparts de ASP Net 2.0 no tenemos las limitaciones que teníamos antes con la obligación de seleccionar uno de los interfaces que WSS2 nos proponía. Ahora disponemos de libertad para intercambiar información.


No obstante hay pre-definidos tres Interfaces, IWebPartField, IWebPartRow e IWebPartTable, pero no hay obligación de usarlos.


La información que van a intercambiar dos webparts, se conoce como “Contrato de comunicación” que representaremos con un Interface.


Por ejemplo para emular el conocido ICellProvider y el ICellConsumer de WSS2 y el IWebPartField que nos propone ASP.Net 2.0 bastará con intercambiar una cadena de texto, de manera que nuestro interface de comunicación será:

    public interface IMensaje
{
string Mensaje { get; }
}

Cada uno de los webparts que usaremos Proveedor y Consumidor usarán este Interface, el proveedor deberá implementarlo y el consumidor lo utilizará internamente usando una instancia del mismo. 


El webpart proveedor


using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace MiWebPart
{
public class Proveedor : WebPart, IMensaje
{
private TextBox entrada;
private Button accion;

// Creamos los controles
protected override void CreateChildControls()
{
entrada = new TextBox();
Controls.Add(entrada);

accion = new Button();
accion.Text = “Proveer”;
Controls.Add(accion);
}

protected override void RenderContents(HtmlTextWriter writer)
{
entrada.RenderControl(writer);
accion.RenderControl(writer);
}

[ConnectionProvider(“Mensaje”)]
public IMensaje ProveerMensaje()
{
return this;
}

// Enviamos el contenido del TextBox
public string Mensaje
{
get
{
return entrada.Text;
}
}
}
}


Comparado con las webparts de WSS2 ya veis que diferencia, hay que destacar el método ProveerMensaje() que está decorado con el atributo [ConnectionProvider(“Mensaje”)] en donde Mensaje es el tipo de información que intercambia este WebPart. ProveerMensaje devuelve una referencia a si mismo como el interface del mensaje que esta implementando (precioso…)


El webpart consumidor


using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

namespace MiWebPart
{
public class Consumidor : WebPart
{
private IMensaje mensaje;
private Label label;

[ConnectionConsumer(“Mensaje”)]
public void ConsumirMensaje(IMensaje imensaje )
{
mensaje = imensaje;
}

protected override void CreateChildControls()
{
label = new Label();
Controls.Add(label);
}

protected override void OnPreRender(EventArgs e)
{
if (mensaje != null)
{
label.Text = mensaje.Mensaje;
}

}

protected override void RenderContents(HtmlTextWriter writer)
{
label.RenderControl(writer);
}

}
}



Este webpart, solo necesita instanciar el interface “private IMensaje mensaje” y definir un método que lo consuma, este método que irá decorado con el atributo [ConnectionConsumer(“Mensaje”)], debe ser publico, no devolver nada y tomar como argumento un interface definido. (brillante…)


El resultado



Por último comentar, que existe la posibilidad de que dos webparts con distintos interfaces compartan información, para ello se pueden usar objetos de transformación, clases que derivaremos de WebPartTransformer.


 

Las WebParts en WSS3 y MOSS 2007 (3)

Siguiendo con lo expuesto anteriormente, lo primero es revisar el formato en que se exportan las webparts basadas en Asp.Net 2.0. Una vez exportado nuestro webpart lo primero que vemos es que la extensión a cambiado, de .dwp (las webparts de WSS2) a .webpart


También podemos observar que el espacio de nombres corresponde con la v3 <webPart xmlns=”http://schemas.microsoft.com/WebPart/v3″>, esto solo ocurre con las webparts nativas ya que por compatibilidad las webparts que usen la api Microsoft.SharePoint.WebPart, mantendrán el formato .dwp


<webParts>
  <webPart xmlns=”http://schemas.microsoft.com/WebPart/v3″>
    <metaData>
      <type name=”MiWebPart.MiPrimerWebPart, MiWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d196fc71b3d34a48″ />
      <importErrorMessage>Error importando el webpart</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name=”AllowClose” type=”bool”>True</property>
        <property name=”Width” type=”unit” />
        <property name=”AllowMinimize” type=”bool”>True</property>
        <property name=”MensajeVisible” type=”bool”>False</property>
        <property name=”AllowConnect” type=”bool”>True</property>
        <property name=”ChromeType” type=”chrometype”>Default</property>
        <property name=”TitleIconImageUrl” type=”string” />
        <property name=”Description” type=”string”>Mi descripción</property>
        <property name=”Hidden” type=”bool”>False</property>
        <property name=”TitleUrl” type=”string” />
        <property name=”AllowEdit” type=”bool”>True</property>
        <property name=”Height” type=”unit” />
        <property name=”HelpUrl” type=”string” />
        <property name=”Title” type=”string”>Mi Primer WebPart</property>
        <property name=”CatalogIconImageUrl” type=”string” />
        <property name=”Direction” type=”direction”>NotSet</property>
        <property name=”ChromeState” type=”chromestate”>Normal</property>
        <property name=”AllowZoneChange” type=”bool”>True</property>
        <property name=”AllowHide” type=”bool”>True</property>
        <property name=”HelpMode” type=”helpmode”>Navigate</property>
        <property name=”ExportMode” type=”exportmode”>All</property>
      </properties>
    </data>
  </webPart>
</webParts>

 


Era importante revisar este nuevo formato, por que es el que tendremos que usar si queremos instalar nuestro webpart desde un archivo .CAB como hacíamos en la versión 2 y usar el STSADM


Nuestro .webpart que forma parte del proyecto contendrá como mínimo lo siguiente:



<?xml version=”1.0″ encoding=”utf-8″?>
<webParts>
  <webPart xmlns=”http://schemas.microsoft.com/WebPart/v3″>
    <metaData>
      <type name=”MiWebPart.MiPrimerWebPart, MiWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d196fc71b3d34a48″ />
      <importErrorMessage>Error importando el webpart</importErrorMessage>
    </metaData>
    <data>
      <properties>
        <property name=”Title” type=”string”>Mi Primer WebPart</property>
        <property name=”Description” type=”string”>Mi descripción</property>
      </properties>
    </data>
  </webPart>
</webParts>

 


Para poder instalar nuestro archivo .CAB, debemos crear un manifiesto, este manifiesto por el momento es el mismo que se venia usando con la versión 2 y desconozco si realizarán un nuevo formato para esta nueva versión. Bien, entonces nuestro manifiesto será el siguiente:


<?xml version=”1.0″?>
<WebPartManifest xmlns=”http://schemas.microsoft.com/WebPart/v2/Manifest”>
  <Assemblies>
    <Assembly FileName=”MiWebPart.dll”>     
      <SafeControls>
        <SafeControl
          Namespace=”MiWebPart”
          TypeName=”*”
        />
      </SafeControls>
    </Assembly>
  </Assemblies>
  <DwpFiles>
    <DwpFile FileName=”MiPrimerWebPart.webpart”/>
  </DwpFiles>
</WebPartManifest>

 


La única diferencia con los manifiestos que veníamos haciendo es que en vez de especificar un archivo .dwp ahora especificamos un archivo .webpart


Por último nos queda crear un nuevo proyecto de instalación .CAB, y unirlo a nuestro proyecto del webpart.



Os dejo aquí una copia del proyecto completo que podeís usar como plantilla para otros webparts.


 Descargar MiWebPart.zip (23.53 KB)

Las WebParts en WSS3 y MOSS 2007 (2)

Continuando con el post anterior, usando las características de las WebParts de ASP Net 2.0,  podemos añadir propiedades a nuestras webparts para que se muestren en el area de edición.


using System.Web.UI;
using System.Web.UI.WebControls.WebParts;

namespace MiWebPart
{
public class MiPrimerWebPart : WebPart
{
private bool bMensajeVisible = true;

[Personalizable(PersonalizationScope.Shared),
WebBrowsable,
WebDisplayName(“Ver 2º Mensaje”),
WebDescription(“Activar desactivar el 2º mensaje”)]
public bool MensajeVisible
{
get { return bMensajeVisible; }
set { bMensajeVisible = value; }
}

protected override void RenderContents(HtmlTextWriter writer)
{
writer.Write(“Hola Mundillo!!”);

if (bMensajeVisible)
{
writer.Write(“<br><b>Hola Mundillo!! Otra vez</b>”);
}

base.RenderContents(writer);
}
}
}



Para ello basta con decorar las propiedades con los atributos necesarios. En este caso el atributo Personalizable indica que el valor de la propiedad se guardará cuando este se modifique, para que una propiedad pueda marcarse con el atributo Personalizable debe cumplir lo siguiente:

• La propiedad debe ser pública y debe tener descriptores de acceso get y set.
• La propiedad debe ser una propiedad de lectura y escritura.
• La propiedad debe estar sin parámetros.
• La propiedad no se puede indizar.


Este atributo define también si la personalización será compartida o individual. (PersonalizationScope.Shared, PersonalizationScope.User)


El atributo WebBrowsable indica si la propiedad designada se mostrará en el editor de propiedades.
El atributo WebDisplayName define el nombre que aparecerá junto a la propiedad.
Y por último el atributo WebDescription  contiene la descripción de la propiedad.


Una vez marcada la propiedad con sus atributos correspondientes podremos editarlos cuando modifiquemos las propiedades del webpart.



Finalmente, para poder hacer nuestro webpart exportable, debemos indicarlo explícitamente, de manera que podemos crear un constructor e indicarlo allí.


 public MiPrimerWebPart()
{
ExportMode = WebPartExportMode.All;
}



 


Parte 1 – Introducción a las webparts basadas en ASP.Net 2.0 para WSS3
Parte 2 – Propiedades personalizadas y exportación.
Parte 3 – Creando un archivo CAB para instalar nuestro webpart (descarga del proyecto completo)
Parte 4 – Comunicación de WebParts


 

Las WebParts en WSS3 y MOSS 2007 (1)

Como ya sabéis Windows SharePoints Services 3.0 está construido sobre ASP.Net 2.0, esto nos brinda la posibilidad de crear webparts que podríamos llamar nativas de ASP.Net 2.0 dentro de WSS3, estas webparts nativas vendrían derivados de System.Web.UI.WebControls.WebParts.WebPart.


Para mantener la compatibilidad (como prometieron) con desarrollos anteriores y para no perder la funcionalidad de ASP.Net 2.0 la antigua API Microsoft.SharePoint.WebPartPages.WebPart  que hemos venido usando con WSS2 deriva ahora de System.Web.UI.WebControls.WebParts.WebPart.


De manera que ahora disponemos de dos alternativas a la hora de desarrollar para WSS3 siempre moviéndonos en ASP.Net 2.0.


Según la versión preliminar del SDK, se nos recomienda usar la forma nativa a excepción de:

• Conexiones de webparts entre páginas
• Conexiones entre webparts que están fuera de una zona de webparts
• Conexiones en el lado del cliente
• Datos cacheados en la base de datos de contenido

Estas características solo están disponibles en las webparts heredadas de Microsoft.SharePoint.WebPartPages.WebPart 

Bueno, esto es un gran avance ya que el código para nuestro primer WebPart nativo de WSS3 queda reducido a:


using System.Web.UI;
using System.Web.UI.WebControls.WebParts;

namespace MiWebPart
{
public class MiPrimerWebPart : WebPart
{
protected override void RenderContents(HtmlTextWriter writer)
{
writer.Write(“Hola Mundillo!!”);
base.RenderContents(writer);
}
}
}



Usando VS2005 podemos crear un nuevo proyecto “Librería de clases”,  añadimos la referencia a System.Web y creamos nuestro primer webpart.

Al igual que con las WebParts de WSS2 deberemos firmar nuestro ensamblado (esto es mucho más fácil con VS2005) basta con decir en las propiedades del proyecto que queremos firmar el ensamblado con una nueva clave, y esta se creará automáticamente.

Generamos la solución y tenemos nuestro MiWebPart.dll

En este primer ejemplo vamos ha instalarlo en el Global Assembly Cache, de modo que tendremos que copiar la dll en el servidor c:windowsassembly.


Una vez copiado podemos pinchar sobre la dll y ver las propiedades para obtener el PublickKeyToken que necesitaremos para registrar el control en nuestro servidor como un control seguro.




Para ello debemos modificar el archivo web.config para añadir en la sección <SafeControls> la siguiente línea.


<SafeControl Assembly=”MiWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d196fc71b3d34a48″ 
Namespace=”MiWebPart” TypeName=”*” Safe=”True” />

Una vez registrado el control deberemos reiniciar el servidor IISRESET para que este este accessible.

En WSS3 una vez que la dll está registrada en el web.config será detectada. De modo que ahora solo nos queda añadirla a nuestra galería de webparts.  (Site Settings -> Galleries -> Web Parts, si no aparece pulsamos sobre New y la añadimos a la galeria)  


Después ya podemos ponerla donde queramos.