Webpart Virtual Earth para Sharepoint 2007 y WSS 3.0

El mes pasado estuve participando en la construcción de un sitio informativo contra el nuevo virus A(N1H1). En este desarrollo, lo que hicimos es cargar en un mapa todos los centros de atención disponibles de cada país para que la gente estuviera informada. Debo reconocer que fue una muy linda experiencia, por el desarrollo en sí y porque el proyecto fue implementado con grandes amigos de la comunidad.
En este caso, lo que quiero compartir con ustedes es una Webpart que muestra la ubicación geográfica mediante latitud y longitud cargados en una lista. La lista que se utilizara como fuente de datos, deberá tener asociado un tipo de contenido especialmente creado para manejar los puntos, con lo cual podemos tener referencia geográfica sobre cualquier lista de Sharepoint que necesitemos, es decir, podemos tener una lista de contactos, clientes o sucursales de nuestra empresa, mostrando la ubicación en el mapa.
En la imagen 1 podemos ver la WebPart cargada y funcionando, mostrando la ubicación de un punto cargado en una lista.

[Imagen 1]
clip_image002

El desarrollo está realizado en Visual Studio 2008 y consta de 3 proyectos diferentes:

1) Componente de Clases -> Encargado de leer la información cargada en Sharepoint.

2) Proyecto Web -> Este proyecto se creó para crear un control de usuario (ASCX) que es el encargado de cargar el mapa.

3) Proyecto de deploy WSP -> Proyecto encargado de crear la característica, tipo de contenido y la Webpart que se instalara en Sharepoint.

Lo primero que debemos entender es cómo funcionan los servicios de Mapas de Microsoft y como debemos utilizarlos. El manejo se realiza mediante JavaScript, es decir, lo primero que tenemos que registrar es una referencia al SDK para que tengamos acceso al modelo de Objetos en JavaScript. En la sección 1 vemos el registro que debemos hacer al SDK. En nuestro ejemplo, el mismo lo incluimos dinámicamente con Asp.Net.

[Sección 1]

<script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" type="text/javascript"></script>

Otro elemento importante que tenemos que tener, es un objeto HTML donde se cargara nuestro mapa, en este ejemplo hemos colocado una Div y le hemos asignado un Id, ya que cuando empecemos a trabajar con los Objetos JavaScripts lo vamos a tener que pasar el Id de nuestra div en el constructor. En la sección 2 se puede ver la declaración de dicha Div.

[Sección 2]

<div id="myMap" style=’position:relative; width:600px; height:600px;’></div>

Lo próximo es empezar a crear funciones JavaScript que nos permitan crear los mapas y cargarlos. Como el ejemplo utiliza como fuente de datos una lista de Sharepoint, entonces, la inclusión de muchas de las funciones se realizada desde el servidor utilizando las características de Asp.Net. En la sección 3 vemos un ejemplo del código que debemos utilizar para cargar un mapa con unas coordenadas (latitud y longitud) determinadas.

[Sección 3]

<script type="text/javascript">
         var map = null;        
         function GetMap()
         {
            map = new VEMap(‘myMap’);
            map.LoadMap(new VELatLong(47.6, -122.33), 10 ,’r’ ,false);
         }  
</script>

Lo primero que hacemos es crearnos un objeto llamado VEMap y le pasamos el Id de la div que tenemos en el HTML para que se muestre el mapa. Una vez creado el mismo, invocamos el método LoadMap y le pasamos como primer parámetro una instancia del objeto VELatLong, el cual recibe la latitud y longitud que queremos mostrar. Como segundo parámetro el nivel de zoom que queremos y después una denominación para estilo que determina como queremos ver el mapa.
En el ejemplo podemos ver también que el punto en el mapa lo marcamos con un icono de color rojo donde mostramos información adicional, como ser la dirección y teléfono en este ejemplo. Para hacer esto, el SDK nos proporciona un objeto llamado VEShape el cual el constructor recibe dos parámetros, uno el tipo de icono que queremos crear y como segundo parámetro un objeto del tipo VELatLong con la latitud y longitud de donde queremos ubicarlo, en el ejemplo utilizamos el mismo que usamos para construir el mapa. Una vez que tenemos dicho objeto creado, lo que debemos hacerlo es cargarlo en nuestro mapa, para lo cual utilizaremos un método del objeto VEMap, llamado AddShape que recibe dicho objeto. En la sección 4 vemos el código JavaScript completo utilizado en el ejmplo.

[Sección 4]

<script type="text/javascript">

var map = null;

var pinid = 0;

function GetMap(pVeLatLong, pZoom) {

map = new VEMap(‘myMap’);

map.LoadMap(pVeLatLong, pZoom, ‘r’, false);

}

function AddPushpin(pVeLatLong, pNombre, pDescripcion) {

var shape = new VEShape(VEShapeType.Pushpin, pVeLatLong);

shape.SetTitle(pNombre);

shape.SetDescription(pDescripcion);

pinid++;

map.AddShape(shape);

}

