UriTemplate en UriTemplateTable
Webontwikkelaars moeten de vorm en indeling van de URI's beschrijven waarop hun services reageren. Windows Communication Foundation (WCF) heeft twee nieuwe klassen toegevoegd om ontwikkelaars controle te geven over hun URI's. UriTemplate en UriTemplateTable vormen de basis van de op URI gebaseerde verzendengine in WCF. Deze klassen kunnen ook zelfstandig worden gebruikt, zodat ontwikkelaars kunnen profiteren van sjablonen en het URI-toewijzingsmechanisme zonder een WCF-service te implementeren.
Sjablonen
Een sjabloon is een manier om een set relatieve URI's te beschrijven. In de set URI-sjablonen in de volgende tabel ziet u hoe een systeem dat verschillende typen weerinformatie ophaalt, kan worden gedefinieerd.
Gegevens | Template |
---|---|
Nationale prognoses | weer/nationaal |
Statusprognose | weer/{state} |
Stadsprognose | weer/{state}/{city} |
Activiteitsprognose | weer/{state}/{city}/{activity} |
In deze tabel wordt een set structureel vergelijkbare URI's beschreven. Elke vermelding is een URI-sjabloon. De segmenten in accolades beschrijven variabelen. De segmenten die niet in accolades worden gebruikt, beschrijven letterlijke tekenreeksen. Met de WCF-sjabloonklassen kan een ontwikkelaar een binnenkomende URI gebruiken, bijvoorbeeld '/weather/wa/seattle/cycling', en deze koppelen aan een sjabloon die deze beschrijft, '/weather/{state}/{city}/{activity}'.
UriTemplate
UriTemplate is een klasse die een URI-sjabloon inkapselt. De constructor gebruikt een tekenreeksparameter die de sjabloon definieert. Deze tekenreeks bevat de sjabloon in de indeling die in de volgende sectie wordt beschreven. De UriTemplate klasse biedt methoden waarmee u een binnenkomende URI kunt koppelen aan een sjabloon, een URI van een sjabloon kunt genereren, een verzameling variabelenamen kunt ophalen die in de sjabloon worden gebruikt, bepalen of twee sjablonen gelijkwaardig zijn en de tekenreeks van de sjabloon retourneren.
Match(Uri, Uri) gebruikt een basisadres en een kandidaat-URI en probeert de URI aan de sjabloon te koppelen. Als de overeenkomst is geslaagd, wordt er een UriTemplateMatch exemplaar geretourneerd. Het UriTemplateMatch object bevat een basis-URI, de kandidaat-URI, een naam/waardeverzameling van de queryparameters, een matrix van de relatieve padsegmenten, een verzameling namen/waarden van variabelen die overeenkomen, het UriTemplate exemplaar dat wordt gebruikt om de overeenkomst uit te voeren, een tekenreeks die een niet-overeenkomend gedeelte van de kandidaat-URI bevat (gebruikt wanneer de sjabloon een jokerteken heeft), en een object dat is gekoppeld aan de sjabloon.
Notitie
De UriTemplate klasse negeert het schema en het poortnummer bij het koppelen van een kandidaat-URI aan een sjabloon.
Er zijn twee methoden waarmee u een URI kunt genereren op basis van een sjabloon BindByName(Uri, NameValueCollection) en BindByPosition(Uri, String[]). BindByName(Uri, NameValueCollection) neemt een basisadres en een naam/waardeverzameling van parameters. Deze parameters worden vervangen door variabelen wanneer de sjabloon afhankelijk is. BindByPosition(Uri, String[]) neemt de naam/waardeparen en vervangt ze van links naar rechts.
ToString() retourneert de sjabloontekenreeks.
De PathSegmentVariableNames eigenschap bevat een verzameling van de namen van de variabelen die worden gebruikt in padsegmenten in de sjabloontekenreeks.
IsEquivalentTo(UriTemplate) neemt een UriTemplate parameter en retourneert een Booleaanse waarde die aangeeft of de twee sjablonen gelijkwaardig zijn. Zie de sectie Equivalentie van sjablonen verderop in dit onderwerp voor meer informatie.
UriTemplate is ontworpen om te werken met elk URI-schema dat voldoet aan de HTTP-URI-grammatica. Hier volgen enkele voorbeelden van ondersteunde URI-schema's.
http://
https://
net.tcp://
net.pipe://
sb://
Schema's zoals file:// en urn:// voldoen niet aan de GRAMMATICA van de HTTP-URI en veroorzaken onvoorspelbare resultaten wanneer ze worden gebruikt met URI-sjablonen.
Tekenreekssyntaxis van sjabloon
Een sjabloon heeft drie delen: een pad, een optionele query en een optioneel fragment. Zie de volgende sjabloon voor een voorbeeld:
"/weather/{state}/{city}?forecast={length)#frag1
Het pad bestaat uit '/weather/{state}/{city}', de query bestaat uit '?forecast={length}, en het fragment bestaat uit '#frag1'.
Voorloop- en volgslashes zijn optioneel in de padexpressie. Zowel de query- als fragmentexpressies kunnen volledig worden weggelaten. Een pad bestaat uit een reeks segmenten gescheiden door '/', elk segment kan een letterlijke waarde, een variabelenaam (geschreven in {accolades}) of een jokerteken (geschreven als '*') hebben. In de vorige sjabloon is het segment \weather een letterlijke waarde, terwijl {state} en {city} variabelen zijn. Variabelen nemen hun naam op uit de inhoud van hun accolades en ze kunnen later worden vervangen door een concrete waarde om een gesloten URI te maken. Het jokerteken is optioneel, maar kan alleen worden weergegeven aan het einde van de URI, waarbij het logisch overeenkomt met de rest van het pad.
Met de query-expressie, indien aanwezig, wordt een reeks niet-geordende naam-/waardeparen opgegeven, gescheiden door '&'. Elementen van de query-expressie kunnen letterlijke paren (x=2) of een variabelepaar (x={var}) zijn. Alleen de rechterkant van de query kan een variabele-expressie hebben. ({someName} = {someValue} is niet toegestaan. Niet-toegestane waarden (?x) zijn niet toegestaan. Er is geen verschil tussen een lege query-expressie en een query-expressie die bestaat uit slechts één '?' (beide betekent 'een willekeurige query').
De fragmentexpressie kan bestaan uit een letterlijke waarde, er zijn geen variabelen toegestaan.
Alle namen van sjabloonvariabelen binnen een sjabloontekenreeks moeten uniek zijn. Namen van sjabloonvariabelen zijn niet hoofdlettergevoelig.
Voorbeelden van geldige sjabloontekenreeksen:
""
"/schoen"
"/schoen/*"
"{shoe}/boot"
"{shoe}/{boat}/bed/{quilt}"
"schoen/{boot}"
"schoen/{boat}/*"
"schoen/boot?x=2"
"schoen/{boot}?x={bed}"
"schoen/{boot}?x={bed}&y=band"
"?x={shoe}"
"schoen?x=3&y={var}
Voorbeelden van ongeldige sjabloontekenreeksen:
"{shoe}/{SHOE}/x=2": dubbele variabelenamen.
"{shoe}/boat/?bed={shoe}" – Dubbele variabele namen.
"?x=2&x=3": naam/waardeparen binnen een querytekenreeks moeten uniek zijn, zelfs als het letterlijke waarden zijn.
"?x=2&": querytekenreeks is ongeldig.
"?2&x={shoe}": de queryreeks moet naam-/waardeparen zijn.
"?y=2&&&X=3": de queryreeks moet naam-waardeparen zijn, namen kunnen niet beginnen met '&'.
Samengestelde padsegmenten
Met samengestelde padsegmenten kan één URI-padsegment meerdere variabelen en variabelen in combinatie met letterlijke waarden bevatten. Hier volgen voorbeelden van geldige samengestelde padsegmenten.
/Bestandsnaam. {ext}/
/{bestandsnaam}.jpg/
/{bestandsnaam}. {ext}/
/{a}. {b}someLiteral{c}({d})/
Hier volgen voorbeelden van ongeldige padsegmenten.
/{} - Variabelen moeten een naam hebben.
/{shoe}{boat} - Variabelen moeten worden gescheiden door een letterlijke waarde.
Overeenkomende en samengestelde padsegmenten
Met samengestelde padsegmenten kunt u een UriTemplate definiëren met meerdere variabelen binnen één padsegment. Bijvoorbeeld in de volgende sjabloontekenreeks: Adressen/{state}. {city}" twee variabelen (staat en plaats) worden gedefinieerd binnen hetzelfde segment. Deze sjabloon komt overeen met een URL, zoals http://example.com/Washington.Redmond
een URL, maar komt ook overeen met een URL zoals http://example.com/Washington.Redmond.Microsoft
. In het laatste geval bevat de statusvariabele 'Washington' en bevat de plaatsvariabele 'Redmond.Microsoft'. In dit geval komt elke tekst (behalve '/') overeen met de variabele {city}. Als u een sjabloon wilt die niet overeenkomt met de 'extra'-tekst, plaatst u de variabele in een afzonderlijk sjabloonsegment, bijvoorbeeld: Adressen/{state}/{city}.
Benoemde jokertekensegmenten
Een benoemd jokertekensegment is een padvariabelesegment waarvan de variabelenaam begint met het jokerteken '*'. De volgende sjabloontekenreeks bevat een benoemd jokertekensegment met de naam 'schoen'.
"literal/{*shoe}"
Jokertekensegmenten moeten de volgende regels volgen:
Er kan maximaal één benoemd jokertekensegment zijn voor elke sjabloontekenreeks.
Er moet een benoemd jokertekensegment worden weergegeven in het meest rechtse segment in het pad.
Een benoemd jokertekensegment kan niet naast een anoniem jokertekensegment in dezelfde sjabloontekenreeks bestaan.
De naam van een benoemd jokertekensegment moet uniek zijn.
Benoemde jokertekensegmenten kunnen geen standaardwaarden hebben.
Benoemde jokertekensegmenten kunnen niet eindigen op '/'.
Standaardvariabelewaarden
Met standaardvariabelewaarden kunt u standaardwaarden opgeven voor variabelen binnen een sjabloon. Standaardvariabelen kunnen worden opgegeven met de accolades die de variabele declareren of als een verzameling die wordt doorgegeven aan de UriTemplate-constructor. In de volgende sjabloon ziet u twee manieren om een UriTemplate met variabelen met standaardwaarden op te geven.
UriTemplate t = new UriTemplate("/test/{a=1}/{b=5}");
Deze sjabloon declareert een variabele met de naam a
een standaardwaarde van 1
en een variabele b
met een standaardwaarde van 5
.
Notitie
Alleen padsegmentvariabelen mogen standaardwaarden hebben. Queryreeksvariabelen, samengestelde segmentvariabelen en benoemde jokertekenvariabelen mogen geen standaardwaarden hebben.
De volgende code laat zien hoe standaardvariabelewaarden worden verwerkt wanneer deze overeenkomen met een kandidaat-URI.
Uri baseAddress = new Uri("http://localhost:8000/");
UriTemplate t = new UriTemplate("/{state=WA}/{city=Redmond}/", true);
Uri candidate = new Uri("http://localhost:8000/OR");
UriTemplateMatch m1 = t.Match(baseAddress, candidate);
Console.WriteLine($"Template: {t}");
Console.WriteLine($"Candidate URI: {candidate}");
// Display contents of BoundVariables
Console.WriteLine("BoundVariables:");
foreach (string key in m1.BoundVariables.AllKeys)
{
Console.WriteLine($"\t{key}={m1.BoundVariables[key]}");
}
// The output of the above code is
// Template: /{state=WA}/{city=Redmond}/
// Candidate URI: http://localhost:8000/OR
// BoundVariables:
// STATE=OR
// CITY=Redmond
Notitie
Een URI zoals komt niet overeen met http://localhost:8000///
de sjabloon die in de voorgaande code wordt vermeld, maar een URI zoals http://localhost:8000/
wel.
De volgende code laat zien hoe standaardvariabelewaarden worden verwerkt bij het maken van een URI met een sjabloon.
Uri baseAddress = new Uri("http://localhost:8000/");
Dictionary<string,string> defVals = new Dictionary<string,string> {{"a","1"}, {"b", "5"}};
UriTemplate t = new UriTemplate("/test/{a}/{b}", defVals);
NameValueCollection vals = new NameValueCollection();
vals.Add("a", "10");
Uri boundUri = t.BindByName(baseAddress, vals);
Console.WriteLine("BaseAddress: {0}", baseAddress);
Console.WriteLine("Template: {0}", t.ToString());
Console.WriteLine("Values: ");
foreach (string key in vals.AllKeys)
{
Console.WriteLine("\tKey = {0}, Value = {1}", key, vals[key]);
}
Console.WriteLine("Bound URI: {0}", boundUri);
// The output of the preceding code is
// BaseAddress: http://localhost:8000/
// Template: /test/{a}/{b}
// Values:
// Key = a, Value = 10
// Bound URI: http://localhost:8000/test/10/5
Wanneer een variabele een standaardwaarde krijgt, null
zijn er enkele extra beperkingen. Een variabele kan een standaardwaarde hebben als null
de variabele zich in het rechtersegment van de sjabloontekenreeks bevindt of als alle segmenten rechts van het segment standaardwaarden hebben.null
Hieronder ziet u geldige sjabloontekenreeksen met standaardwaarden van null
:
UriTemplate t = new UriTemplate("shoe/{boat=null}");
UriTemplate t = new UriTemplate("{shoe=null}/{boat=null}");
UriTemplate t = new UriTemplate("{shoe=1}/{boat=null}");
Hieronder ziet u ongeldige sjabloontekenreeksen met standaardwaarden van null
:
UriTemplate t = new UriTemplate("{shoe=null}/boat"); // null default must be in the right most path segment
UriTemplate t = new UriTemplate("{shoe=null}/{boat=x}/{bed=null}"); // shoe cannot have a null default because boat does not have a default null value
Standaardwaarden en overeenkomende waarden
Wanneer een kandidaat-URI wordt gekoppeld aan een sjabloon met standaardwaarden, worden de standaardwaarden in de BoundVariables verzameling geplaatst als er geen waarden zijn opgegeven in de kandidaat-URI.
Equivalentie van sjabloon
Er worden twee sjablonen als structureel equivalent beschouwd wanneer alle letterlijke gegevens van de sjablonen overeenkomen en ze variabelen in dezelfde segmenten hebben. De volgende sjablonen zijn bijvoorbeeld structureel gelijkwaardig:
/a/{var1}/b/{var2}?x=1&y=2
a/{x}/b%20b/{var1}?y=2&x=1
a/{y}/B%20B/{z}/?y=2&x=1
Enkele dingen die u moet zien:
Als een sjabloon voorloopslashes bevat, wordt alleen de eerste genegeerd.
Bij het vergelijken van sjabloontekenreeksen voor structurele gelijkwaardigheid, wordt case genegeerd voor variabele namen en padsegmenten, zijn queryreeksen hoofdlettergevoelig.
Queryreeksen zijn niet gerangschikt.
UriTemplateTable
De UriTemplateTable klasse vertegenwoordigt een associatieve tabel met UriTemplate objecten die zijn gebonden aan een object van de door de ontwikkelaar gekozen object. Een UriTemplateTable moet ten minste één UriTemplate bevatten voordat u belt MakeReadOnly(Boolean). De inhoud van een UriTemplateTable kan worden gewijzigd totdat MakeReadOnly(Boolean) deze wordt aangeroepen. Validatie wordt uitgevoerd wanneer MakeReadOnly(Boolean) deze wordt aangeroepen. Het type validatie dat wordt uitgevoerd, is afhankelijk van de waarde van de allowMultiple
parameter aan MakeReadOnly(Boolean).
Wanneer MakeReadOnly(Boolean) het doorgeven false
wordt aangeroepen, UriTemplateTable controleert u of er geen sjablonen in de tabel staan. Als er structureel equivalente sjablonen worden gevonden, wordt er een uitzondering gegenereerd. Dit wordt gebruikt in combinatie met wanneer u ervoor wilt zorgen dat slechts één sjabloon overeenkomt met MatchSingle(Uri) een binnenkomende URI.
Wanneer MakeReadOnly(Boolean) wordt aangeroepen om door te true
geven, UriTemplateTable kunnen meerdere, structureel equivalente sjablonen worden opgenomen in een UriTemplateTable.
Als een set UriTemplate objecten die zijn toegevoegd aan een UriTemplateTable querytekenreeks bevat, mogen ze niet dubbelzinnig zijn. Identieke queryreeksen zijn toegestaan.
Notitie
Hoewel de UriTemplateTable basisadressen die gebruikmaken van andere schema's dan HTTP, worden het schema en het poortnummer genegeerd bij het koppelen van kandidaat-URI's aan sjablonen.
Dubbelzinnigheid van queryreeks
Sjablonen die een equivalent pad delen, bevatten dubbelzinnige queryreeksen als er een URI is die overeenkomt met meer dan één sjabloon.
De volgende sets queryreeksen zijn ondubbelzinnig op zichzelf:
?x=1
?x=2
?x=3
?x=1&y={var}
?x=2&z={var}
?x=3
?x=1
?
? x={var}
?
?m=get&c=rss
?m=put&c=rss
?m=get&c=atom
?m=put&c=atom
De volgende sets queryreekssjablonen zijn niet eenduidig binnen zichzelf:
?x=1
?x={var}
"x=1": komt overeen met beide sjablonen.
?x=1
?y=2
"x=1&y=2" komt overeen met beide sjablonen. Dit komt doordat een querytekenreeks meer queryreeksvariabelen kan bevatten dan de sjabloon die overeenkomt met de sjabloon.
?x=1
?x=1&y={var}
"x=1&y=3" komt overeen met beide sjablonen.
?x=3&y=4
?x=3&z=5
Notitie
De tekens á en Á worden beschouwd als verschillende tekens wanneer ze worden weergegeven als onderdeel van een letterlijk URI-pad of UriTemplate padsegment (maar de tekens a en A worden beschouwd als hetzelfde). De tekens á en Á worden beschouwd als dezelfde tekens wanneer ze worden weergegeven als onderdeel van een UriTemplate {variableName} of een querytekenreeks (en a en A worden ook beschouwd als dezelfde tekens).