Dela via


UriTemplate och UriTemplateTable

Webbutvecklare kräver möjligheten att beskriva formen och layouten för de URI:er som deras tjänster svarar på. Windows Communication Foundation (WCF) har lagt till två nya klasser för att ge utvecklare kontroll över sina URI:er. UriTemplate och UriTemplateTable utgör grunden för den URI-baserade sändningsmotorn i WCF. Dessa klasser kan också användas på egen hand, så att utvecklare kan dra nytta av mallar och URI-mappningsmekanismen utan att implementera en WCF-tjänst.

Mallar

En mall är ett sätt att beskriva en uppsättning relativa URI:er. Uppsättningen med URI-mallar i följande tabell visar hur ett system som hämtar olika typer av väderinformation kan definieras.

Data Template
Nationell prognos väder/nationellt
Tillståndsprognos weather/{state}
Stadsprognos weather/{state}/{city}
Aktivitetsprognos weather/{state}/{city}/{activity}

Den här tabellen beskriver en uppsättning strukturellt liknande URI:er. Varje post är en URI-mall. Segmenten i klammerparenteser beskriver variabler. Segmenten som inte finns i klammerparenteser beskriver literalsträngar. Med WCF-mallklasserna kan en utvecklare ta en inkommande URI, till exempel "/weather/wa/seattle/cycling", och matcha den med en mall som beskriver den, "/weather/{state}/{city}/{activity}".

Uritemplate

UriTemplate är en klass som kapslar in en URI-mall. Konstruktorn tar en strängparameter som definierar mallen. Den här strängen innehåller mallen i det format som beskrivs i nästa avsnitt. Klassen UriTemplate innehåller metoder som gör att du kan matcha en inkommande URI med en mall, generera en URI från en mall, hämta en samling variabelnamn som används i mallen, avgöra om två mallar är likvärdiga och returnera mallens sträng.

Match(Uri, Uri) tar en basadress och en kandidat-URI och försöker matcha URI:n med mallen. Om matchningen lyckas returneras en UriTemplateMatch instans. Objektet UriTemplateMatch innehåller en bas-URI, kandidat-URI, en namn-/värdesamling av frågeparametrarna, en matris med segmenten för relativ sökväg, en namn-/värdesamling med variabler som matchades, den UriTemplate instans som användes för att utföra matchningen, en sträng som innehåller en omatchad del av kandidat-URI:n (används när mallen har ett jokertecken). och ett objekt som är associerat med mallen.

Kommentar

Klassen UriTemplate ignorerar schemat och portnumret när du matchar en kandidat-URI till en mall.

Det finns två metoder som gör att du kan generera en URI från en mall BindByName(Uri, NameValueCollection) och BindByPosition(Uri, String[]). BindByName(Uri, NameValueCollection) tar en basadress och en namn-/värdesamling med parametrar. Dessa parametrar ersätts med variabler när mallen är bunden. BindByPosition(Uri, String[]) tar namn/värde-paren och ersätter dem från vänster till höger.

ToString() returnerar mallsträngen.

Egenskapen PathSegmentVariableNames innehåller en samling med namnen på variablerna som används i sökvägssegmenten i mallsträngen.

IsEquivalentTo(UriTemplate) tar en UriTemplate som parameter och returnerar ett booleskt värde som anger om de två mallarna är likvärdiga. Mer information finns i avsnittet Malljämvikt senare i det här avsnittet.

UriTemplate är utformad för att fungera med alla URI-scheman som överensstämmer med HTTP-URI-grammatiken. Följande är exempel på URI-scheman som stöds.

  • http://

  • https://

  • net.tcp://

  • net.pipe://

  • sb://

Scheman som file:// och urn:// överensstämmer inte med HTTP-URI-grammatiken och orsakar oförutsägbara resultat när de används med URI-mallar.

Syntax för mallsträng

En mall har tre delar: en sökväg, en valfri fråga och ett valfritt fragment. Ett exempel finns i följande mall:

"/weather/{state}/{city}?forecast={length)#frag1

Sökvägen består av "/weather/{state}/{city}", frågan består av "?forecast={length} och fragmentet består av "#frag1".

Inledande och avslutande snedstreck är valfria i sökvägsuttrycket. Både fråge- och fragmentuttrycken kan utelämnas helt. En sökväg består av en serie segment avgränsade med "/", varje segment kan ha ett literalvärde, ett variabelnamn (skrivet i {klammerparenteser}) eller ett jokertecken (skrivet som *). I den föregående mallen är segmentet "\weather\ ett literalvärde medan "{state}" och "{city}" är variabler. Variabler tar sitt namn från innehållet i sina klammerparenteser och de kan senare ersättas med ett konkret värde för att skapa en stängd URI. Jokertecknet är valfritt, men kan bara visas i slutet av URI:n, där det logiskt matchar "resten av sökvägen".

