Come aggiungere impostazioni di configurazione personalizzate per un'applicazione (ASP) .NET

Dalla sua versione, le applicazioni ei componenti ASP.NET hanno cercato nel file web.config di caricare qualsiasi impostazione di cui hanno bisogno per funzionare. Tuttavia, l'aggiunta di impostazioni personalizzate per aggiungere flessibilità e robustezza a un'applicazione oa un componente non è così semplice come la maggior parte vorrebbe. Questo articolo ti insegna come scrivere le classi necessarie per gestire gli elementi di configurazione XML e utilizzare le impostazioni che contengono all'interno del tuo codice.

Tutorial ripubblicato

Ogni poche settimane, rivisitiamo alcuni dei post preferiti del nostro lettore da tutta la cronologia del sito. Questo tutorial è stato pubblicato per la prima volta nel novembre 2012.

.NET Framework offre un'ampia varietà di impostazioni che possono essere configurate in web.config per modificare il comportamento di uno o più componenti incorporati all'interno dell'applicazione. Per alcuni sviluppatori è sufficiente attenersi esclusivamente alle impostazioni fornite da .NET Framework. Ma molti più sviluppatori scoprono di aver bisogno di controllare una più ampia raccolta di impostazioni - sia per componenti (scritti da loro stessi o di terze parti), sia semplicemente per un insieme di valori che si trovano a utilizzare durante l'applicazione.

Il file web.config ti consente di impostare le impostazioni personalizzate con elemento, ma non consente altro che semplici coppie chiave / valore. Il seguente elemento XML è un esempio di un'impostazione contenuta all'interno :

Le impostazioni chiave / valore possono sicuramente essere utili in molte circostanze, ma le impostazioni semplicemente non sono abbastanza flessibili per componenti o impostazioni robusti o complessi.

Fortunatamente, Microsoft consente agli sviluppatori di scrivere classi che aggiungono l'accesso programmatico alle impostazioni di configurazione personalizzate contenute in web.config.


La sezione di configurazione

Le impostazioni all'interno di web.config sono classificate in sezioni di configurazione. Ad esempio, le impostazioni contenute all'interno di la sezione riguarda le impostazioni ASP.NET per la tua applicazione. È possibile modificare lo schema di autenticazione della propria app, nonché aggiungere o rimuovere gestori HTTP per eseguire funzioni specifiche per tipi di file specifici. Il sezione ti permette di controllare molte delle impostazioni di IIS7 senza avere accesso diretto a IIS7.

È richiesta una sezione di configurazione di tutte le impostazioni non contenute nel elemento. Quindi è una buona idea progettare la struttura XML delle impostazioni di configurazione prima di scrivere qualsiasi codice.

La configurazione utilizzata come esempio in questo tutorial è per un componente che recupera feed RSS o Atom. Non fa alcuna analisi, poiché questo esula dallo scopo di questo tutorial. Invece di codificare in modo rigido l'elenco dei feed da recuperare, il componente guarda alla sua configurazione per contenere i nomi e gli URL dei feed da recuperare. Il componente si chiama FeedRetriever e la struttura XML desiderata della sua configurazione è la seguente:

      

Il elemento definisce dalla sezione di configurazione. Come regola generale, una sezione di configurazione dovrebbe condividere il nome del componente per cui è stata progettata. Il elementi solo figlio è il elemento. Pensa a questo elemento come a una raccolta di feed perché contiene diversi elementi elementi (si pensi al metodo Add () che ha la maggior parte degli oggetti di raccolta). La scelta di usare un elemento chiamato "add" può sembrare strano all'inizio, ma il l'elemento è utilizzato nella maggior parte delle sezioni di configurazione integrate. Quindi usarlo qui segue semplicemente le pratiche di progettazione avanzate da Microsoft.

Questi gli elementi utilizzano gli attributi name, url e cache per impostare determinate impostazioni per ogni feed. Naturalmente, gli attributi name e url sono obbligatori, ma l'attributo cache non lo è e dovrebbe essere impostato come true.