var mm_load = window.onload;

window.onload = function() {

if (typeof LoadMapa != ‘undefined’)

LoadMapa();

if (typeof mm_load != ‘undefined’)

eval(mm_load);

}

</script>

Ahora lo que tenemos que hacer es colocar el código C# de nuestro control de usuario para implementar el comportamiento deseado. En el ejemplo lo que hacemos es cargar en el Load del control los datos de la lista de Sharepoint y en el evento del Comobo Box inyectar el código JavaScript necesario para el punto seleccionado por el usuario. Con esto logramos que cada vez que el usuario seleccione un punto el mapa lo dibuje dependiendo de las coordenadas cargadas.
Una vez que nuestro control de usuario esta pronto, vamos a modificar la directiva de control para referenciar el ensamblado donde estará la clase que contiene el código, puesto que en el modelo de instalación que tenemos, el ensamblado estará instalado en la GAC, ya que el mismo será instalado por nuestro paquete WSP, en la sección 5 podemos ver la directiva del control donde en el atributo Inherits declaramos la clase y a continuación la firma del ensamblado completo.

[Sección 5]

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="LocationsVirtualEarth.ascx.cs" Inherits="Siderys.Blog.VirtualEarth.UI.UserControl.LocationsVirtualEarth, Siderys.Blog.VirtualEarth.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=711eed342842acee" %>

Vamos a prepara nuestro proyecto instalador, para que cree la característica, tipo de contenido y columnas del sitio que necesitamos tener en Sharepoint para que la solución funcione. En la imagen 2 podemos ver la estructura de carpetas creadas en el proyecto para poder instalar todos los archivos en Sharepoint.

[Imagen 2]
clip_image003

Cuando creamos el proyecto (utilizando el WSPBuilder) se nos crea la carpeta 12, esta carpeta hace referencia a la carpeta 12 creada en el sistema de archivos cuando instalamos Sharepoint (C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions12). Lo que nosotros debemos hacer es ir creando las carpetas (igual que la instalación de Sharepoint) donde queremos que se coloquen nuestro archivos, por ejemplo las características se encuentran en la carpeta Feature, dentro de la carpeta Template, por lo cual la creamos si la necesitamos o agregamos un nuevo ítem en el proyecto del tipo característica y se nos creara automáticamente. En la imagen 2 vemos que hay una carpeta llamada Siderys.Blog.VirtualEarth.UI.WebPart que representa la característica que vamos a estar creando. En la carpeta UserControl colocaremos nuestro control de usuario para que sea instalado en Sharepoint, esto nos permitirá tener disponible el mismo desde cualquier portal web que tengamos creado. Después creamos la carpeta GAC, esta carpeta contendrá todos los ensamblados que vamos a colocar en la GAC y por ultimo tenemos la carpeta WebPartCode, que contiene la Webpart que vamos a estar creando. En la imagen 3 podemos ver la estructura de carpetas con todos los archivos necesarios creados.

[Imagen 3]
clip_image004

Algunos archivos no están incluidos en el proyecto, puesto que son copiados cuando se compilan los otros proyectos (mediante un script configurado en las propiedades del proyecto), pero no se preocupen, no es necesario que estén incluidos para generar el WSP, ya que solo basta que estén en dichas carpetas.
Como comentamos, la instalación nos creara un tipo de contenido y sus campos para que el usuario pueda asociar dicho tipo de contenido a la lista que desea y así tener la capacidad de cargar puntos geográficos en una lista existente. En la sección 6 podemos ver el código del archivo XML del archivo SiderysVirtualEarthMapContentType.xml para crear el tipo de contenido correspondiente.

[Sección 6]

 

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <ContentType ID="0x01001B25C760504E45c8AA38B26573E16F61"               
    Name="Siderys.Blog.VirtualEarthMap"
    Group="Siderys.Blog"
    Description="Content Type to add fields to create point to use in maps">
    <FieldRefs>
      <FieldRef ID="{0664FE0B-F9B2-46eb-B069-0DAE0C610935}" 
Name="Name Point" Required="TRUE"  ShowInEditForm = "TRUE" ShowInNewForm = "TRUE" 
ShowInDisplayForm ="TRUE"/>
      <FieldRef ID="{613ADC57-8EB4-49c3-BC76-126791C6C050}" 
Name="Latitude" Required="TRUE"  ShowInEditForm = "TRUE" ShowInNewForm = "TRUE" 
ShowInDisplayForm ="TRUE"/>
      <FieldRef ID="{FD566634-C1E0-45d5-BB4E-41A364C5AA37}" 
Name="Longitude" Required="TRUE"  ShowInEditForm = "TRUE" ShowInNewForm = "TRUE" 
ShowInDisplayForm ="TRUE"/>
      <FieldRef ID="{CF35C355-55F7-4131-9D94-A4957C750F38}" 
