Aangepaste configuratie-instellingen toevoegen voor een (ASP) .NET-toepassing

Sinds de release ervan hebben ASP.NET-toepassingen en componenten gekeken naar het web.config-bestand om alle instellingen te laden die ze nodig hebben om te functioneren. Het toevoegen van aangepaste instellingen om flexibiliteit en robuustheid aan een toepassing of component toe te voegen, is echter niet zo eenvoudig als de meeste zouden willen. In dit artikel leert u hoe u de noodzakelijke klassen schrijft om XML-configuratie-elementen af ​​te handelen en de instellingen te gebruiken die ze in uw code bevatten.

Opnieuw gepubliceerde zelfstudie

Om de paar weken bekijken we enkele van onze favoriete lezers uit de geschiedenis van de site. Deze tutorial werd voor het eerst gepubliceerd in november 2012.

Het .NET Framework biedt een breed scala aan instellingen die kunnen worden geconfigureerd in web.config om het gedrag van een of meer ingebouwde componenten in de toepassing te wijzigen. Voor sommige ontwikkelaars is het volstaan ​​om alleen de instellingen van het .NET Framework te volgen. Maar veel meer ontwikkelaars vinden dat ze een bredere verzameling instellingen moeten beheren - hetzij voor componenten (die ze zelf of een derde partij hebben geschreven), of gewoon een reeks waarden die ze tijdens hun toepassing gebruiken..

Met het bestand web.config kunt u aangepaste instellingen instellen met de element, maar het staat niets anders toe dan eenvoudige sleutel / waardeparen. Het volgende XML-element is een voorbeeld van een instelling die zich binnenin bevindt :

Key / Value-instellingen kunnen in veel omstandigheden zeker nuttig zijn, maar instellingen zijn eenvoudigweg niet flexibel genoeg voor robuuste of complexe componenten of instellingen.

Gelukkig stelt Microsoft ontwikkelaars in staat klassen te schrijven die programmatische toegang tot aangepaste configuratie-instellingen binnen web.config toevoegen.


De configuratiesectie

Instellingen binnen web.config worden gecategoriseerd in configuratiesecties. Bijvoorbeeld de instellingen in de sectie heeft betrekking op ASP.NET-instellingen voor uw toepassing. U kunt het authenticatieschema van uw app wijzigen en HTTP-handlers toevoegen of verwijderen om specifieke functies voor specifieke bestandstypen uit te voeren. De In dit gedeelte kunt u veel van de instellingen van IIS7 beheren zonder rechtstreeks toegang te hebben tot IIS7.

Een configuratiesectie is vereist voor alle instellingen die niet zijn opgenomen in de element. Het is dus een goed idee om de XML-structuur van uw configuratie-instellingen te ontwerpen voordat u een code schrijft.

De configuratie die als voorbeeld wordt gebruikt in deze zelfstudie, is voor een component die RSS- of Atom-feeds ophaalt. Er wordt niet geparseerd, omdat dit buiten het bestek van deze zelfstudie valt. In plaats van het hard coderen van de lijst met feeds die moeten worden opgehaald, kijkt de component naar de configuratie ervan met de namen en URL's van de feeds die moeten worden opgehaald. Het onderdeel heet FeedRetriever en de gewenste XML-structuur van de configuratie ziet er als volgt uit:

      

De element wordt gedefinieerd door de configuratiesectie. Over het algemeen moet een configuratiesectie de naam delen van de component waarvoor deze is ontworpen. De elementen alleen kind is het element. Beschouw dit element als een verzameling feeds omdat het meerdere bevat elementen (denk aan de methode Add () die de meeste verzameling-objecten hebben). De keuze om een ​​element met de naam "toevoegen" te gebruiken, lijkt in eerste instantie misschien vreemd, maar de element wordt gebruikt in de meeste ingebouwde configuratiesecties. Dus het hier gebruiken volgt eenvoudigweg de ontwerppraktijken van Microsoft.

Deze elementen gebruiken de kenmerken name, url en cache om bepaalde instellingen voor elke feed in te stellen. Natuurlijk zijn de kenmerken name en url vereist, maar het cache-attribuut is dat niet, en zou standaard als waar moeten zijn.