La configurazione di cui sopra è semplice. Il l'elemento potrebbe essere modificato per contenere un altro bambino, chiamato , per contenere le impostazioni che si applicano a tutti i feed. Il gli elementi potrebbero anche utilizzare attributi aggiuntivi, come cacheTime e requestFrequency, per controllare per quanto tempo un feed viene memorizzato nella cache e quanto spesso viene richiesto dall'host remoto. L'unico limite all'estensibilità e alla configurabilità è la tua immaginazione.


Scrivere il gestore di configurazione

Dopo aver progettato la struttura XML, il passo successivo è scrivere un gestore di configurazione per elaborare le impostazioni definite nell'XML. Il gestore è principalmente una classe che eredita da System.Configuration.ConfigurationSection, ma incorpora anche l'uso di altre classi, ad esempio classi derivate da System.Configuration.ConfigurationElement e System.Configuration.ConfigurationElementCollection.

Le classi basate su ConfigurationElement rappresentano singoli elementi; è il blocco di base di una sezione di configurazione. I tipi che derivano da ConfigurationElementCollection rappresentano semplicemente gli elementi che contengono più di un tipo di elemento. Dalla configurazione sopra elencata, il elemento è rappresentato da una classe che deriva da ConfigurationElementCollection e il gli elementi sono rappresentati da una classe basata su ConfigurationElement.


Rappresentare il Elemento

Inizierai con il elemento rappresentandolo con una classe chiamata FeedElement (derivata da ConfigurationElement). Questa classe e le future classi relative alla configurazione risiedono nello spazio dei nomi FeedRetriever.Configuration.

Ogni oggetto ConfigurationElement funziona come un indicizzatore per la sua raccolta interna di valori di proprietà. È questa raccolta interna, insieme agli attributi .NET, che ti consente di mappare il file attributi dell'elemento alle proprietà della classe FeedElement.

Il seguente codice è il codice completo per la classe FeedElement:

public class FeedElement: ConfigurationElement [ConfigurationProperty ("name", IsKey = true, IsRequired = true)] public string Nome get return (string) this ["name"];  set this ["nome"] = valore;  [ConfigurationProperty ("url", IsRequired = true, DefaultValue = "http: // localhost")] [RegexStringValidator (@ "https? \: // \ S +")] public string Url get return (string) questo [ "url"];  set this ["url"] = valore;  [ConfigurationProperty ("cache", IsRequired = false, DefaultValue = true)] public bool Cache get return (bool) this ["cache"];  set this ["cache"] = valore; 

