Klasy UriTemplate i UriTemplateTable
Deweloperzy sieci Web wymagają możliwości opisania kształtu i układu identyfikatorów URI, na które reagują ich usługi. Program Windows Communication Foundation (WCF) dodał dwie nowe klasy, aby zapewnić deweloperom kontrolę nad ich identyfikatorami URI. UriTemplate i UriTemplateTable stanowią podstawę aparatu wysyłania opartego na identyfikatorze URI w programie WCF. Te klasy mogą być również używane samodzielnie, dzięki czemu deweloperzy mogą korzystać z szablonów i mechanizmu mapowania identyfikatorów URI bez implementowania usługi WCF.
Szablony
Szablon to sposób opisywania zestawu względnych identyfikatorów URI. Zestaw szablonów identyfikatorów URI w poniższej tabeli pokazuje, jak można zdefiniować system, który pobiera różne typy informacji o pogodzie.
Data | Template |
---|---|
Prognoza krajowa | pogoda/krajowa |
Prognoza stanu | pogoda/{state} |
Prognoza miasta | weather/{state}/{city} |
Prognoza aktywności | weather/{state}/{city}/{activity} |
W tej tabeli opisano zestaw uri strukturalnych podobnych identyfikatorów URI. Każdy wpis jest szablonem identyfikatora URI. Segmenty w nawiasach klamrowych opisują zmienne. Segmenty nie w nawiasach klamrowych opisują ciągi literału. Klasy szablonów programu WCF umożliwiają deweloperowi użycie przychodzącego identyfikatora URI, na przykład "/weather/wa/seattle/cycling" i dopasowanie go do szablonu, który go opisuje: "/weather/{state}/{city}/{activity}".
UriTemplate
UriTemplate to klasa, która hermetyzuje szablon identyfikatora URI. Konstruktor przyjmuje parametr ciągu, który definiuje szablon. Ten ciąg zawiera szablon w formacie opisanym w następnej sekcji. Klasa UriTemplate udostępnia metody, które umożliwiają dopasowanie przychodzącego identyfikatora URI do szablonu, generowanie identyfikatora URI na podstawie szablonu, pobieranie kolekcji nazw zmiennych używanych w szablonie, określanie, czy dwa szablony są równoważne, i zwracanie ciągu szablonu.
Match(Uri, Uri) przyjmuje adres podstawowy i identyfikator URI kandydata oraz próbuje dopasować identyfikator URI do szablonu. Jeśli dopasowanie zakończy się pomyślnie, UriTemplateMatch zostanie zwrócone wystąpienie. Obiekt UriTemplateMatch zawiera podstawowy identyfikator URI, identyfikator URI kandydata, kolekcję nazwa/wartość parametrów zapytania, tablicę segmentów ścieżki względnej, kolekcję nazw/wartości zmiennych, które zostały dopasowane, UriTemplate wystąpienie używane do wykonania dopasowania, ciąg zawierający dowolną niezgodną część identyfikatora URI kandydata (używany, gdy szablon ma symbol wieloznaczny), oraz obiekt skojarzony z szablonem.
Uwaga
Klasa UriTemplate ignoruje schemat i numer portu podczas dopasowywania identyfikatora URI kandydata do szablonu.
Istnieją dwie metody, które umożliwiają generowanie identyfikatora URI na podstawie szablonu i BindByName(Uri, NameValueCollection)BindByPosition(Uri, String[]). BindByName(Uri, NameValueCollection) przyjmuje adres podstawowy i kolekcję nazw/wartości parametrów. Te parametry są zastępowane zmiennymi, gdy szablon jest powiązany. BindByPosition(Uri, String[]) przyjmuje pary nazwa/wartość i zastępuje je od lewej do prawej.
ToString() Zwraca ciąg szablonu.
Właściwość PathSegmentVariableNames zawiera kolekcję nazw zmiennych używanych w segmentach ścieżki w ciągu szablonu.
IsEquivalentTo(UriTemplate)UriTemplate przyjmuje jako parametr i zwraca wartość logiczną określającą, czy dwa szablony są równoważne. Aby uzyskać więcej informacji, zobacz sekcję Równoważność szablonu w dalszej części tego tematu.
UriTemplate program jest przeznaczony do pracy z dowolnym schematem identyfikatora URI, który jest zgodny z gramatyką identyfikatora URI HTTP. Poniżej przedstawiono przykłady obsługiwanych schematów identyfikatorów URI.
http://
https://
net.tcp://
net.pipe://
sb://
Schematy, takie jak file:// i urn://, nie są zgodne z gramatyką identyfikatora URI HTTP i powodują nieprzewidywalne wyniki w przypadku użycia z szablonami identyfikatorów URI.
Składnia ciągu szablonu
Szablon ma trzy części: ścieżkę, opcjonalne zapytanie i opcjonalny fragment. Przykład można znaleźć w następującym szablonie:
"/weather/{state}/{city}?forecast={length)#frag1
Ścieżka składa się z "/weather/{state}/{city}", zapytanie składa się z "?forecast={length}", a fragment składa się z "#frag1".
Ukośniki wiodące i końcowe są opcjonalne w wyrażeniu ścieżki. W całości można pominąć zarówno wyrażenia zapytania, jak i fragmentu. Ścieżka składa się z serii segmentów rozdzielonych znakami "/", każdy segment może mieć wartość literału, nazwę zmiennej (zapisaną w nawiasach klamrowych}) lub symbol wieloznaczny (zapisany jako "*"). W poprzednim szablonie segment "\weather\ jest wartością literału, podczas gdy "{state}" i "{city}" są zmiennymi. Zmienne przyjmują swoją nazwę z zawartości nawiasów klamrowych i później można je zastąpić konkretną wartością, aby utworzyć zamknięty identyfikator URI. Symbol wieloznaczny jest opcjonalny, ale może być wyświetlany tylko na końcu identyfikatora URI, gdzie logicznie pasuje do reszty ścieżki.
Wyrażenie zapytania, jeśli jest obecne, określa serię nieurządkowanych par nazw/wartości rozdzielonych przez '&'. Elementy wyrażenia zapytania mogą być parami literałów (x=2) lub parą zmiennych (x={var}). Tylko prawa strona zapytania może mieć wyrażenie zmiennej. ({someName} = {someValue} jest niedozwolona. Niezapłacone wartości (?x) nie są dozwolone. Nie ma różnicy między pustym wyrażeniem zapytania a wyrażeniem zapytania składającym się tylko z jednego wyrażenia "?". (obie oznaczają "dowolne zapytanie").
Wyrażenie fragmentu może składać się z wartości literału, a żadne zmienne nie są dozwolone.
Wszystkie nazwy zmiennych szablonu w ciągu szablonu muszą być unikatowe. Nazwy zmiennych szablonu nie są uwzględniane wielkości liter.
Przykłady prawidłowych ciągów szablonu:
""
"/shoe"
"/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}
Przykłady nieprawidłowych ciągów szablonu:
"{shoe}/{SHOE}/x=2" — zduplikowane nazwy zmiennych.
"{shoe}/boat/?bed={shoe}" — zduplikowane nazwy zmiennych.
"?x=2&x=3" — pary nazw/wartości w ciągu zapytania muszą być unikatowe, nawet jeśli są literałami.
"?x=2&" — ciąg zapytania jest źle sformułowany.
"?2&x={shoe}" — ciąg zapytania musi być parami nazwa/wartość.
"?y=2&&X=3" — ciąg kwerendy musi być parami wartości nazwy, nazwy nie mogą zaczynać się od "&".
Segmenty ścieżek złożonych
Segmenty ścieżek złożonych umożliwiają pojedynczemu segmentowi ścieżki identyfikatora URI zawierającemu wiele zmiennych, a także zmiennych połączonych z literałami. Poniżej przedstawiono przykłady prawidłowych segmentów ścieżek złożonych.
/Pod nazwą. {ext}/
/{nazwa_pliku}.jpg/
/{nazwa_pliku}. {ext}/
/{a}. {b}someLiteral{c}({d})/
Poniżej przedstawiono przykłady nieprawidłowych segmentów ścieżki.
/{} - Zmienne muszą być nazwane.
/{shoe}{boat} — zmienne muszą być rozdzielone literałem.
Segmenty pasujących i złożonych ścieżek
Segmenty ścieżek złożonych umożliwiają zdefiniowanie identyfikatora UriTemplate zawierającego wiele zmiennych w ramach jednego segmentu ścieżki. Na przykład w następującym ciągu szablonu: "Adresy/{state}. {city}" dwie zmienne (stan i miasto) są definiowane w tym samym segmencie. Ten szablon będzie pasował do adresu URL, takiego jak , ale będzie również pasował do adresu URL, takiego jak http://example.com/Washington.Redmond
http://example.com/Washington.Redmond.Microsoft
. W tym drugim przypadku zmienna stanowa będzie zawierać wartość "Washington", a zmienna miasta będzie zawierać wartość "Redmond.Microsoft". W takim przypadku dowolny tekst (z wyjątkiem '/') będzie zgodny ze zmienną {city}. Jeśli chcesz, aby szablon, który nie będzie pasować do "dodatkowego" tekstu, umieść zmienną w osobnym segmencie szablonu, na przykład: "Adresy/{state}/{miasto}.
Nazwane segmenty symboli wieloznacznych
Nazwany segment z symbolami wieloznacznymi to dowolny segment zmiennej ścieżki, którego nazwa zmiennej zaczyna się od symbolu wieloznakowego "*". Poniższy ciąg szablonu zawiera nazwany segment symboli wieloznacznych o nazwie "shoe".
"literal/{*shoe}"
Segmenty z symbolami wieloznacznymi muszą być zgodne z następującymi regułami:
Dla każdego ciągu szablonu może istnieć co najwyżej jeden segment z symbolami wieloznacznymi.
W ścieżce musi znajdować się nazwany segment z symbolami wieloznacznymi.
Nazwany segment symboli wieloznacznych nie może współistnieć z anonimowym segmentem symboli wieloznacznych w ramach tego samego ciągu szablonu.
Nazwa nazwanego segmentu symboli wieloznacznych musi być unikatowa.
Nazwane segmenty wieloznaczne nie mogą mieć wartości domyślnych.
Nazwane segmenty wieloznaczne nie mogą kończyć się ciągiem "/".
Domyślne wartości zmiennych
Domyślne wartości zmiennych umożliwiają określanie wartości domyślnych zmiennych w szablonie. Zmienne domyślne można określić za pomocą nawiasów klamrowych, które deklarują zmienną lub jako kolekcję przekazaną do konstruktora UriTemplate. Poniższy szablon przedstawia dwa sposoby określania UriTemplate zmiennej ze zmiennymi z wartościami domyślnymi.
UriTemplate t = new UriTemplate("/test/{a=1}/{b=5}");
Ten szablon deklaruje zmienną o nazwie a
z wartością 1
domyślną i zmienną o nazwie b
z wartością 5
domyślną .
Uwaga
Tylko zmienne segmentu ścieżki mogą mieć wartości domyślne. Zmienne ciągu zapytania, zmienne segmentu złożonego i nazwane zmienne wieloznaczne nie mogą mieć wartości domyślnych.
Poniższy kod przedstawia sposób obsługi domyślnych wartości zmiennych podczas dopasowywania identyfikatora URI kandydata.
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
Uwaga
Identyfikator URI, taki jak http://localhost:8000///
nie pasuje do szablonu wymienionego w poprzednim kodzie, jednak identyfikator URI, taki jak http://localhost:8000/
nie.
Poniższy kod przedstawia sposób obsługi domyślnych wartości zmiennych podczas tworzenia identyfikatora URI przy użyciu szablonu.
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
Gdy zmienna ma wartość null
domyślną, istnieją pewne dodatkowe ograniczenia. Zmienna może mieć wartość null
domyślną, jeśli zmienna jest zawarta w prawym segmencie ciągu szablonu lub jeśli wszystkie segmenty po prawej stronie segmentu mają wartości null
domyślne . Poniżej przedstawiono prawidłowe ciągi szablonu z wartościami null
domyślnymi :
UriTemplate t = new UriTemplate("shoe/{boat=null}");
UriTemplate t = new UriTemplate("{shoe=null}/{boat=null}");
UriTemplate t = new UriTemplate("{shoe=1}/{boat=null}");
Poniżej przedstawiono nieprawidłowe ciągi szablonu z wartościami null
domyślnymi :
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
Wartości domyślne i dopasowywanie
Podczas dopasowywania identyfikatora URI kandydata do szablonu, który ma wartości domyślne, wartości domyślne są umieszczane w BoundVariables kolekcji, jeśli wartości nie są określone w identyfikatorze URI kandydata.
Równoważność szablonu
Mówi się, że dwa szablony są strukturalnie równoważne , gdy wszystkie literały szablonów są zgodne i mają zmienne w tych samych segmentach. Na przykład następujące szablony są strukturalnie równoważne:
/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
Kilka rzeczy, które należy zauważyć:
Jeśli szablon zawiera wiodące ukośniki, tylko pierwszy z nich jest ignorowany.
Podczas porównywania ciągów szablonów dla równoważności strukturalnej wielkość liter jest ignorowana dla nazw zmiennych i segmentów ścieżki, w ciągach zapytania jest uwzględniana wielkość liter.
Ciągi zapytania są nieurządzane.
Uritemplatetable
Klasa UriTemplateTable reprezentuje asocjacyjną tabelę UriTemplate obiektów powiązanych z obiektem wybranego przez dewelopera. Element UriTemplateTable musi zawierać co najmniej jeden UriTemplate element przed wywołaniem metody MakeReadOnly(Boolean). Zawartość obiektu UriTemplateTable można zmienić do momentu MakeReadOnly(Boolean) wywołania. Walidacja jest wykonywana po MakeReadOnly(Boolean) wywołaniu. Typ wykonanej weryfikacji zależy od wartości parametru allowMultiple
do MakeReadOnly(Boolean).
Gdy MakeReadOnly(Boolean) jest wywoływana funkcja przekazywania false
, sprawdza, UriTemplateTable czy w tabeli nie ma szablonów. Jeśli znajdzie on jakiekolwiek szablony równoważne strukturalnie, zgłasza wyjątek. Jest to używane w połączeniu z MatchSingle(Uri) , gdy chcesz upewnić się, że tylko jeden szablon pasuje do przychodzącego identyfikatora URI.
Gdy MakeReadOnly(Boolean) jest wywoływana funkcja przekazywania , UriTemplateTabletrue
umożliwia zawieranie wielu szablonów równoważnych strukturalnie w obiekcie UriTemplateTable.
Jeśli zestaw obiektów dodanych UriTemplate do UriTemplateTable ciągu zapytania zawiera, nie może być niejednoznaczny. Identyczne ciągi zapytania są dozwolone.
Uwaga
Chociaż ustawienie zezwala na UriTemplateTable adresy podstawowe korzystające z schematów innych niż HTTP, schemat i numer portu są ignorowane podczas dopasowywania identyfikatorów URI kandydata do szablonów.
Niejednoznaczność ciągu zapytania
Szablony współużytkujące równoważną ścieżkę zawierają niejednoznaczne ciągi zapytania, jeśli istnieje identyfikator URI zgodny z więcej niż jednym szablonem.
Następujące zestawy ciągów zapytania są jednoznaczne w sobie:
?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
Następujące zestawy szablonów ciągów zapytania są niejednoznaczne w sobie:
?x=1
?x={var}
"x=1" — pasuje do obu szablonów.
?x=1
?y=2
"x=1&y=2" pasuje do obu szablonów. Jest to spowodowane tym, że ciąg zapytania może zawierać więcej zmiennych ciągu zapytania, a następnie szablon, który pasuje.
?x=1
?x=1&y={var}
"x=1&y=3" pasuje do obu szablonów.
?x=3&y=4
?x=3&z=5
Uwaga
Znaki á i Á są uważane za różne znaki, gdy są one wyświetlane jako część literału ścieżki identyfikatora URI lub UriTemplate segmentu ścieżki (ale znaki a i A są uważane za takie same). Znaki á i Á są uważane za te same znaki, gdy są one wyświetlane jako część UriTemplate {variableName} lub ciągu zapytania (a i A są również uważane za te same znaki).