De bovenstaande configuratie is eenvoudig. De element kan worden gewijzigd om een ​​ander kind te bevatten, genaamd , om instellingen te bevatten die op alle feeds van toepassing zouden zijn. De elementen kunnen ook gebruikmaken van extra kenmerken, zoals cacheTime en requestFrequency, om te bepalen hoelang een feed in de cache wordt opgeslagen en hoe vaak deze wordt opgevraagd bij de externe host. De enige beperking tot de uitbreidbaarheid en configureerbaarheid is uw verbeelding.


De configuratiehandler schrijven

Na het ontwerpen van de XML-structuur, is de volgende stap het schrijven van een configuratiehandler voor het verwerken van de instellingen die in de XML zijn gedefinieerd. De handler is primair een klasse die overerft van System.Configuration.ConfigurationSection, maar deze bevat ook het gebruik van andere klassen - zoals klassen die zijn afgeleid van System.Configuration.ConfigurationElement en System.Configuration.ConfigurationElementCollection.

Klassen op basis van ConfigurationElement vertegenwoordigen individuele elementen; het is de bouwsteen van een configuratiesectie. Typen die afkomstig zijn van ConfigurationElementCollection vertegenwoordigen eenvoudig elementen die meer dan één type element bevatten. Uit de bovenstaande configuratie, de element wordt vertegenwoordigd door een klasse die is afgeleid van ConfigurationElementCollection en de elementen worden vertegenwoordigd door een op ConfigurationElement gebaseerde klasse.


Vertegenwoordigen van de Element

Je begint met de element door het te presenteren met een klasse genaamd FeedElement (afgeleid van ConfigurationElement). Deze klasse- en toekomstige configuratie-gerelateerde klassen bevinden zich in de FeedRetriever.Configuration-naamruimte.

Elk ConfigurationElement-object functioneert als een index voor de interne verzameling van eigenschapswaarden. Het is deze interne verzameling, samen met .NET-kenmerken, waarmee u de kaart kunt toewijzen elementattributen voor de eigenschappen van de klasse FeedElement.

De volgende code is de volledige code voor de klasse FeedElement:

public class FeedElement: ConfigurationElement [ConfigurationProperty ("name", IsKey = true, IsRequired = true)] public string Name get return (string) this ["name"];  stel this ["name"] = waarde in;  [ConfigurationProperty ("url", IsRequired = true, DefaultValue = "http: // localhost")] [RegexStringValidator (@ "https? \: // \ S +")] public string Url krijg return (string) deze [ "url"];  stel this ["url"] = waarde in;  [ConfigurationProperty ("cache", IsRequired = false, DefaultValue = true)] public bool Cache get return (bool) this ["cache"];  stel this ["cache"] = waarde in; 

De ConfigurationElement-klasse dient als een indexering voor een onderliggende verzameling configuratie-eigenschappen (vandaar de indexeringsnotatie van deze [keyValue]). Door dit sleutelwoord te gebruiken en toegang te krijgen tot de onderliggende eigenschap met een tekenreekscode, kunt u de waarde van de eigenschap ophalen en instellen zonder dat een privéveld die gegevens bevat. De onderliggende eigenschappenverzameling slaat gegevens op als type Object; daarom moet je de waarde uitbrengen als het juiste type als je er iets mee wilt doen.

De eigenschappen die XML-attributen vertegenwoordigen, zijn versierd met ConfigurationPropertyAttribute-kenmerken. De eerste parameter van het kenmerk ConfigurationPropertyAttribute is de naam van het XML-kenmerk dat wordt gevonden in de element. De eerste parameter volgen is een reeks van elk aantal benoemde parameters. De volgende lijst is een volledige lijst van mogelijke parameters:

  • DefaultValue - Hiermee wordt de standaardwaarde voor de ingerichte eigenschap opgehaald of ingesteld. Deze parameter
    is niet nodig.
  • IsDefaultCollection - Hiermee wordt een Booleaanse waarde opgehaald of ingesteld die aangeeft of de eigenschap
    is de standaardbezitverzameling voor de ingerichte eigenschap. Deze parameter is
    niet vereist en de standaardwaarde is false.
  • IsKey - Hiermee wordt een Booleaanse waarde opgehaald of ingesteld die aangeeft of deze eigenschap een sleuteleigenschap is
    voor de ingerichte elementeigenschap. Deze parameter is niet vereist en is de standaardinstelling
    waarde is fout.
  • IsRequired - Hiermee wordt een Booleaanse waarde opgehaald of ingesteld die aangeeft of het gedecoreerde element is
    eigendom is verplicht. Deze parameter is niet vereist en de standaardwaarde is false.

