UriTemplate a UriTemplateTable

Weboví vývojáři vyžadují možnost popsat tvar a rozložení identifikátorů URI, na které jejich služby reagují. Windows Communication Foundation (WCF) přidal dvě nové třídy, které vývojářům umožňují řídit jejich identifikátory URI. UriTemplate a UriTemplateTable tvoří základ dispečerského modulu založeného na identifikátoru URI ve WCF. Tyto třídy lze také použít samostatně, což vývojářům umožňuje využívat šablony a mechanismus mapování identifikátoru URI bez implementace služby WCF.

Šablony

Šablona představuje způsob, jak popsat sadu relativních identifikátorů URI. Sada šablon identifikátorů URI v následující tabulce ukazuje, jak může být definován systém, který načítá různé typy informací o počasí.

Data Šablona
Národní prognóza počasí/národní
Prognóza stavu weather/{state}
Prognóza města weather/{state}/{city}
Prognóza aktivity weather/{state}/{city}/{activity}

Tato tabulka popisuje sadu strukturálně podobných identifikátorů URI. Každá položka je šablona identifikátoru URI. Segmenty ve složených závorkách popisují proměnné. Segmenty, které nejsou ve složených závorkách, popisují literálové řetězce. Třídy šablon WCF umožňují vývojáři použít příchozí identifikátor URI, například /weather/wa/seattle/cycling, a spárovat ho se šablonou, která ji popisuje: /weather/{state}/{city}/{activity}.

UriTemplate

UriTemplate je třída, která zapouzdřuje šablonu identifikátoru URI. Konstruktor přebírá řetězcový parametr, který definuje šablonu. Tento řetězec obsahuje šablonu ve formátu popsaném v další části. Třída UriTemplate poskytuje metody, které umožňují spárovat příchozí identifikátor URI se šablonou, vygenerovat identifikátor URI ze šablony, načíst kolekci názvů proměnných použitých v šabloně, určit, zda jsou dvě šablony ekvivalentní, a vrátit řetězec šablony.

Match(Uri, Uri) vezme základní adresu a identifikátor URI kandidáta a pokusí se shodovat s identifikátorem URI šablony. Pokud je shoda úspěšná, UriTemplateMatch vrátí se instance. Objekt UriTemplateMatch obsahuje základní identifikátor URI, kandidátské identifikátor URI, kolekci parametrů dotazu name/value, pole segmentů relativní cesty, kolekci proměnných s názvem a hodnotou, UriTemplate instanci použitou k provedení shody, řetězec, který obsahuje libovolnou nesouvisenou část identifikátoru URI kandidáta (používá se při použití šablony se zástupným znakem). a objekt přidružený k šabloně.

Poznámka:

Třída UriTemplate ignoruje schéma a číslo portu při porovnávání kandidátských identifikátorů URI k šabloně.

Existují dvě metody, které umožňují vygenerovat identifikátor URI ze šablony BindByName(Uri, NameValueCollection) a BindByPosition(Uri, String[]). BindByName(Uri, NameValueCollection) přebírá základní adresu a kolekci parametrů name/value. Tyto parametry jsou při vazbě šablony nahrazeny proměnnými. BindByPosition(Uri, String[]) vezme páry name/value a nahradí je zleva doprava.

ToString() vrátí řetězec šablony.

Vlastnost PathSegmentVariableNames obsahuje kolekci názvů proměnných použitých v segmentech cesty v řetězci šablony.

IsEquivalentTo(UriTemplate)UriTemplate přebírá jako parametr a vrací logickou hodnotu, která určuje, zda jsou tyto dvě šablony ekvivalentní. Další informace najdete v části Ekvivalence šablon dále v tomto tématu.

UriTemplate je navržený tak, aby fungoval s libovolným schématem identifikátoru URI, které odpovídá gramatikě identifikátoru URI PROTOKOLU HTTP. Tady jsou příklady podporovaných schémat identifikátorů URI.

  • http://

  • https://

  • net.tcp://

  • net.pipe://

  • sb://

Schémata jako file:// a urn:// neodpovídají gramatikě identifikátoru URI PROTOKOLU HTTP a při použití se šablonami identifikátorů URI způsobují nepředvídatelné výsledky.

Syntaxe řetězce šablony

Šablona má tři části: cestu, volitelný dotaz a volitelný fragment. Příklad najdete v následující šabloně:

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

Cesta se skládá z "/weather/{state}/{city}", dotaz se skládá z "?forecast={length} a fragment se skládá z "#frag1".

Počáteční a koncové lomítka jsou ve výrazu cesty volitelné. Výrazy dotazu i fragmentu je možné zcela vynechat. Cesta se skládá z řady segmentů oddělených znakem /, každý segment může mít literální hodnotu, název proměnné (napsaný v {složených závorkách}) nebo zástupný znak (napsaný jako *). V předchozí šabloně je segment \weather\ literálovou hodnotou, zatímco {state} a {city} jsou proměnné. Proměnné přebírají jejich název z obsahu složených závorek a mohou být později nahrazeny konkrétní hodnotou pro vytvoření uzavřeného identifikátoru URI. Zástupný znak je volitelný, ale může se zobrazit pouze na konci identifikátoru URI, kde logicky odpovídá zbytku cesty.

