SharePoint 2010: “Proveedor de mapa de sitio” personalizado para ocultar la Variación (Custom SiteMap Provider)

Escenario

En estos días nos encontramos el caso de tener que ocultar el nodo correspondiente a la variación en el camino de hormigas, migas de pan,… (breadcrumb).

Home > Español > MySite > MyPage

Esto era imposible hacerlo con las herramientas que tenemos por defecto mediante la configuración del control que estábamos usando

   1: <asp:SiteMapPath SiteMapProvider="SPContentMapProvider" id="ContentMap" SkipLinkText="" NodeStyle-CssClass="ms-sitemapdirectional" runat="server"/>

 

Solución

Como solución a nuestro problema, decidimos crearnos nuestro propio proveedor para el mapa del sition (Custom SiteMap Provider). Para ello, nos creamos un proyecto de SharePoint 2010 en Visual Studio 2010 y añadimos una clase que herede de “SiteMapProvider”

   1: public class Navigation : SiteMapProvider

 

Esto nos obliga a implementar ciertos métodos necesarios para el correcto funcionamiento del provider.

   1: public override SiteMapNode FindSiteMapNode(string rawUrl)

   2:  {

   3:      throw new NotImplementedException();

   4:  }

   5:  

   6:  public override SiteMapNodeCollection GetChildNodes(SiteMapNode node)

   7:  {

   8:      throw new NotImplementedException();

   9:  }

  10:  

  11:  public override SiteMapNode GetParentNode(SiteMapNode node)

  12:  {

  13:      throw new NotImplementedException();

  14:  }

  15:  

  16:  protected override SiteMapNode GetRootNodeCore()

  17:  {

  18:      throw new NotImplementedException();

  19:  }

 
 
De estos métodos, el que más nos interesa es FindSiteMapNode, y es ahí donde debemos escribir nuestro código para evitar mostrar el nodo de la variación. En nuestro caso, lo que hemos hecho ha sido comparar el nombre del nodo con el de la variación actual y si coinciden, quitamos el nodo de la lista y enlazamos su nodo padre con su nodo hijo para que permanezca la relación.
 
De esta forma, el breadcrum nos quedará así: Home > MySite > MyPage
El código completo que escribimos es el siguiente.
   1: public class Navigation : SiteMapProvider

   2: {

   3:     private List<string> variations = new List<string>();

   4:     SiteMapNode rootnode;

   5:  

   6:     public Navigation()

   7:     {

   8:         ReadOnlyCollection<VariationLabel> allVariations = Variations.Current.UserAccessibleLabels;

   9:         foreach (VariationLabel item in allVariations)

  10:             variations.Add(item.DisplayName);

  11:     }

  12:  

  13:     private bool ExistsVariation(string Title)

  14:     {

  15:         return variations.Contains(Title);

  22:     }

  23:  

  24:     private void NodeToList(SiteMapNode node, ref SiteMapNodeCollection list)

  25:     {

  26:         if (node != null)

  27:         {

  28:             if (!ExistsVariation(node.Title))

  29:                 list.Add(node);

  30:             NodeToList(node.ParentNode, ref(list));

  31:         }

  32:     }

  33:  

  34:     private SiteMapNode GetNodeWithoutVar(SiteMapNode node)

  35:     {

  36:         SiteMapNodeCollection NodesCol = new SiteMapNodeCollection();

  37:         NodeToList(node, ref(NodesCol));

  38:  

  39:         for (int i = 0; i < NodesCol.Count - 1; i++)

  40:             NodesCol[i].ParentNode = NodesCol[i + 1];

  41:         return NodesCol[0];

  42:     }

  43:  

  44:     public override SiteMapNode FindSiteMapNode(string rawUrl)

  45:     {

  46:         PortalSiteMapProvider portalProvider = PortalSiteMapProvider.WebSiteMapProvider;

  47:         PortalSiteMapNode webNode = ((PortalSiteMapNode)portalProvider.FindSiteMapNode (rawUrl));

  48:         

  49:         return GetNodeWithoutVar(webNode.WebNode);

  50:     }

  51:  

  52:     protected override SiteMapNode GetRootNodeCore()

  53:     {

  54:         return rootnode;

  55:     }

  56:  

  57:     public override SiteMapNodeCollection GetChildNodes(SiteMapNode node)

  58:     {

  59:         SiteMapNodeCollection children = new SiteMapNodeCollection();

  60:         if (node.HasChildNodes)

  61:             foreach (SiteMapNode cNode in node.ChildNodes) children.Add(cNode);

  62:         return children;

  63:     }

  64:  

  65:     public override SiteMapNode GetParentNode(SiteMapNode node)

  66:     {

  67:         return node.ParentNode;

  68:     }

  69: }