De standaardwaarde van "http: // localhost" voor de eigenschap Url is geen fout. Het .NET Framework biedt u ook de mogelijkheid om de eigenschappen te verfraaien met validatorattributen, zoals het RegexStringValidatorAttribute dat de eigenschap Url verfraait. Deze validator neemt de waarde van de eigenschap Url en valideert deze met de reguliere expressie die aan het kenmerk wordt verstrekt; het valideert echter ook de eigenschap Url voordat deze de gegevens uit het XML-element bevat. De standaardwaarde van de eigenschap Url is een lege tekenreeks wanneer een FeedElement-object voor het eerst wordt gemaakt. Een lege tekenreeks valideert niet met de opgegeven reguliere expressie, dus de validator genereert een ArgumentException voordat gegevens worden geladen vanuit het XML-bestand.

Er zijn twee mogelijke oplossingen voor dit probleem. De eerste benadering wijzigt de reguliere expressie om lege tekenreeksen toe te staan. De tweede benadering wijst een standaardwaarde toe aan de eigenschap. Het maakt in dit specifieke geval niet uit. Zelfs met een standaardwaarde is het kenmerk url nog steeds een vereist kenmerk in de element - de toepassing genereert een ConfigurationErrorsException als een element heeft geen url-kenmerk.

Er zijn verschillende andere validatorattributen in de namespace System.Configuration om gegevens te valideren die zijn toegewezen aan eigenschappen en de XML-kenmerken waarnaar ze verwijzen. Hieronder worden alle validatorattributen weergegeven in de naamruimte System.Configuration:

  • CallbackValidatorAttribute - Geeft een koppeling tussen een CallbackValidator-object en de te valideren code - staat toe
    dynamische validatie voor een configuratiewaarde.
  • IntegerValidatorAttribute - Valideert met een IntegerValidator-object om te bepalen of de configuratiewaarde binnen of buiten een specifiek bereik valt.
  • LongValidatorAttribute - Valideert met een object LongValidator om te bepalen of de configuratiewaarde binnen of buiten een specifiek bereik valt.
  • PositiveTimeSpanValidatorAttribute - Valideert met een PositiveTimeSpanValidator-object voor positieve TimeSpan-configuratiewaarden.
  • RegexStringValidatorAttribute - Valideert met een RegexStringValidator-object om te bepalen of de configuratiewaarde overeenkomt met de reguliere expressie.
  • StringValidatorAttribute - Valideert met een StringValidator-object om ervoor te zorgen dat de configuratiewaarde voldoet aan bepaalde criteria, zoals tekenreekslengte en ongeldige tekens.
  • SubclassTypeValidatorAttribute - Valideert met een SubclassTypeValidator-object om te bepalen of de configuratiewaarde is afgeleid van een bepaald type.
  • TimeSpanValidatorAttribute - Valideert met een TimeSpanValidator-object om te bepalen of de configuratiewaarde valt binnen of buiten een specifiek bereik.

Met uitzondering van het CallbackValidatorAttribute, hoeft u geen bijbehorende validatorobjecten te maken voor gebruik in combinatie met de validatorattributen. De runtime van .NET maakt de juiste validatorobjecten voor u en de kenmerken bevatten de benodigde parameters om de validatorobjecten te configureren.

Dit kleine stukje code is alles wat nodig is om een ​​individu programmatisch te vertegenwoordigen elementen. De volgende stap is om een ​​klasse te schrijven die de element.


Een Element Collection Class schrijven