Frågeuttrycket, om det finns, anger en serie osorterade namn/värdepar avgränsade med '&'. Element i frågeuttrycket kan antingen vara literalpar (x=2) eller ett variabelpar (x={var}). Endast den högra sidan av frågan kan ha ett variabeluttryck. ({someName} = {someValue} tillåts inte. Obetalda värden (?x) är inte tillåtna. Det finns ingen skillnad mellan ett tomt frågeuttryck och ett frågeuttryck som bara består av ett enda ?? (båda betyder "alla frågor").

Fragmentuttrycket kan bestå av ett literalvärde, inga variabler tillåts.

Alla mallvariabelnamn i en mallsträng måste vara unika. Mallvariabelnamn är skiftlägeskänsliga.

Exempel på giltiga mallsträngar:

  • ""

  • "/sko"

  • "/shoe/*"

  • "{shoe}/boat"

  • "{shoe}/{boat}/bed/{quilt}"

  • "shoe/{boat}"

  • "shoe/{boat}/*"

  • "shoe/boat?x=2"

  • "shoe/{boat}?x={bed}"

  • "shoe/{boat}?x={bed}&y=band"

  • "?x={shoe}"

  • "shoe?x=3&y={var}

Exempel på ogiltiga mallsträngar:

  • "{shoe}/{SHOE}/x=2" – Duplicera variabelnamn.

  • "{shoe}/boat/?bed={shoe}" – Duplicera variabelnamn.

  • "?x=2&x=3" – Namn/värde-par i en frågesträng måste vara unika, även om de är literaler.

  • "?x=2&" – Frågesträngen är felaktigt formaterad.

  • "?2&x={shoe}" – Frågesträngen måste vara namn/värdepar.

  • "?y=2&&X=3" – Frågesträngen måste vara namnvärdepar, namn kan inte börja med '&'.

Segment för sammansatt sökväg

Sammansatta sökvägssegment tillåter att ett enda URI-sökvägssegment innehåller flera variabler samt variabler som kombineras med literaler. Följande är exempel på giltiga sammansatta sökvägssegment.

  • /Filnamn. {ext}/

  • /{filename}.jpg/

  • /{filename}. {ext}/

  • /{a}. {b}someLiteral{c}({d})/

Följande är exempel på ogiltiga sökvägssegment.

  • /{} - Variabler måste namnges.

  • /{shoe}{boat} – Variabler måste avgränsas med en literal.

Matchnings- och sammansatta sökvägssegment

Med sammansatta sökvägssegment kan du definiera en UriTemplate som har flera variabler inom ett enda sökvägssegment. I följande mallsträng: "Adresser/{tillstånd}. {city}" två variabler (delstat och stad) definieras inom samma segment. Den här mallen skulle matcha en URL, http://example.com/Washington.Redmond till exempel men den matchar även en URL som http://example.com/Washington.Redmond.Microsoft. I det senare fallet innehåller delstatsvariabeln "Washington" och stadsvariabeln innehåller "Redmond.Microsoft". I det här fallet matchar all text (utom '/') variabeln {city}. Om du vill ha en mall som inte matchar texten "extra" placerar du variabeln i ett separat mallsegment, till exempel: "Addresses/{state}/{city}.

Namngivna jokerteckensegment

Ett namngivet jokerteckensegment är ett sökvägsvariabelsegment vars variabelnamn börjar med jokertecknet '*'. Följande mallsträng innehåller ett namngivet jokerteckensegment med namnet "shoe".

"literal/{*shoe}"

Jokerteckensegment måste följa följande regler:

  • Det kan finnas högst ett med namnet jokerteckensegment för varje mallsträng.

  • Ett namngivet jokerteckensegment måste visas i det högra segmentet i sökvägen.

  • Ett namngivet jokerteckensegment kan inte samexistera med ett anonymt jokerteckensegment i samma mallsträng.

  • Namnet på ett namngivet jokerteckensegment måste vara unikt.

  • Namngivna jokerteckensegment kan inte ha standardvärden.

  • Namngivna jokerteckensegment kan inte sluta med "/".

Standardvariabelvärden

Med standardvariabelvärden kan du ange standardvärden för variabler i en mall. Standardvariabler kan anges med klammerparenteser som deklarerar variabeln eller som en samling som skickas till konstruktorn UriTemplate. Följande mall visar två sätt att ange en UriTemplate med variabler med standardvärden.

UriTemplate t = new UriTemplate("/test/{a=1}/{b=5}");  

Den här mallen deklarerar en variabel med namnet med standardvärdet 1 och en variabel med namnet b med standardvärdet 5.a

Kommentar

Endast sökvägssegmentvariabler får ha standardvärden. Frågesträngsvariabler, sammansatta segmentvariabler och namngivna jokerteckenvariabler tillåts inte ha standardvärden.

Följande kod visar hur standardvariabelvärden hanteras när du matchar en kandidat-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

Kommentar

En URI som matchar inte mallen som http://localhost:8000/// anges i föregående kod, men en URI som http://localhost:8000/ den gör.

Följande kod visar hur standardvariabelvärden hanteras när du skapar en URI med en mall.

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  

När en variabel får ett standardvärde null för finns det några ytterligare begränsningar. En variabel kan ha ett standardvärde för null om variabeln finns inom det högra segmentet i mallsträngen eller om alla segment till höger om segmentet har standardvärdena null. Följande är giltiga mallsträngar med standardvärdena null:

  • UriTemplate t = new UriTemplate("shoe/{boat=null}");

  • UriTemplate t = new UriTemplate("{shoe=null}/{boat=null}");

  • UriTemplate t = new UriTemplate("{shoe=1}/{boat=null}");

Följande är ogiltiga mallsträngar med standardvärdena 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

Standardvärden och matchning

När du matchar en kandidat-URI med en mall som har standardvärden placeras standardvärdena i BoundVariables samlingen om värdena inte anges i kandidat-URI:n.

Malljämvikt

Två mallar sägs vara strukturellt likvärdiga när alla mallarnas literaler matchar och de har variabler i samma segment. Följande mallar är till exempel strukturellt likvärdiga:

  • /a/{var1}/b b/{var2}?x=1&y=2

  • a/{x}/b%20b/{var1}?y=2&x=1

  • a/{y}/B%20B/{z}/?y=2&x=1

Några saker att märka:

  • Om en mall innehåller inledande snedstreck ignoreras bara den första.

  • När du jämför mallsträngar för strukturell ekvivalens ignoreras skiftläget för variabelnamn och sökvägssegment, frågesträngar är skiftlägeskänsliga.

  • Frågesträngar är osorterade.

UriTemplateTable

Klassen UriTemplateTable representerar en associativ tabell med UriTemplate objekt som är bundna till ett objekt som utvecklaren väljer. Ett UriTemplateTable måste innehålla minst en UriTemplate innan du anropar MakeReadOnly(Boolean). Innehållet i en UriTemplateTable kan ändras tills det anropas MakeReadOnly(Boolean) . Verifieringen utförs när MakeReadOnly(Boolean) anropas. Vilken typ av validering som utförs beror på värdet för parametern allowMultiple till MakeReadOnly(Boolean).

När MakeReadOnly(Boolean) kallas för att skicka in falseUriTemplateTable kontrollerar du att det inte finns några mallar i tabellen. Om den hittar några strukturellt likvärdiga mallar utlöser den ett undantag. Detta används tillsammans med MatchSingle(Uri) när du vill se till att endast en mall matchar en inkommande URI.

När MakeReadOnly(Boolean) kallas för att skicka in trueUriTemplateTable tillåter du att flera, strukturellt likvärdiga mallar finns i en UriTemplateTable.

Om en uppsättning UriTemplate objekt som läggs till i en UriTemplateTable innehåller frågesträngar får de inte vara tvetydiga. Identiska frågesträngar tillåts.

Kommentar

UriTemplateTable Även om tillåter basadresser som använder andra scheman än HTTP, ignoreras schemat och portnumret vid matchning av kandidat-URI:er till mallar.

Tvetydighet i frågesträng

Mallar som delar en motsvarande sökväg innehåller tvetydiga frågesträngar om det finns en URI som matchar mer än en mall.

Följande uppsättningar med frågesträngar är entydiga inom sig själva:

  • ?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

Följande uppsättningar med frågesträngsmallar är tvetydiga inom sig själva:

  • ?x=1

  • ?x={var}

"x=1" – matchar båda mallarna.

  • ?x=1

  • ?y=2

"x=1&y=2" matchar båda mallarna. Det beror på att en frågesträng kan innehålla fler frågesträngsvariabler och den mall som den matchar.

  • ?x=1

  • ?x=1&y={var}

"x=1&y=3" matchar båda mallarna.

  • ?x=3&y=4

  • ?x=3&z=5

Kommentar

Tecknen á och Á anses vara olika tecken när de visas som en del av en URI-sökväg eller UriTemplate sökvägssegmentliteral (men tecknen a och A anses vara desamma). Tecknen á och Á anses vara samma tecken när de visas som en del av en UriTemplate {variableName} eller en frågesträng (och a och A anses också vara samma tecken).

Se även