La classe ConfigurationElement funge da indicizzatore di una raccolta sottostante di proprietà di configurazione (da cui la notazione dell'indicizzatore di questo [keyValue]). Utilizzando la parola chiave this e accedendo alla proprietà sottostante con una chiave stringa, è possibile ottenere e impostare il valore della proprietà senza che sia necessario un campo privato per contenere tali dati. La raccolta di proprietà sottostante memorizza i dati come tipo Object; pertanto, devi castare il valore come tipo appropriato se vuoi fare qualcosa con esso.

Le proprietà che rappresentano gli attributi XML sono decorate con gli attributi ConfigurationPropertyAttribute. Il primo parametro dell'attributo ConfigurationPropertyAttribute è il nome dell'attributo XML trovato all'interno di elemento. Seguendo il primo parametro è un insieme di un numero qualsiasi di parametri con nome. Il seguente elenco è un elenco completo di parametri possibili:

  • DefaultValue - Ottiene o imposta il valore predefinito per la proprietà decorata. Questo parametro
    non è richiesto.
  • IsDefaultCollection - Ottiene o imposta un valore booleano che indica se la proprietà
    è la raccolta di proprietà predefinita per la proprietà decorata. Questo parametro è
    non richiesto e il valore predefinito è falso.
  • IsKey - Ottiene o imposta un valore booleano che indica se questa proprietà è una proprietà chiave
    per la proprietà dell'elemento decorato. Questo parametro non è richiesto e il suo valore predefinito
    il valore è falso.
  • IsRequired - Ottiene o imposta un valore booleano che indica se l'elemento decorato
    la proprietà è richiesta Questo parametro non è richiesto e il suo valore predefinito è falso.

Il valore predefinito di "http: // localhost" per la proprietà Url non è un errore. .NET Framework consente inoltre di decorare le proprietà con attributi di validatore, ad esempio RegexStringValidatorAttribute che decora la proprietà Url. Questo validatore prende il valore della proprietà Url e lo convalida rispetto all'espressione regolare fornita all'attributo; tuttavia, convalida anche la proprietà Url prima che contenga i dati dall'elemento XML. Il valore predefinito della proprietà Url è una stringa vuota quando viene creato per la prima volta un oggetto FeedElement. Una stringa vuota non si convalida con l'espressione regolare fornita, quindi il validatore lancia un'eccezione ArgumentException prima che qualsiasi dato venga caricato dal file XML.

Esistono due possibili soluzioni per questo problema. Il primo approccio modifica l'espressione regolare per consentire stringhe vuote. Il secondo approccio assegna un valore predefinito alla proprietà. Non importa in questo caso particolare. Anche con un valore predefinito, l'attributo url è ancora un attributo obbligatorio nel file element - l'applicazione lancia una ConfigurationErrorsException se un l'elemento non ha un attributo url.

Ci sono molti altri attributi di validatore nello spazio dei nomi System.Configuration per convalidare i dati assegnati alle proprietà e gli attributi XML a cui mappano. Di seguito sono elencati tutti gli attributi del validatore all'interno dello spazio dei nomi System.Configuration:

  • CallbackValidatorAttribute - Fornisce un'associazione tra un oggetto CallbackValidator e il codice da convalidare - consente
    validazione dinamica per un valore di configurazione.
  • IntegerValidatorAttribute - Valida usando un oggetto IntegerValidator per determinare se il valore di configurazione rientra o non rientra in un intervallo specifico.
  • LongValidatorAttribute: convalida l'utilizzo di un oggetto LongValidator per determinare se il valore di configurazione si trova all'interno o all'esterno di un intervallo specifico.
  • PositiveTimeSpanValidatorAttribute - Valida usando un oggetto PositiveTimeSpanValidator per valori di configurazione TimeSpan positivi.
  • RegexStringValidatorAttribute - Valida usando un oggetto RegexStringValidator per determinare se il valore di configurazione aderisce all'espressione regolare.
  • StringValidatorAttribute: convalida utilizzando un oggetto StringValidator per garantire che il valore di configurazione soddisfi determinati criteri, quali lunghezza della stringa e caratteri non validi.
  • SubclassTypeValidatorAttribute - Valida usando un oggetto SubclassTypeValidator per determinare se il valore di configurazione deriva da un determinato tipo.
  • TimeSpanValidatorAttribute: convalida utilizzando un oggetto TimeSpanValidator per determinare se il valore di configurazione si trova all'interno o all'esterno di un intervallo specifico.

Ad eccezione di CallbackValidatorAttribute, non è necessario creare oggetti di validazione corrispondenti da utilizzare insieme agli attributi del validatore. Il runtime .NET crea gli oggetti validator appropriati per te e gli attributi contengono i parametri necessari per configurare gli oggetti validator.

Questo piccolo pezzetto di codice è tutto ciò che è necessario per rappresentare a livello di singolo individuo elementi. Il prossimo passo è scrivere una classe che rappresenti il elemento.


Scrivere una classe di raccolta di elementi

La rappresentazione XML del elemento è quello di una raccolta di elementi di feed. Allo stesso modo, la rappresentazione programmatica del elemento è una raccolta di oggetti FeedElement. Questa classe, chiamata FeedElementCollection, deriva dalla classe abstract ConfigurationElementCollection.

La classe ConfigurationElementCollection contiene diversi membri, ma solo due sono contrassegnati come astratti. Pertanto, l'implementazione di ConfigurationElementCollection più semplice ha due metodi:

  • CreateNewElement () - Crea un nuovo oggetto ConfigurationElement (FeedElement in questo
    Astuccio).
  • GetElementKey () - Ottiene la chiave dell'elemento per un elemento di configurazione specificato (il
    Nome proprietà degli oggetti FeedElement in questo caso).