De XML-weergave van de element is dat van een verzameling feedelementen. Evenzo is de programmatische weergave van de element is een verzameling FeedElement-objecten. Deze klasse, genaamd FeedElementCollection, is afgeleid van de abstracte klasse ConfigurationElementCollection.

De klasse ConfigurationElementCollection bevat verschillende leden, maar slechts twee zijn gemarkeerd als abstract. De eenvoudigste implementatie ConfigurationElementCollection heeft dus twee methoden:

  • CreateNewElement () - Maakt een nieuw ConfigurationElement-object (FeedElement hierin
    geval).
  • GetElementKey (): haalt de elementcode voor een opgegeven configuratie-element (de
    Naam eigenschap van FeedElement-objecten in dit geval).

Bekijk met dat in gedachten de volledige code voor de klasse FeedElementCollection hieronder:

[ConfigurationCollection (typeof (FeedElement))] public class FeedElementCollection: ConfigurationElementCollection protected override ConfigurationElement CreateNewElement () return new FeedElement ();  beveiligd override-object GetElementKey (element ConfigurationElement) return ((FeedElement) -element) .Name; 

Een ConfigurationCollectionAttribute siert deze collectieklasse. De eerste parameter voor het kenmerk is een Type-object - het type items dat de verzameling bevat. In dit geval is dit het FeedElement-type. Nadat de parameter type verschillende parameters heeft gekregen, kunt u deze doorgeven aan het kenmerk. Deze staan ​​hieronder vermeld:

  • AddItemName - Stelt de naam in van de configuratie element. Bijvoorbeeld,
    om dit als "feed" in te stellen zou de elementen in de
    configuratie moet worden gewijzigd in .
  • ClearItemsName - Stelt de naam in van de configuratie-element (gebruikt
    om alle items uit de verzameling te verwijderen).
  • RemoveItemName - Stelt de naam in voor de configuratie-element (gebruikt
    om een ​​item uit de verzameling te verwijderen).

Als je deze parameters wit laat, worden ze standaard ingesteld , , .


De FeedRetreiverSection Class schrijven

De laatste klasse, genaamd FeedRetrieverSection, is afgeleid van ConfigurationSection en vertegenwoordigt de element. Dit is de eenvoudigste klasse van de configuratieklassen, omdat de enige vereiste waaraan moet worden voldaan, is om programmatische toegang te bieden tot de element (de FeedElementCollection).

public class FeedRetrieverSection: ConfigurationSection [ConfigurationProperty ("feeds", IsDefaultCollection = true)] public FeedElementCollection Feeds krijg return (FeedElementCollection) this ["feeds"];  stel this ["feeds"] = waarde in; 

Het is één eigenschap, van het type FeedElementCollection en genaamd Feeds, is versierd met een ConfigurationPropertyAttribute - het toewijzen aan de element.


Web.config aanpassen

Als de configuratiehandler is voltooid, kunt u de juiste elementen toevoegen aan web.config. De sectie kan overal in het bestand gaan zolang het een directe afstammeling is van het rootelement (de element). Plaatsing binnen een ander configuratiegedeelte resulteert in een fout.

De volgende stap is het toevoegen van een

onderliggende element . De
element heeft twee interessante kenmerken:

  • name - De naam van het configuratiesectie-element. In dit geval is de naam feedRetriever.
  • type - De gekwalificeerde naam van de klasse die bij de sectie hoort en indien nodig,
    de naam van de assembly waarin de klasse zich bevindt. In dit geval de gekwalificeerde naam
    is FeedRetriever.Configuration.FeedRetrieverSection. Als het zich in een afzonderlijke bevindt
    assembly, heeft het typekenmerk de waarde "FeedRetriever.Configuration.FeedRetrieverSection,
    ", waar is de naam van de assembly
    zonder de hoekbeugels.

Het volgende

element is wat u toevoegt aan een web.config-bestand, onder , wanneer de configuratieklassen zich niet in een afzonderlijke assembly bevinden (zoals het geval is bij het downloaden van de code):

Uw toepassing is nu correct geconfigureerd om de klassen FeedRetrieverSection, FeedElementCollection en FeedElement te gebruiken om u programmatische toegang te verlenen tot de aangepaste instellingen in de configuratiesectie in web.config. Dus hoe krijg je toegang tot deze instellingen vanuit je code?


