UriTemplate und UriTemplateTable
Webentwickler benötigen die Fähigkeit, die Form und das Layout der URIs zu beschreiben, auf die ihre Dienste reagieren. In Windows Communication Foundation (WCF) wurden zwei neue Klassen hinzugefügt, mit denen die Entwickler ihre URIs gut kontrollieren können. UriTemplate und UriTemplateTable bilden die Basis des URI-basierten Dispatchmoduls in WCF. Diese Klassen können auch alleine verwendet werden und geben so den Entwicklern die Möglichkeit, Vorlagen und den URI-Abbildungsmechanismus zu nutzen, ohne einen WCF-Dienst implementieren zu müssen.
Vorlagen
Eine Vorlage ist eine Möglichkeit, einen Satz relativer URIs zu beschreiben. Der Satz von URI-Vorlagen in der folgenden Tabelle zeigt, wie ein System, das verschiedene Arten von Wetterdaten abruft, definiert werden könnte.
Daten | Vorlage |
---|---|
Nationale Vorhersage |
Wetter/national |
Bundeslandvorhersage |
Wetter/{Staat} |
Ortsvorhersage |
Wetter/{Bundesland}/{Stadt} |
Aktivitätsvorhersage |
Wetter/{Bundesland}/{Stadt}/{Aktivität} |
In dieser Tabelle wird ein Satz strukturell ähnlicher URIs beschrieben. Jeder Eintrag ist eine URI-Vorlage. Die Segmente in geschweiften Klammern beschreiben Variablen. Die Segmente, die nicht in geschweifte Klammern eingefasst sind, beschreiben Literalzeichenfolgen. Die WCF-Vorlagenklassen ermöglichen dem Entwickler, einen eingehenden URI (z. B. "/Wetter/BW/Mannheim/wechselhaft") anzunehmen und ihn mit einer Vorlage abzugleichen, die ihn beschreibt, "/Wetter/{Bundesland}/{Stadt}/{Aktivität}".
UriTemplate
UriTemplate ist eine Klasse, die eine URI-Vorlage kapselt. Der Konstruktor nimmt einen Zeichenfolgenparameter, der die Vorlage definiert. Diese Zeichenfolge enthält die Vorlage in dem im nächsten Abschnitt beschriebenen Format. Die UriTemplate-Klasse bietet Methoden, die die Zuordnung eines eingehenden URI zu einer Vorlage, die Generierung eines URI aus einer Vorlage, das Abrufen einer Sammlung von Variablennamen, die in der Vorlage verwendet werden, die Bestimmung, ob zwei Vorlagen gleichwertig sind, und die Ausgabe der Zeichenfolge der Vorlage ermöglichen.
Match nimmt eine Basisadresse und einen möglichen URI und versucht, den URI der Vorlage zuzuweisen. Wenn die Zuordnung erfolgreich ist, wird eine UriTemplateMatch-Instanz zurückgegeben. Das UriTemplateMatch-Objekt enthält einen Basis-URI, den möglichen URI, eine Name-Wert-Sammlung der Abfrageparameter, eine Matrix der Segmente des relativen Pfads, eine Name-Wert-Sammlung der Variablen, die zugeordnet wurden, die UriTemplate-Instanz, die zum Durchführen der Zuordnung verwendet wurde, eine Zeichenfolge, die jeden nicht zugeordneten Teil des Kandidaten-URI enthält (wird verwendet, wenn die Vorlage über einen Platzhalter verfügt), und ein Objekt, das der Vorlage zugewiesen ist.
Hinweis: |
---|
Beim Vergleichen eines möglichen URIs mit einer Vorlage ignoriert die UriTemplate-Klasse das Schema und die Portnummer. |
Zum Generieren eines URI aus einer Vorlage stehen zwei Methoden zur Verfügung: BindByName und BindByPosition. BindByName akzeptiert eine Basisadresse und eine Name-Wert-Sammlung der Parameter. Wenn die Vorlage gebunden ist, werden diese Parameter durch Variablen ersetzt. BindByPosition nimmt die Name-Wert-Paare und ersetzt sie von links nach rechts.
ToString gibt die Vorlagenzeichenfolge zurück,
Die PathSegmentVariableNames-Eigenschaft enthält eine Sammlung der Namen der Variablen, die innerhalb der Pfadsegmente in der Vorlagenzeichenfolge verwendet werden.
IsEquivalentTo nimmt eine UriTemplate als Parameter und gibt einen Booleschen Wert zurück, der angibt, ob die beiden Vorlagen gleichwertig sind. Weitere Informationen finden Sie unter dem Abschnitt "Vorlagenäquivalenz" finden Sie weiter unten in diesem Thema.
UriTemplate wurde für die Zusammenarbeit mit einem URI-Schema entwickelt, das der HTTP URI-Grammatik entspricht. Im Folgenden finden Sie Beispiele für unterstützte URI-Schemas:
http://
https://
net.tcp://
net.pipe://
sb://
Schemas wie "file://" und "urn://" entsprechen nicht der HTTP-URI-Grammatik und führen bei der Verwendung mit URI-Vorlagen zu unvorhersehbaren Ergebnissen.
Vorlagenzeichenfolgen-Syntax
Eine Vorlage besteht aus drei Teilen: einem Pfad, einer optionalen Abfrage und einem optionalen Fragment. Ein Beispiel finden Sie in der folgenden Vorlage:
"/weather/{state}/{city}?forecast={length)#frag1
Der Pfad besteht aus "/Wetter/{Bundesland}/{Ort}", die Abfrage besteht aus "?forecast={Länge}, und das Fragment besteht aus "#frag1."
Führende und nachstehende Schrägstriche sind im Pfadausdruck optional. Sowohl der Abfrage- als auch der Fragmentausdruck kann vollständig weggelassen werden. Ein Pfad besteht aus einer Reihe von Segmenten, die durch "/" voneinander getrennt sind; jedes Segment kann einen Literalwert, einen Variablennamen (der in {geschweiften Klammern} steht) oder einen Platzhalter (der als "*" geschrieben wird) besitzen. In der vorherigen Vorlage ist das "\Wetter\"-Segment ein Literalwert, während "{Bundesland}" und "{Ort}" Variablen sind. Variablen erhalten ihren Namen von den Inhalten der geschweiften Klammern und können später durch einen bestimmten Wert ersetzt werden, um einen geschlossenen URI zu erschaffen. Der Platzhalter ist optional, kann aber nur am Ende des URI eingesetzt werden, wo er logisch "dem Rest des Pfads" entspricht.
Der Abfrageausdruck gibt ggf. eine Reihe ungeordneter Name-Wert-Paare an, die durch "&" getrennt werden. Bei den Elementen des Abfrageausdrucks kann es sich entweder um Literalpaare (x=2) oder ein Variablenpaar (x={var}) handeln. Nur die rechte Seite der Abfrage kann einen variablen Ausdruck enthalten. ({someName} = {someValue} ist nicht zulässig. Ungepaarte Werte (?x) sind nicht zulässig. Es besteht kein Unterschied zwischen einem leeren Abfrageausdruck und einem Abfrageausdruck, der aus einem einzelnen "?" besteht. (beide bedeuten "beliebige Anfrage").
Der Fragmentausdruck kann aus einem Literalwert bestehen, Variablen sind nicht zulässig.
Alle Vorlagenvariablennamen innerhalb einer Vorlagenzeichenfolge müssen eindeutig sein. Bei Namen von Vorlagenvariablen wird die Groß- und Kleinschreibung nicht berücksichtigt.
Beispiele für gültige Vorlagenzeichenfolgen:
""
"/Schuh"
"/Schuh/*"
"{Schuh}/Boot"
"{Schuh}/{Boot}/Bett/{Steppdecke}"
"Schuh/{Boot}"
"Schuh/{Boot}/*"
"Schuh/Boot?x=2"
"Schuh/{Boot}?x={Bett}"
"Schuh/{Boot}?x={Bett}&y=band"
"?x={Schuh}"
"Schuh?x=3&y={var}
Beispiele für ungültige Vorlagenzeichenfolgen sind:
"{Schuh}/{SCHUH}/x=2" – doppelte Variablennamen.
"{Schuh}/Boot/?Bett={SCHUH}" – doppelte Variablennamen.
"?x=2&x=3" – Name-Wert-Paare innerhalb einer Abfragezeichenfolge müssen eindeutig sein, auch wenn sie Literale sind.
"?x=2&" – Abfragezeichenfolge ist fehlerhaft.
"?2&x={Schuh}" – Abfragezeichenfolge muss Name-Wert-Paar sein.
"?y=2&&X=3" – Abfragezeichenfolge muss Name-Wert-Paar sein; Namen dürfen nicht mit "& " beginnen.
Zusammengesetzte Pfadsegmente
Bei zusammengesetzten Pfadsegmenten kann ein einzelnes URI-Pfadsegment mehrere Variablen sowie mit Literalwerten kombinierte Variablen enhalten. Im Folgenden finden Sie Beispiele für gültige zusammengesetzte Pfadsegmente:
/Dateiname.{Erw.}/
/{Dateiname}.jpg/
/{Dateiname}.{Erw.}/
/{a}.{b}Literalwert{c}({d})/
Im Folgenden finden Sie Beispiele für ungültige Pfadsegmente:
/{} – Variablen müssen benannt werden.
/{Schuh}{Boot} – Variablen müssen durch einen Literalwert getrennt werden.
Zuordnung und zusammengesetzte Pfadsegmente
Zusammengesetzte Pfadsegmente ermöglichen Ihnen das Definieren einer UriTemplate mit mehreren Variablen in nur einem Pfadsegment. In der Vorlagenzeichenfolge "Addresses/{state}.{city}" sind zwei Variablen (state und city) in demselben Segment definiert. Durch diese Vorlage würde eine URL wie "http://example.com/Washington.Redmond" zugeordnet werden, aber auch eine URL wie "http://example.com/Washington.Redmond.Microsoft". In letzterem Fall enthält die state-Variable "Washington" und die city-Variable "Redmond.Microsoft". In diesem Fall entspricht jeder Text (mit Ausnahme von "/") der {city}-Variable. Wenn Sie eine Vorlage erstellen möchten, durch die der "zusätzliche" Text nicht zugeordnet wird, fügen Sie die Variable in einem separaten Vorlagensegment ein, z. B. "Addresses/{state}/{city}".
Benannte Platzhaltersegmente
Bei einem benannten Platzhaltersegment handelt es sich um ein beliebiges Pfadvariablensegment, dessen Variablenname mit dem Platzhalterzeichen "*" beginnt. Die folgende Vorlagenzeichenfolge enthält ein benanntes Platzhaltersegment mit dem Namen "Schuh".
"literal/{*shoe}"
Für Platzhaltersegmente gelten die folgenden Regeln:
Für jede Vorlagenzeichenfolge kann höchstens ein benanntes Platzhaltersegment vorhanden sein.
Ein benanntes Platzhaltersegment muss sich im am weitesten rechts stehenden Segment des Pfads befinden.
Ein benanntes Platzhaltersegment kann nicht zusammen mit einem anonymen Platzhaltersegment innerhalb der gleichen Vorlagenzeichenfolge verwendet werden.
Der Name eines benannten Platzhaltersegments muss eindeutig sein.
Benannte Platzhaltersegmente können keine Standardwerte besitzen.
Benannte Platzhaltersegmente können nicht mit "/" enden.
Standardvariablenwerte
Standardvariablenwerte ermöglichen das Angeben von Standardwerten für Variablen innerhalb einer Vorlage. Standardvariablen können mit den geschweiften Klammern, durch die die Variable deklariert wird, oder durch eine an den UriTemplate-Konstruktor weitergegebene Sammlung angegeben werden. Die folgende Vorlage zeigt zwei Möglichkeiten, eine UriTemplate mit Variablen mit Standardwerten anzugeben:
UriTemplate t = new UriTemplate("/test/{a=1}/{b=5}");
In dieser Vorlage werden die Variable a
mit dem Standardwert 1
und die Variable b
mit dem Standardwert 5
deklariert.
Hinweis: |
---|
Nur Pfadsegmentvariablen können Standardwerte besitzen. Bei Abfragezeichenfolgenvariablen, zusammengesetzten Segmentvariablen sowie bei benannten Platzhaltervariablen sind Standardwerte nicht zulässig. |
Im folgenden Code wird die Behandlung von Standardvariablenwerten beim Abgleichen eines möglichen URI gezeigt:
Uri baseAddress = new Uri("https://localhost:800
Dictionary<string,string> defVals = new Dictionary<string,string> {{"a","1"}, {"b", "5"}};
UriTemplate t = new UriTemplate("/test/{a}/{b}", defVals);0");
UriTemplate t = new UriTemplate("/{state=WA}/{city=Redmond}/", true);
Uri candidate = new Uri("https://localhost:8000/OR");
UriTemplateMatch m1 = t.Match(baseAddress, candidate);
// Display contents of BoundVariables
foreach (string key in m1.BoundVariables.AllKeys)
{
Console.WriteLine("\t\t{0}={1}", key, m1.BoundVariables[key]);
}
// The output of the above code is
// Template: /{state=WA}/{city=Redmond}/
// Candidate URI: https://localhost:8000/OR
// BoundVariables:
// STATE=OR
// CITY=Redmond
Hinweis: |
---|
Der URI "https://localhost:8000///" entspricht nicht der im vorhergehenden Code enthaltenen Vorlage, der URI "https://localhost:8000/" dagegen schon. |
Im folgenden Code wird die Behandlung von Standardvariablenwerten beim Erstellen eines URI mit einer Vorlage veranschaulicht.
Uri baseAddress = new Uri("https://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: https://localhost:8000/
// Template: /test/{a}/{b}
// Values:
// Key = a, Value = 10
// Bound URI: https://localhost:8000/test/10/5
Erhält eine Variable den Standardwert NULL, gelten einige zusätzliche Einschränkungen. Eine Variable kann den Standardwert NULL besitzen, wenn sich die Variable im am weitesten rechts befindlichen Segment der Vorlagenzeichenfolge befindet oder wenn alle Segmente rechts des Segments jeweils den Standardwert NULL besitzen. Im Folgenden finden Sie gültige Vorlagenzeichenfolgen mit dem Standardwert NULL:
-
UriTemplate t = new UriTemplate("shoe/{boat=null}");
-
UriTemplate t = new UriTemplate("{shoe=null}/{boat=null}");
-
UriTemplate t = new UriTemplate("{shoe=1}/{boat=null}");
Im Folgenden finden Sie ungültige Vorlagenzeichenfolgen mit dem Standardwert 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
Standardwerte und Vergleich
Beim Vergleichen eines möglichen URI mit einer Vorlage mit Standardwerten werden die Standardwerte in der BoundVariables-Sammlung platziert, wenn im möglichen URI keine Werte angegeben sind.
Vorlagenäquivalenz
Zwei Vorlagen gelten als strukturell äquivalent, wenn alle Literalwerte der Vorlagen übereinstimmen und sie über Variablen in den gleichen Segmenten verfügen. Beispielsweise sind die folgenden Vorlagen strukturell äquivalent:
/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
Hierbei müssen noch einige Punkte beachtet werden:
Wenn eine Vorlage führende Schrägstriche enthält, wird nur der erste ignoriert.
Wenn Vorlagenzeichenfolgen auf strukturelle Äquivalenz verglichen werden, wird die Groß-/Kleinschreibungen bei den Variablennamen und Pfadsegmenten ignoriert; bei den Abfragezeichenfolgen muss sie beachtet werden.
Abfragezeichenfolgen sind unsortiert.
UriTemplateTable
Die Klasse UriTemplateTable stellt eine assoziative Tabelle aus UriTemplate-Objekten dar, die an ein Objekt nach Wahl des Entwicklers gebunden sind. UriTemplateTable muss vor Aufruf von MakeReadOnly mindestens eine UriTemplate enthalten. Der Inhalt einer UriTemplateTable kann geändert werden, bis MakeReadOnly aufgerufen wird. Die Überprüfung wird ausgeführt, wenn MakeReadOnly aufgerufen wird. Der Typ der ausgeführten Prüfung hängt vom Wert des Parameters allowMultiple zur MakeReadOnly ab.
Wenn MakeReadOnly bei Übergabe in false aufgerufen wird, überprüft die UriTemplateTable, dass sich keine Vorlagen in der Tabelle befinden. Wenn strukturell äquivalente Vorlagen gefunden werden, wird eine Ausnahme ausgelöst. Dies wird zusammen mit MatchSingle verwendet, wenn sichergestellt werden soll, dass nur eine Vorlage einem eingehenden URI entspricht.
Wenn MakeReadOnly bei der Übergabe von true aufgerufen wird, lässt UriTemplateTable mehrere strukturell äquivalente Vorlagen in einer UriTemplateTable zu.
Wenn ein Satz UriTemplate-Objekte, die einer UriTemplateTable hinzugefügt sind, Abfragezeichenfolgen enthält, dürfen sie nicht mehrdeutig sein. Identische Abfragezeichenfolgen sind zulässig.
Hinweis: |
---|
Zwar lässt die UriTemplateTable Basisadressen mit HTTP-fremden Schemas zu, Schema und Portnummer werden beim Vergleichen möglicher URIs mit Vorlagen jedoch ignoriert. |
Abfragezeichenfolgenmehrdeutigkeit
Vorlagen, die einen äquivalenten Pfad teilen, enthalten mehrdeutige Abfragezeichenfolgen, wenn es einen URI gibt, der mehr als einer Vorlage entspricht.
Die folgenden Sätze von Abfragezeichenfolgen sind in sich selbst eindeutig:
?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
Die folgenden Abfragezeichenfolgenvorlagen sind in sich selbst mehrdeutig:
?x=1
?x={var}
"x=1" – passt zu beiden Vorlagen.
?x=1
?y=2
"x=1&y=2" passt zu beiden Vorlagen. Das liegt daran, dass eine Abfragezeichenfolge mehr Abfragezeichenfolgen-Variablen enthalten kann als die Vorlage, zu der sie passt.
?x=1
?x=1&y={var}
"x=1&y=3" passt zu beiden Vorlagen.
?x=3&y=4
?x=3&z=5
Hinweis: |
---|
Die Zeichen "á" und "Á" gelten als unterschiedliche Zeichen, wenn sie als Teil eines URI-Pfads oder eines UriTemplate-Pfadsegmentliterals verwendet werden. (Die Zeichen "a" und "A" gelten hingegen als gleich.) Die Zeichen á und Á gelten als gleiche Zeichen, wenn sie als Teil einer UriTemplate {Variablenname} oder einer Abfragezeichenfolge erscheinen (a und A gelten ebenfalls als gleiche Zeichen). |
Siehe auch
Aufgaben
UriTemplate-Beispiel
Beispiel zur UriTemplate-Tabelle
Beispiel zum UriTemplate-Tabellenverteiler
Konzepte
Überblick über WCF-Web-HTTP-Programmiermodelle
Objektmodell für WCF-Web-HTTP-Programmierung