Con questo in mente, visualizza il codice completo per la classe FeedElementCollection di seguito:

[ConfigurationCollection (typeof (FeedElement))] public class FeedElementCollection: ConfigurationElementCollection override protetto ConfigurationElement CreateNewElement () return new FeedElement ();  oggetto override protetto GetElementKey (elemento ConfigurationElement) return ((FeedElement) element) .Name; 

Un ConfigurationCollectionAttribute decora questa classe di raccolta. Il primo parametro dell'attributo è un oggetto Type: il tipo di elementi che contiene la raccolta. In questo caso, è il tipo di FeedElement. Dopo che il parametro type è composto da più parametri con nome, puoi passare all'attributo. Questi sono elencati di seguito:

  • AddItemName - Imposta il nome del elemento di configurazione. Per esempio,
    impostandolo come "feed" richiederebbe il elementi nel
    configurazione da modificare in .
  • ClearItemsName - Imposta il nome del elemento di configurazione (usato
    per cancellare tutti gli elementi dalla raccolta).
  • RemoveItemName - Imposta il nome per elemento di configurazione (usato
    rimuovere un oggetto dalla raccolta).

Lasciando questi parametri denominati in bianco, li imposteranno automaticamente , , .


Scrivere la classe FeedRetreiverSection

La classe finale, chiamata FeedRetrieverSection, deriva da ConfigurationSection e rappresenta il elemento. Questa è la classe più semplice delle classi di configurazione, poiché l'unico requisito che deve soddisfare è fornire accesso programmatico a elemento (il FeedElementCollection).