Výraz dotazu, pokud je k dispozici, určuje řadu neseřazených párů název/hodnota oddělených znakem &. Prvky výrazu dotazu můžou být buď literální páry (x=2), nebo dvojice proměnných (x={var}). Výraz proměnné může mít pouze pravá strana dotazu. ({someName} = {someValue} není povoleno. Nezaplacené hodnoty (?x) nejsou povoleny. Mezi prázdným výrazem dotazu a výrazem dotazu, který se skládá pouze z jediného výrazu "?", neexistuje žádný rozdíl. (oba znamenají "jakýkoli dotaz").

Výraz fragmentu se může skládat z literálové hodnoty, nejsou povoleny žádné proměnné.

Všechny názvy proměnných šablony v řetězci šablony musí být jedinečné. Názvy proměnných šablony nerozlišují malá a velká písmena.

Příklady platných řetězců šablon:

  • ""

  • "/bota"

  • "/bota/*"

  • "{shoe}/boat"

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

  • "bota/{boat}"

  • "bota/{boat}/*"

  • "bota/loď?x=2"

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

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

  • "?x={shoe}"

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

Příklady neplatných řetězců šablon:

  • "{shoe}/{SHOE}/x=2" – duplicitní názvy proměnných.

  • "{shoe}/boat/?bed={shoe}" – duplicitní názvy proměnných.

  • "?x=2&x=3" – páry název/hodnota v rámci řetězce dotazu musí být jedinečné, i když se jedná o literály.

  • "?x=2&" – řetězec dotazu je poškozený.

  • "?2&x={shoe}" – Řetězec dotazu musí být dvojice name/value.

  • "?y=2&&&X=3" – Řetězec dotazu musí být dvojice hodnot názvů, názvy nesmí začínat znakem &.

Složené segmenty cesty

Složené segmenty cesty umožňují jednomu segmentu cesty identifikátoru URI obsahovat více proměnných a také proměnné v kombinaci s literály. Tady jsou příklady platných segmentů složených cest.

  • /Název_souboru. {ext}/

  • /{název_souboru}.jpg/

  • /{název_souboru}. {ext}/

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

Tady jsou příklady neplatných segmentů cesty.

  • /{} - Proměnné musí být pojmenované.

  • /{shoe}{boat} – proměnné musí být odděleny literálem.

Porovnávání a složené segmenty cest

Složené segmenty cesty umožňují definovat identifikátor UriTemplate, který má více proměnných v rámci jednoho segmentu cesty. Například v následujícím řetězci šablony: "Addresses/{state}. {city}" dvě proměnné (stát a město) jsou definovány ve stejném segmentu. Tato šablona by odpovídala adrese URL, například http://example.com/Washington.Redmond ale bude také odpovídat adrese URL, jako http://example.com/Washington.Redmond.Microsoftje . V druhém případě bude proměnná státu obsahovat "Washington" a proměnná města bude obsahovat "Redmond.Microsoft". V tomto případě se jakýkoli text (s výjimkou /) shoduje s proměnnou {city}. Pokud chcete šablonu, která neodpovídá textu "extra", umístěte proměnnou do samostatného segmentu šablony, například: "Addresses/{state}/{city}.

Pojmenované segmenty se zástupnými cardy

Pojmenovaný segment se zástupnými znaky je jakýkoli segment proměnné cesty, jehož název proměnné začíná zástupným znakem *. Následující řetězec šablony obsahuje pojmenovaný segment se zástupnými znaky s názvem "shoe".

"literal/{*shoe}"

Segmenty se zástupnými znaky musí dodržovat následující pravidla:

  • Pro každý řetězec šablony může existovat maximálně jeden pojmenovaný segment se zástupnými znaky.

  • V pravé části cesty se musí zobrazit pojmenovaný segment se zástupným znakem.

  • Pojmenovaný segment se zástupnými znaky nemůže existovat společně s anonymním segmentem se zástupnými znaky ve stejném řetězci šablony.

  • Název pojmenovaného segmentu se zástupným znakem musí být jedinečný.

  • Pojmenované segmenty se zástupnými znaky nemohou mít výchozí hodnoty.

  • Pojmenované segmenty zástupných znaků nemohou končit znakem /.

Výchozí hodnoty proměnných

Výchozí hodnoty proměnných umožňují zadat výchozí hodnoty pro proměnné v rámci šablony. Výchozí proměnné lze zadat pomocí složených závorek, které deklarují proměnnou nebo jako kolekci předané konstruktoru UriTemplate. Následující šablona ukazuje dva způsoby, jak zadat UriTemplate proměnné s výchozími hodnotami.

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

Tato šablona deklaruje proměnnou a s výchozí hodnotou 1 a proměnnou s názvem b s výchozí hodnotou 5.

Poznámka:

Výchozí hodnoty mají povolené pouze proměnné segmentu cesty. Proměnné řetězce dotazu, proměnné složeného segmentu a pojmenované proměnné se zástupnými znaky nesmějí mít výchozí hodnoty.

Následující kód ukazuje, jak se při porovnávání kandidátských identifikátorů URI zpracovávají výchozí hodnoty proměnných.

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

Poznámka:

Identifikátor URI, jako http://localhost:8000/// například neodpovídá šabloně uvedené v předchozím kódu, ale identifikátor URI, jako http://localhost:8000/ tomu tak je.

Následující kód ukazuje, jak se při vytváření identifikátoru URI pomocí šablony zpracovávají výchozí hodnoty proměnných.

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  

Pokud je proměnné přidělena výchozí hodnota null , existují některá další omezení. Proměnná může mít výchozí hodnotu null , pokud je proměnná obsažena v pravém největším segmentu řetězce šablony nebo pokud všechny segmenty napravo od segmentu mají výchozí hodnoty null. Následující jsou platné řetězce šablony s výchozími hodnotami null:

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

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

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

Níže jsou neplatné řetězce šablony s výchozími hodnotami 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

Výchozí hodnoty a porovnávání

Při porovnávání kandidátských identifikátorů URI se šablonou, která má výchozí hodnoty, se výchozí hodnoty umístí do BoundVariables kolekce, pokud hodnoty nejsou zadané v identifikátoru URI kandidáta.

Ekvivalence šablon

Dvě šablony jsou strukturálně ekvivalentní , když se všechny literály šablon shodují a mají proměnné ve stejných segmentech. Například následující šablony jsou strukturálně ekvivalentní:

  • /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ěkolik věcí, které byste si mohli všimnout:

  • Pokud šablona obsahuje úvodní lomítka, bude ignorována pouze první.

  • Při porovnávání řetězců šablony pro strukturální ekvivalenci se u názvů proměnných a segmentů cest ignoruje malá a velká písmena.

  • Řetězce dotazů nejsou seřazené.

Tabulka UriTemplateTable

Třída UriTemplateTable představuje asociativní tabulku UriTemplate objektů svázaných s objektem výběru vývojáře. Před UriTemplateTable voláním MakeReadOnly(Boolean)musí obsahovat alespoň jeden UriTemplate . Obsah souboru UriTemplateTable lze změnit, dokud MakeReadOnly(Boolean) se nevolá. Při zavolání se provede MakeReadOnly(Boolean) ověření. Typ provedeného ověření závisí na hodnotě parametru allowMultiple do MakeReadOnly(Boolean).

Pokud MakeReadOnly(Boolean) se volá předávání false, UriTemplateTable kontroly, aby se zajistilo, že v tabulce nejsou žádné šablony. Pokud najde nějaké strukturálně ekvivalentní šablony, vyvolá výjimku. Používá se ve spojení s MatchSingle(Uri) tím, že chcete zajistit, aby příchozí identifikátor URI odpovídal pouze jedné šabloně.

Pokud MakeReadOnly(Boolean) se nazývá předávání true, UriTemplateTable umožňuje více, strukturálně ekvivalentní šablony být obsaženy v objektu UriTemplateTable.

Pokud sada UriTemplate objektů přidaných do UriTemplateTable řetězce dotazu obsahuje, nesmí být nejednoznačné. Jsou povoleny identické řetězce dotazů.

Poznámka:

UriTemplateTable I když umožňuje základní adresy, které používají jiná schémata než HTTP, schéma a číslo portu se při porovnávání kandidátských identifikátorů URI k šablonám ignorují.

Nejednoznačnost řetězce dotazu

Šablony, které sdílejí ekvivalentní cestu, obsahují nejednoznačné řetězce dotazu, pokud existuje identifikátor URI, který odpovídá více než jedné šabloně.

Následující sadyřetězcůch

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

Následující sady šablon řetězců dotazu jsou nejednoznačné v sobě:

  • ?x=1

  • ?x={var}

"x=1" – odpovídá oběma šablon.

  • ?x=1

  • ?y=2

"x=1&y=2" odpovídá oběma šablon. Důvodem je to, že řetězec dotazu může obsahovat více proměnných řetězce dotazu, které odpovídá šabloně.

  • ?x=1

  • ?x=1&y={var}

"x=1&y=3" odpovídá oběma šablon.

  • ?x=3&y=4

  • ?x=3&z=5

Poznámka:

Znaky á a Á se považují za různé znaky, pokud se zobrazí jako součást literálu cesty URI nebo UriTemplate segmentu cesty (ale znaky a a A jsou považovány za stejné). Znaky á a Á se považují za stejné znaky, pokud se zobrazují jako součást UriTemplate řetězce dotazu {variableName} nebo řetězce dotazu (a a A jsou také považovány za stejné znaky).

Viz také