Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Gestione avanzata di SiteMap e navigazione

Localizzare e personalizzare sitemap e strumenti di navigazione
Localizzare e personalizzare sitemap e strumenti di navigazione
Link copiato negli appunti

La gestione della navigazione è una parte di fondamentale importanza nello sviluppo di un sito web. Questo perché essa rappresenta il modo in cui gli utenti navigano il sito e trovano i contenuti di loro interesse.

La navigazione di un sito è parte portante dell'usabilità dell'applicazione stessa: chi naviga deve avere sempre a portata di mano le macrosezioni del sito, un ritorno immediato alla home page, il punto in cui si trova la pagina corrente e una visualizzazione generale dell'intera struttura, in modo tale da essere facilitato durante la navigazione a trovare le informazioni che lo interessano.

ASP.NET, nella sua versione 2.0, ha inserito dei meccanismi e alcuni nuovi oggetti in grado di facilitare lo sviluppatore nella creazione e nella gestione dell'intera struttura di navigazione del sito. L'insieme di questi meccanismi prende il nome di Site Navigation; al suo interno troviamo nuovi controlli web, un gruppo di nuove API per la manipolazione degli elementi di navigazione e un sistema, basato sul concetto di "Provider Model", che espone le informazioni di navigazione alle pagine della nostra applicazione web.

I nuovi controlli aggiunti sono quattro, uno dei quali va inserito sotto la categoria dei "Data Source Controls", mentre gli altri sono tutti di presentazione. Abbiamo avuto modo di conoscerli nella Guida ASP.NET 2.0. Ripassiamoli:

  • Menu - controllo che visualizza la struttura del sito attraverso un menu a tendina personalizzabile (System.Web.UI.WebControls.Menu);
  • TreeView - controllo che visualizza la struttura del sito in un menu ad albero espandibile (System.Web.UI.WebControls.TreeView);
  • SiteMapPath - controllo che visualizza la posizione corrente dell'utente rispetto alla struttura del sito (System.Web.UI.WebControls.SiteMapPath);
  • SiteMapDataSource - controllo che funge da fonte di dati per i controlli di presentazione descritti sopra (System.Web.UI.WebControls.SiteMapDataSource).

Questi controlli, combinati assieme ad un provider di navigazione, ci aiutano a generare la struttura della nostra applicazione. Il provider espone alle pagine del sistema le informazioni di navigazione. Queste informazioni hanno come repository predefinito dei file, in formato XML, con estensione .sitemap (estensione aggiunta con l'avvento di ASP.NET 2.0), nei quali possiamo salvare la struttura ad albero delle pagine dell'applicazione web, legando ad ogni indirizzo, un titolo ed una descrizione.

È possibile inoltre, creare dei provider personalizzati per la lettura delle informazioni di navigazione da altri storage, come per esempio da una base di dati o dal file system (per la creazione di un provider di navigazione personalizzato, rimandiamo all'ultimo paragrafo dell'articolo).

Per la creazione di nuovi provider, il framework ha inserito una sezione nel file di configurazione del sito, in cui questi vanno registrati per poi poter essere richiamati all'interno delle pagine. Come provider di default, ASP.NET si aspetta di trovare nella root dell'applicazione il file web.sitemap. Questo è l'unico file .sitemap che non necessita di essere registrato tra i provider di navigazione all'interno del web.config.

Tutti i file ".sitemap", che vogliamo inserire nell'applicazione, devono avere una struttura simile a questa:

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
  <siteMapNode url="~/Default.aspx" title="Home" description="Home">
    <siteMapNode url="~/page1.aspx" title="Pagina1" description="Pagina1" />
    <siteMapNode url="~/page2.aspx" title="Pagina2" description="Pagina2" />
  </siteMapNode>
</siteMap>

Un'architettura di questo genere semplifica la creazione e la gestione della navigazione dei nostri siti web, grazie proprio all'utilizzo di XML e di oggetti di presentazione da personalizzare in base alle proprie esigenze grafiche.

Per visualizzare la struttura di navigazione descritta nel file di site map, non dobbiamo far altro che inserire nelle nostre pagine un controllo che funge da fonte di dati (SiteMapDataSource), e un controllo di presentazione (per esempio un Menu), e il gioco è fatto!

<asp:SiteMapDataSource ID="siteMapDataSource" runat="server" />
<asp:Menu ID="Menu1" runat="server" DataSourceID="siteMapDataSource" />

Vediamo ora alcune tecniche per utilizzare al meglio gli strumenti che ASP.NET 2.0 ci mette a disposizione.

Suddividere gli elementi di navigazione in più file

Abbiamo visto che le informazioni di navigazione per il nostro sito, possono essere salvate all'interno di un file .sitemap. Soprattutto agli occhi di una figura con compiti amministrativi, può risultare utile suddividere la struttura dell'applicazione in più parti e dare la gestione di ognuna delle parti a una persona diversa.

Il sistema di Site Navigation di ASP.NET ci offre anche questa funzionalità. Possiamo creare un file .sitemap per ogni macro-sezione del nostro sito, farli gestire a gruppi o utenti differenti e creare un provider di navigazione che raggruppi tutte queste sotto sezioni. Il provider può essere creato seguendo due modalità:

attraverso l'attributo siteMapFile dell'elemento <siteMapNode>:

File .sitemap

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
  <siteMapNode url="~/Default.aspx" title="Home" description="Home">
    <siteMapNode url="~/blog.aspx" title="Blog" description="Blog" />
    <siteMapNode siteMapFile="~/Articoli/articoli.sitemap" />
    <siteMapNode siteMapFile="~/Projects/projects.sitemap" />
  </siteMapNode>
</siteMap>

oppure, registrando tutti i sotto-provider all'interno del web.config, e richiamandoli nel file principale attraverso l'attributo Provider (sempre dell'elemento <siteMapNode>)

web.config

<siteMap defaultProvider="DefaultSiteMapProvider">
  <providers>
    <clear />
    <add name="DefaultSiteMapProvider" siteMapFile="~/Web.sitemap" type="System.Web.XmlSiteMapProvider" />
    <add name="ProviderArticoli" siteMapFile="~/Articoli/articoli.sitemap" type="System.Web.XmlSiteMapProvider" />
    <add name="ProviderProgetti" siteMapFile="~/Projects/projects.sitemap" type="System.Web.XmlSiteMapProvider" />
  </providers>
</siteMap>

web.sitemap

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
  <siteMapNode url="~/Default.aspx" title="Home" description="Home">
    <siteMapNode url="~/blog.aspx" title="Blog" description="Blog" />
    <siteMapNode provider="ProviderArticoli" />
    <siteMapNode provider="ProviderProgetti" />
  </siteMapNode>
</siteMap>

Localizzazione degli elementi di navigazione

Un'altra funzionalità che abbiamo a disposizione, è quella di gestire le informazioni di navigazione in più lingue, in modo tale da presentare all'utente che naviga il nostro sito la struttura localizzata secondo la lingua del suo browser.

Questo è possibile attraverso i nuovi meccanismi di localizzazione di ASP.NET 2.0 che sono composti da due nuove directory (la App_GlobalResources e la App_LocalResources), utili a contenere tutti i file risorsa (.resx) aventi le coppie chiave-valore per ogni etichetta da localizzare.

Per la localizzazione della site map, dobbiamo inserire all'interno della directory App_GlobalResources (directory relativa a tutte le risorse globali per l'applicazione) un file di risorsa per ogni lingua che vogliamo gestire; questo file deve essere nominato come il file di site map da localizzare (per esempio web.sitemap) seguito dal codice della lingua scelta. Per esempio:

Italiano: web.sitemap.it-it.resx
Inglese : web.sitemap.en-us.resx
Francese: web.sitemap.fr-fr.resx

Una volta creati questi file di risorsa, dobbiamo aggiungere al nodo principale della site map l'attributo enableLocalization ed impostarlo su true. Poi, per ogni nodo di navigazione, dobbiamo impostare una chiave di localizzazione (con l'attributo resourceKey) in modo tale che le etichette di quel singolo elemento, possano essere valorizzate direttamente dal file di risorse della lingua corrente.

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0"
      enableLocalization="true">
  <siteMapNode url="~/Default.aspx" title="Home" resourceKey="HomeKey">
    <siteMapNode url="~/blog.aspx" title="Blog" resourceKey="BlogKey" />
    <siteMapNode url="~/articoli.aspx" title="Articoli" resourceKey="ArticoliKey" />
  </siteMapNode>
</siteMap>

In ogni file di risorse dobbiamo poi inserire tutti i valori per ogni proprietà dell'elemento <siteMapNode> che volgiamo localizzare; quindi, per esempio, la chiave "HomeKey" avrà nel file di risorse le seguenti chiavi:

  • HomeKey.Title
  • HomeKey.Description

In questo modo, in fase di rendering dei controlli di navigazione, il site map provider sceglie il file di risorse della lingua corrente e legge i valori delle chiavi legate alle relative proprietà del nodo.

E così la nostra struttura di navigazione è stata anche localizzata !

Creazione della site map da una connessione OleDb

Per creare la struttura di navigazione del nostro sito, non siamo obbligati ad usare file .sitemap come fonte di informazioni, anche se è questo è forse il modo più facile da comprendere ed utilizzare.

È possibile, per esempio, creare un provider di navigazione che legga il contenuto di una particolare directory del file system, oppure che crei la struttura del sito prelevando informazioni da un database.

Il caso più comune è quello in cui si utilizzano pagine dinamiche che esistono in virtù di un legame con una particolare query al database. Anche queste pagine dovrebbero essere inserite nella struttura di navigazione del sito.

Per far ciò, grazie al modello basato sui provider, su cui si basa l'intero sistema di ASP.NET 2.0 e in generale l'intero .NET Framework, possiamo creare il nostro provider di navigazione personalizzato creando una classe (da inserire nella directory App_Code o in un assembly da referenziare nell'applicazione) che erediti dalla classe StaticSiteMapProvider e che implementi i metodi:

  • BuildSiteMap - che carica le informazioni di navigazione e ritorna la collezione di nodi, che a partire dal nodo di root, formano l'albero di navigazione del sito;
  • GetRootNodeCore - che ritorna il nodo principale dell'albero.

Inoltre, ci vengono offerti altri metodi complementari da sovrascrivere per prelevare delle informazioni dai file di configurazione in fase di inizializzazione (Initialize()) o per ripulire le informazioni dalla memoria (clear()).

La realizzazione del nostro provider risulta abbastanza semplice, infatti attraverso le API di navigazione (soprattutto della classe SiteMapNode), creiamo prima il nodo di partenza (rappresentato dalla variabile rootNode), poi tramite una connessione alla base di dati e l'esecuzione di una query, abbiamo dato vita a tutti i suoi nodi figli, creando sempre delle nuove istanze della classe SiteMapNode.

Ogni figlio viene aggiunto al nodo di partenza attraverso il metodo AddNode(), metodo ereditato dalla classe padre StaticSiteMapProvider, in modo tale da creare la dipendenza padre-figlio tra i nodi di navigazione.

Nell'esempio, creiamo solo un livello di nodi al di sotto del nodo di partenza; sarebbe comunque possibile creare una struttura ad albero più complessa, utilizzando la ricorsione.

Come operazione primaria, però, facciamo l'overload del metodo Initialize() in modo tale da prelevare dal web.config la stringa di connessione al nostro database.

Vediamo il codice per creare il nostro provider di navigazione personalizzato, utilizzando una connessione OleDb:

public class CustomSiteMapProvider : StaticSiteMapProvider
{
  private OleDbConnection conn = null;
  private SiteMapNode rootNode = null;

  public CustomSiteMapProvider(){ }

  public override void Initialize(string name, NameValueCollection attributes)
  {
    base.Initialize(name, attributes);
    if (String.IsNullOrEmpty(ConfigurationManager.ConnectionStrings["strConn"].ConnectionString))
      throw new ConfigurationErrorsException("Stringa di connessione non trovata !");
  }

  
  [MethodImpl(MethodImplOptions.Synchronized)]
  public override SiteMapNode BuildSiteMap()
  {
    Clear();
    if (this.rootNode != null) return this.rootNode;

    this.rootNode = new SiteMapNode(this, "0", "~/samples.aspx", "Samples", "Samples");

    AddNode(this.rootNode, null);

    string query = "SELECT * FROM Samples ORDER BY ID ASC";
    try
    {
      string strConn = ConfigurationManager.ConnectionStrings["strConn"].ConnectionString.Replace("[App_Data]", HttpContext.Current.Server.MapPath("~/App_Data/"));
      using (conn = new OleDbConnection(strConn))
      {
        OleDbCommand cmd = new OleDbCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = query;
        cmd.Connection = conn;
        conn.Open();
        
        OleDbDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
        if (reader.HasRows)
        {
          while (reader.Read())
          {
            SiteMapNode childNode = new SiteMapNode(this, reader["ID"].ToString(), this.rootNode.Url +
                  "?id=" + reader["ID"].ToString(), reader["Title"].ToString(), reader["Title"].ToString());

            AddNode(childNode, this.rootNode);
          }
          reader.Close();
          reader.Dispose();
        }
        else
          return null;
      }
    }
    catch (Exception exe)
    {
      throw new Exception(exe.Message, exe);
    }
      return this.rootNode;
  }

  protected override SiteMapNode GetRootNodeCore()
  {
    BuildSiteMap();
    return this.rootNode;
  }

  protected override void Clear()
  {
    this.rootNode = null;
    base.Clear();
  }
}

Il nostro provider di navigazione personalizzato è pronto all'uso; dobbiamo solo registrarlo nel web.config e richiamarlo nelle nostre pagine.

Per registrarlo, ci avvaliamo sempre dell'elemento <add> all'interno della sezione siteMap/providers, in cui specifichiamo solamente il nome e il tipo del nostro provider.

<siteMap defaultProvider="CustomSiteMapProvider">
  <providers>
    <clear />
    <add name="CustomSiteMapProvider" type="CustomSiteMapProvider" />
  </providers>
</siteMap>

Ora possiamo richiamarlo in qualsiasi pagina del nostro sito o addirittura in altre site map gia presenti.

Un'ultima tecnica da utilizzare, davvero molto utile, è quella invece di differenziare la visualizzazione degli elementi dell'albero di navigazione in base al ruolo dell'utente corrente. Per un esempio del filtro vi rimando a questo tutorial.

Conclusioni

Con il sistema di Site Navigation, ASP.NET 2.0 ha colmato una notevole lacuna della gestione dei siti. Poter gestire con facilità la struttura di navigazione del proprio sito web è diventata ormai un'esigenza, e pensare che può essere gestito tutto tramite dei file XML è davvero gratificante.

In più, il sistema è estendibile, sempre grazie al modello basato sui provider, che ci permette di inventarci sistemi ancora più evoluti per far sì che le informazioni di navigazione del sito, si aggiornino assieme alla struttura stessa del sito; queste tecniche sono ottime se utilizzate in sistemi di content management.

Ti consigliamo anche