public class FeedRetrieverSection: ConfigurationSection [ConfigurationProperty ("feeds, IsDefaultCollection = true)] feed pubblici FeedElementCollection get return (FeedElementCollection) this [" feeds "];  set this ["feeds"] = valore; 

È una proprietà, di tipo FeedElementCollection e chiamata Feeds, è decorata con un ConfigurationPropertyAttribute - mappandola al elemento.


Modifica di web.config

Completato il gestore di configurazione, è possibile aggiungere gli elementi appropriati a web.config. Il sezione può andare ovunque nel file fintanto che è un discendente diretto dell'elemento root (il elemento). Inserendolo in un'altra sezione di configurazione si genera un errore.

Il prossimo passo è l'aggiunta di a

elemento figlio a . Il
l'elemento ha due attributi di interesse:

  • nome: il nome dell'elemento della sezione di configurazione. In questo caso, il nome è feedRetriever.
  • type: il nome qualificato della classe associata alla sezione e, se necessario,
    il nome dell'assembly in cui risiede la classe. In questo caso, il nome qualificato
    è FeedRetriever.Configuration.FeedRetrieverSection. Se risiede in un separato
    assembly, l'attributo type avrebbe un valore di "FeedRetriever.Configuration.FeedRetrieverSection,
    ", dove è il nome dell'assemblea
    senza le parentesi angolari.

Il seguente

elemento è ciò che si aggiunge a un file web.config, sotto , quando le classi di configurazione non risiedono in un assembly separato (come nel caso del download del codice):

Ora l'applicazione è configurata correttamente per utilizzare le classi FeedRetrieverSection, FeedElementCollection e FeedElement per garantire l'accesso programmatico alle impostazioni personalizzate contenute nel sezione di configurazione in web.config. Quindi, come accedi a queste impostazioni dal tuo codice?


Accesso ai dati di configurazione dal codice

Lo spazio dei nomi System.Configuration contiene una classe statica denominata ConfigurationManager. Se usi il sezione per ospitare le stringhe di connessione, hai almeno familiarità con ConfigurationManager. Ha un metodo chiamato GetSection (), che accetta una stringa contenente il nome della sezione di configurazione da recuperare. Il seguente codice lo dimostra (supponiamo che l'utilizzo di System.Configuration sia nella parte superiore del file di codice):

FeedRetrieverSection config = ConfigurationManager.GetSection ("feedRetriever") come FeedRetrieverSection;

Il metodo GetSection () restituisce un valore di tipo Object, quindi deve essere eseguito su qualsiasi tipo di gestore per quella sezione. Questo codice recupera la sezione denominata feedRetriever e trasmette il risultato come FeedRetrieverSection. Una volta ottenuto l'oggetto, è possibile iniziare l'accesso ai dati di configurazione a livello di programmazione.

Per darti un'idea di come le impostazioni di configurazione possono essere utilizzate all'interno del tuo componente o applicazione, il codice seguente è un'implementazione molto basilare del componente FeedRetriever.

public class FeedRetriever public static FeedRetrieverSection _Config = ConfigurationManager.GetSection ("feedRetriever") come FeedRetrieverSection;
pubblico static void GetFeeds () foreach (FeedElement feedEl in _Config.Feeds) // make request HttpWebRequest request = (HttpWebRequest) WebRequest.Create (feedEl.Url); HttpWebResponse response = (HttpWebResponse) request.GetResponse (); if (response.StatusCode == HttpStatusCode.OK) string feedData = String.Empty; using (StreamReader reader = new StreamReader (response.GetResponseStream ())) feedData = reader.ReadToEnd (); if (feedEl.Cache) // nomefile della cache file string filename = String.Format ("0 _ 1 .xml", feedEl.Name, DateTime.Now.Ticks); // cache file using (StreamWriter writer = new StreamWriter (@ "C: \" + filename)) writer.Write (feedData);

Innanzitutto, una variabile statica denominata _Config, di tipo FeedRetreiverSection, viene dichiarata e assegnata a un valore chiamando ConfigurationManager.GetSection (). Rendere la variabile statica è una scelta progettuale. In questo modo, tutti i membri della classe, sia di istanza che statici, avrebbero accesso alle impostazioni di configurazione senza dover effettuare più chiamate a GetSection ().

Una volta recuperato il gestore di sezioni con GetSection (), si ha accesso completo agli oggetti creati dalle classi del gestore. La prima riga di GetFeeds () è un per ogni ciclo che scorre attraverso tutti gli oggetti FeedElement contenuti nell'oggetto FeedElementCollection restituito dalla proprietà Feeds. Ciò consente l'accesso diretto a tali oggetti di FeedElement, semplificando l'accesso al nome, all'URL e alle impostazioni della cache di ciascun feed.

Durante ogni iterazione del ciclo, il metodo effettua una richiesta utilizzando la proprietà Url dell'oggetto FeedElement. Se la richiesta ha esito positivo, i dati del feed vengono recuperati e archiviati nella variabile feedData. Quindi il codice controlla la proprietà Cache dell'oggetto FeedElement per determinare se memorizzare o meno nella cache il feed. La memorizzazione nella cache del feed implica la costruzione di un nome file utilizzando la proprietà Nome dell'oggetto FeedElement e la data e l'ora correnti. Quindi un oggetto StreamWriter crea il file e scrive i dati del feed su di esso.

Come puoi vedere, l'utilizzo delle classi del gestore della sezione di configurazione è la chiave per recuperare e utilizzare le impostazioni personalizzate che risiedono in web.config. Richiede sicuramente più tempo e sforzi da parte tua, ma rende sicuramente la tua applicazione o componente molto più facile da configurare per te e per altri sviluppatori.


Vendi i tuoi componenti .NET su CodeCanyon!



Sapevi che abbiamo una categoria .NET su CodeCanyon. Se sei un esperto di .NET, perché non vendere i tuoi script / componenti / controlli come autore e guadagna il 40-70% di ogni vendita?

  • Seguici su Twitter o iscriviti al feed Nettuts + RSS per i migliori tutorial di sviluppo web sul web.