Toegang krijgen tot configuratiegegevens vanuit de code

De namespace System.Configuration bevat een statische klasse met de naam ConfigurationManager. Als u de sectie om uw verbindingsstrings te huisvesten, bent u op zijn minst vertrouwd met ConfigurationManager. Het heeft een methode genaamd GetSection (), die een string accepteert die de naam bevat van de configuratiesectie die moet worden opgehaald. De volgende code demonstreert dit (neem aan dat System.Configuration bovenaan het codebestand staat):

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

De methode GetSection () retourneert een waarde van het type Object, dus deze moet worden gegoten in het type van de handler voor die sectie. Deze code haalt de sectie genaamd feedRetriever op en cast het resultaat als FeedRetrieverSection. Zodra u het object hebt, kunt u programmatisch toegang krijgen tot configuratiegegevens.

Om u een idee te geven van hoe configuratie-instellingen binnen uw component of applicatie kunnen worden gebruikt, is de volgende code een zeer eenvoudige implementatie van de FeedRetriever-component.

public class FeedRetriever public static FeedRetrieverSection _Config = ConfigurationManager.GetSection ("feedRetriever") als FeedRetrieverSection;
public static void GetFeeds () foreach (FeedElement feedEl in _Config.Feeds) // aanvraag 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) // bestandsnaam van cachebestandstring bestandsnaam = String.Format ("0 _ 1 .xml", feedEl.Name, DateTime.Now.Ticks); // cachebestand met (StreamWriter writer = new StreamWriter (@ "C: \" + bestandsnaam)) writer.Write (feedData);

Eerst wordt een statische variabele genaamd _Config, van het type FeedRetreiverSection, gedeclareerd en een waarde toegekend door ConfigurationManager.GetSection () aan te roepen. De variabele statisch maken is een ontwerpkeuze. Door dit te doen, zouden alle leden van de klasse, ofwel instantie of statisch, toegang hebben tot de configuratie-instellingen zonder meerdere aanroepen te hoeven doen naar GetSection ().

Nadat u de sectie-afhandelaar met GetSection () hebt opgehaald, hebt u volledige toegang tot objecten die zijn gemaakt met uw handlerklassen. De eerste regel GetFeeds () is een voor elke lus die alle FeedElement-objecten doorzoekt die zich bevinden in het FeedElementCollection-object dat wordt geretourneerd door de eigenschap Feeds. Dit geeft u directe toegang tot die FeedElement-objecten - waardoor u eenvoudig toegang hebt tot de naam, URL en cache-instellingen van elke feed.

Tijdens elke iteratie van de lus maakt de methode een aanvraag met de URL-eigenschap van het FeedElement-object. Als het verzoek tot een succes leidt, worden de gegevens van de feed opgehaald en opgeslagen in de feedData-variabele. Vervolgens controleert de code de eigenschap Cache van het FeedElement-object om te bepalen of de feed wel of niet in de cache wordt geplaatst. Bij het cachen van de feed wordt een bestandsnaam geconstrueerd met behulp van de eigenschap Name van het FeedElement-object en de huidige datum en tijd. Vervolgens maakt een StreamWriter-object het bestand en schrijft de feedgegevens ernaar toe.

Zoals je kunt zien, is het gebruik van de handlersklassen in de configuratiesectie de sleutel om aangepaste instellingen op te halen en te gebruiken die zich bevinden in web.config. Het vereist zeker meer tijd en moeite van je, maar het maakt je applicatie of component zeker gemakkelijker om te configureren voor jezelf en andere ontwikkelaars.


Verkoop uw .NET-componenten op CodeCanyon!



Wist u dat we een .NET-categorie hebben op CodeCanyon. Als u een bekwame .NET-ontwikkelaar bent, waarom verkoopt u uw scripts / componenten / besturingselementen dan niet als auteur en verdient u 40-70% van elke verkoop?

  • Volg ons op Twitter of abonneer je op de Nettuts + RSS Feed voor de beste tutorials voor webontwikkeling op internet.