Name="Address Point" Required="TRUE"  ShowInEditForm = "TRUE" ShowInNewForm = "TRUE" 
ShowInDisplayForm ="TRUE"/>
      <FieldRef ID="{1DAE65FF-9FA5-48ce-A1D7-E4634F97A219}" 
Name="Phone Point" Required="TRUE"  ShowInEditForm = "TRUE" ShowInNewForm = "TRUE" 
ShowInDisplayForm ="TRUE"/>      
    </FieldRefs>
   </ContentType>
</Elements>

En la sección 7 podemos ver el código XML del archivo Fields.xml para crear columnas de sitio en nuestro portal de Sharepoint, el cual será ejecutado al instalar la solución

[Sección 7]

<Elements xmlns="http://schemas.microsoft.com/sharepoint/"
 xmlns:sen="http://schemas.seneca.com/sharepoint/">
  <Field
    ID="{0664FE0B-F9B2-46eb-B069-0DAE0C610935}"
    Type="Text"
    Name="NamePoint"
    DisplayName="Name Point"
    StaticName="NamePoint"
    Hidden="FALSE"
    Required="TRUE"
    Sealed="FALSE"
    Group="Siderys.Blog"
    Description="Name of the point"/>
  <Field
    ID="{613ADC57-8EB4-49c3-BC76-126791C6C050}"
    Type="Text"
    Name="Latitude"
    DisplayName="Latitude"
    StaticName="Latitude"
    Hidden="FALSE"
    Required="TRUE"
    Sealed="FALSE"
    Group="Siderys.Blog"
    Description="Latitud of the point"/>
  <Field
    ID="{FD566634-C1E0-45d5-BB4E-41A364C5AA37}"
    Type="Text"
    Name="Longitude"
    DisplayName="Longitude"
    StaticName="Longitude"
    Hidden="FALSE"
    Required="TRUE"
    Sealed="FALSE"
    Group="Siderys.Blog"
    Description="Longitude of the point"/>
  <Field
    ID="{CF35C355-55F7-4131-9D94-A4957C750F38}"
    Type="Text"
    Name="AddressPoint"
    DisplayName="Address Point"
    StaticName="AddressPoint"
    Hidden="FALSE"
    Required="TRUE"
    Sealed="FALSE"
    Group="Siderys.Blog"
    Description="Direccion of the point"/>
  <Field
    ID="{1DAE65FF-9FA5-48ce-A1D7-E4634F97A219}"
    Type="Text"
    Name="PhonePoint"
    DisplayName="Phone Point"
    StaticName="PhonePoint"
    Hidden="FALSE"
    Required="TRUE"
    Sealed="FALSE"
    Group="Siderys.Blog"
    Description="Phone of the point"/>
</Elements>

Por último en la sección 8 tenemos el código XML del archivo feature.xml para crear nuestra característica en Sharepoint y que deberemos activar en el portal de Sharepoint donde queremos utilizar nuestra solución.

[Sección 8]

<Feature  Id="F8AC6324-85CA-4222-B0A0-493E7039C5C9"
          Title="Siderys.Blog.VirtualEarth.UI.WebPart"
          Description="WebPart to show locations in a Virtual Earth Maps"
          Version="12.0.0.0"
          Hidden="FALSE"
          Scope="Site"
          DefaultResourceFile="core"
          xmlns="http://schemas.microsoft.com/sharepoint/">
  <ElementManifests>
    <ElementManifest Location="elements.xml"/>
    <ElementManifest Location="Fields.xml"/>
    <ElementManifest Location="SiderysVirtualEarthMapContentType.xml"/>
    <ElementFile Location="Siderys.Blog.VirtualEarth.UI.WebPart.webpart" />
  </ElementManifests>
</Feature>

En la imagen 4 podemos ver la característica activada en las características de la colección de sitio de nuestro portal Web.

[Imagen 4]

clip_image006

Lo próximo que debemos hacer es crear el archivo WSP, para lo cual seleccionamos el proyecto y del menú contextual seleccionamos la opción crear WSP, dentro de la opción WSPBuilder. Para instalar el mismo en Sharepoint, usamos un archivo bat, que podemos ver en la sección 10

[Sección 10]

stsadm -o addsolution -filename Siderys.Blog.VirtualEarth.WSP.wsp

echo *

echo * Activando la solucion Siderys.Blog.VirtualEarth.WSP.wsp

echo *

stsadm -o deploysolution -name Siderys.Blog.VirtualEarth.WSP.wsp -immediate –allowGacDeployment

stsadm -o execadmsvcjobs

iisreset

En mi SkyDrive podrán encontrar el código completo del ejemplo. Para correr el mismo necesitan tener Visual Studio 2008 y WSPBuilder instalado en sus maquinas.

clip_image007

Descargar Solución Completa con Instalador

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *