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

I provider in ASP.NET 2.0

Classi che forniscono dati e servizi. Una delle caratteristiche interessanti di .NET 2.0
Classi che forniscono dati e servizi. Una delle caratteristiche interessanti di .NET 2.0
Link copiato negli appunti

Il modello basato sui provider è un aspetto molto importante di ASP.NET e rappresenta, da un punto di vista architetturale, una delle novità più interessanti della versione 2.0 del .Net Framework.

Il modello di provider permette agli sviluppatori sfruttare i provider nativi di ASP.NET oppure di sostituirli o migliorarli.

In questo articolo introduciamo il Modello di Provider spiegandone la motivazione di base, la struttura nel dettaglio e, sperimentando in modo diretto, la creazione di un provider di mappe di siti Web personalizzato che ci consente di estrapolare i dati relativi alle mappe dei siti da un database Ms Sql Server anziché da un file XML.

Perché utilizzare i provider?

L'utilizzo dei Provider nasce dalla necessità di disporre di un pattern semplice ed efficace per rendere alcune parti di una applicazione personalizzabili.

ASP .NET 2.0 prevede diversi servizi basati su provider, come ad esempio Membership, Ruoli, Gestione dello stato, Personalizzazione, Mappa e navigazione del sito ed altro; questi servizi utilizzano un API comune per svolgere le diverse operazioni. Questa API, facente parte del sistema di ASP.NET, viene esposta come componente collegabile (dll), in questo modo rimane incapsulata e gli sviluppatori possono utilizzarla senza preoccuparsi di come è strutturata internamente.

Se i provider inclusi nel sistema non sono sufficienti a soddisfare le proprie esigenze, ad esempio se si desidera archiviare i dati relativi allo stato delle sessioni in un database diverso da Ms SQL Server, è possibile implementare provider personalizzati in grado di comunicare con il tipo di database scelto. Il modello è facilmente estendibile, ciascun sviluppatore può implementare nuovi Provider personalizzati o acquistarli da terze parti.

Nel modello di Provider, l'API di livello superiore rimane la stessa mentre l'implementazione è affidata a specifiche classi "Provider"

Figura 1. Modello di provider
Modello di provider

Un pò di teoria: il design pattern

Dietro al modello di provider c'è il popolare design pattern comportamentale "pattern strategy" appartenente alla famiglia GoF (Gang of Four).

Il design pattern Strategy consiste nella possibilità di rendere intercambiabili tra loro le diverse strategie di implementazione di un algoritmo applicativo. Ogni applicazione, seleziona l'algoritmo più adatto in relazione al particolare contesto senza nessun impatto sull'interfaccia della funzionalità messa a disposizione dalla API di programmazione. Il tutto avviene in maniera del tutto trasparente agli sviluppatori.

Il pattern Strategy prevede, per ogni oggetto, un modo astratto di esporre le proprie funzionalità in modo tale che, un client, può scollegare l'implementazione di default e collegarne una propria.

Gli sviluppatori possono implementare nuovi Provider personalizzati, ridefinire il comportamento dei Provider già inclusi nel sistema, i client possono collegarsi e personalizzare comportamento e impostazioni.

Tutto questo non significa che l'applicazione diventa un progetto "open-source",
ma che è possibile personalizzare alcune parti dell'ambiente di runtime ASP.NET attraverso le classi denominate appunto provider, dalle quali è possibile derivarne una propria.

La pratica

L'implementazione di un proprio provider in ASP.NET prevede la scrittura:

  • della classe, che fornisce le funzionalità principali;
  • del livello di configurazione, che permette al runtime di ASP.NET di localizzare il provider all'interno dei file di configurazione e di istanziarlo;
  • del livello di memorizzazione, che può essere il database, un file XML o qualsiasi altro supporto fisico in cui vengono memorizzati i dati.

Per estendere un provider dobbiamo definire una nuova classe che eredita dalla classe base definita per quel provider. Tutte le classi base provider derivano da una classe base comune denominata Providerbase.

La classe Providerbase fornisce il metodo Initialize() che è l'unico metodo comune a tutti i provider.

Il file di configurazione, "web.config", contiene una sezione dedicata ai provider e, attraverso il metodo Initialize(), le informazioni contenute in questa sezione vengono passate al metodo, cosi, ciascun provider le utilizza per inizializzare il proprio stato.

Modificare il SiteMapProvider

Come abbiamo detto, in ASP.NET i provider sono utilizzati per svolgere diversi compiti, nel nostro articolo prendiamo in considerazione il servizio di mappa del sito web e la relativa classe SiteMapProvider, la classe base per la gestione delle informazioni della mappa del sito disponibile in ASP.NET.

La mappa di un sito web è una struttura dati gerarchica utilizzata per definire il layout di tutte le pagine dell'applicazione e la relazione che esiste tra le pagine. Il provider di mappa del sito per default, legge i dati relativi alla mappa, da un file XML, denominato web.sitemap.

Nel nostro esempio, estendiamo il provider predefinito per ottenere un nuovo provider che recupera i dati relativi alla mappa, da un database Ms SQL Server anziché da un file XML e, infine, testeremo il provider.

Le classi derivate dalla classe base del provider SiteMapProvider dovranno creare un albero di oggetti nodo della mappa del sito.

Ciascun nodo contiene:

  • nome
  • url
  • un genitore
  • un elenco dei nodi figli
  • i ruoli

XmlSiteMapProvider è il Provider predefinito per la classe SiteMap.

Questo provider deriva dalla classe astratta StaticSiteMapProvider la cui classe base è la classe SiteMapProvider.

XmlSiteMapProvider

Listato 1. Le informazioni relative ai provider, nel web.config

<siteMap>
  <providers>
    <add name="XmlSiteMapProvider " siteMapFile="web.sitemap"
      type="System.Web.XmlSiteMapProvider" />
  </providers>
</siteMap>

Passiamo, ora, alla creazione del provider personalizzato che recupera i dati relativi alle mappe dei siti da un database Ms SQL Server.

Supponiamo di avere una tabella contenuta in un database SQL Server denominata SiteMap, ogni record della tabella rappresenta un nodo della mappa del sito. Per semplicità utilizziamo una sola tabella, contenente tre campi: Title, Url, Roles.

Figura 2. La tabella SiteMap in SQL Server
La tabella SiteMap in SQL Server

Creiamo una classe di provider di mappe dei siti personalizzati denominata MySiteMapProvider, che consente di creare la mappa di un sito dai record memorizzati nella tabella SiteMap del database.

Apriamo la finestra "Esplora Soluzioni" utilizzando Visual Studio o VWD e aggiungiamo un nuovo elemento nella cartella "App_Code". Nella finestra di dialogo "Aggiungi nuovo elemento" selezioniamo Class come tipo di modello e nominiamo la classe "MySiteMapProvider.cs".

Figura 3. Aggiungere la classe al progetto
Aggiungere la classe al progetto

Importiamo nella nuova classe i namespaces che ci occorono.

Listato 2. I namespace

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Data.SqlClient;
using System.Collections.Specialized;

Nella dichiarazione della classe dobbiamo specificare che MySiteMapProvider deriva da System.Web.StaticSiteMapProvider.

Listato 3. Dichiarazione della classe

public class MySiteMapProvider : StaticSiteMapProvider

Aggiungiamo alcuni campi privati

.

Listato 4. I campi privati

public class MySiteMapProvider : StaticSiteMapProvider
{
  static readonly string errore = "Manca la stringa di connessione";
  private string strconn = null;
  private SiteMapNode root = null;

Eseguiamo, ora l'override del metodo Initialize(). Questo metodo inizializza le strutture dati da cui vengono prese le informazioni per la creazione della struttura del provider.

Listato 5. L'override del metodo Initialize

  public override void Initialize (string name, NameValueCollection attributes)
  {
    base.Initialize (name, attributes);
    if (attributes == null)
      throw new ConfigurationException (errore);
    
    strconn = attributes["connectionStringName"];
    
    if (String.IsNullOrEmpty(strconn))
      throw new ConfigurationException (errore);
  }

Aggiungiamo alla classe il metodo BuildSiteMap() di cui eseguiamo l'override. Questo metodo carica le informazioni per la Site Map dal database scelto.

Listato 6. Il Metodo BuildSiteMap

  public override SiteMapNode BuildSiteMap ()
  {
    // Esco dal metodo se è stato già richiamato e il nodo root non è nullo
    if (root != null)
      return root;
  
    // Creo il nodo root
    root = new SiteMapNode (this, "Default.aspx", "Default.aspx", "Home");
    AddNode(root, null);

    // Eseguo la query per leggere i dati necessari per creare i nodi figli
    SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["miaconn"].ConnectionString);

    try {
      connection.Open ();
      SqlCommand command = new SqlCommand("SELECT Title, Url, Roles FROM SiteMap", connection);
      SqlDataReader reader = command.ExecuteReader ();
      
      int url = reader.GetOrdinal("Url");
      int title = reader.GetOrdinal("Title");
      int roles = reader.GetOrdinal("Roles");
      
      // Aggiungo i nodi alla mappa del sito
      while (reader.Read ()) {
        SiteMapNode node = new SiteMapNode (this, reader.GetString(url), reader.GetString(url), reader.GetString(title));
        
        if (!reader.IsDBNull (roles)) {
          string rolenames = reader.GetString (roles);
          
          if (!String.IsNullOrEmpty (rolenames)) {
            string[] rolelist = rolenames.Split (new char[] { ',', ';' }, 512);
            node.Roles = rolelist;
          }
        }
        AddNode (node, root);
      }
    }
    finally { connection.Close (); }
    
    return root;
  }

Aggiungiamo alla classe il metodo GetRootNodeCore(). Questo metodo restituisce il nodo principale che gestisce tutti i sotto nodi e, permette, il caricamento della struttura presente nel provider.

Listato 7. Il Metodo GetRootNode()

  protected override SiteMapNode GetRootNodeCore()
  {
    BuildSiteMap ();
    return root;
  }

Ora, per poter utilizzare il provider dobbiamo apportare delle modifiche al "web.config".Apriamo il file e ci assicuriamo di aver inserito e configurato in modo corretto la connessione al database.

Listato 8. La stringa di connessione al database

<connectionStrings>
  <add name="miaconn"
    connectionString="Data Source=.SQLEXPRESS;
        AttachDbFilename=C:progettiwww.html.itWebProvidersApp_DataDatabase.mdf;
        Integrated Security=True; User Instance=True"
        providerName="System.Data.SqlClient" />
</connectionStrings>

All'interno della sezione <system.web> del web.config, aggiungiamo il nostro provider nella sezione <siteMap> e lo impostiamo come provider di default.

Listato 8. La sezione <siteMap> all'interno del web.config

<siteMap defaultProvider="MySiteMapProvider" enabled="true">
  <providers>
    <add name="MySiteMapProvider"
          type="MySiteMapProvider" securityTrimmingEnabled="true"
          connectionStringName="Database"/>
  </providers>
</siteMap>

Passiamo ora, al test della nostra applicazione. Aggiungiamo al progetto una pagina e la chiamiamo "Default.aspx". Dalla "casella degli strumenti" trasciniamo nella pagina l'oggetto SiteMapDataSource e l'oggetto TreeView

Figura 4. Creare la pagina per il test
Creare la pagina per il test

Impostiamo quindi le proprietà dei due oggetti.

Listato 9. Le proprietà dei due oggetti

<form id="form1" runat="server">
<asp:SiteMapDataSource ID="siteMapDataSource" runat="server" />
<asp:TreeView ID="TreeView1" runat="server" DataSourceID="siteMapDataSource" />
</form>

Compiliamo ed eseguiamo l'applicazione. Apparirà la schermata con i dati della mappa del sito letti dalla tabella del database.

Figura 5. Risultato dell'esecuzione
Risultato dell'esecuzione

Conclusioni

In questo articolo abbiamo prima introdotto il modello basato sui provider e poi abbiamo visto nel dettaglio, come creare un Site Map Provider personalizzato da utilizzare come provider di default per la creazione della struttura di navigazione del nostro sito web prelevando i dati da un database Ms SQL Server.

L'esempio vuole essere un punto di partenza per sperimentare questa tecnica nella personalizzazione dei vari provider inclusi nel sistema quando questi non risultano sufficienti a soddisfare le proprie esigenze.

Ti consigliamo anche