Bagikan melalui


UriTemplate dan UriTemplateTable

Pengembang web memerlukan kemampuan untuk menggambarkan bentuk dan tata letak URI yang direspons layanan mereka. Windows Communication Foundation (WCF) menambahkan dua kelas baru untuk memberi pengembang kontrol atas URI mereka. UriTemplate dan UriTemplateTable membentuk dasar mesin pengiriman berbasis URI di WCF. Kelas-kelas ini juga dapat digunakan sendiri, memungkinkan pengembang untuk memanfaatkan templat dan mekanisme pemetaan URI tanpa menerapkan layanan WCF.

Templat

Templat adalah cara untuk menjelaskan sekumpulan URI relatif. Kumpulan templat URI dalam tabel berikut menunjukkan bagaimana sistem yang mengambil berbagai jenis informasi cuaca mungkin ditentukan.

Data Templat
Prakiraan Nasional cuaca/nasional
Prakiraan Status weather/{state}
Prakiraan Kota weather/{state}/{city}
Prakiraan Aktivitas weather/{state}/{city}/{activity}

Tabel ini menjelaskan sekumpulan URI yang serupa secara struktural. Setiap entri adalah templat URI. Segmen dalam kurung kurawal menggambarkan variabel. Segmen yang tidak dalam kurung kurawal menggambarkan string harfiah. Kelas templat WCF memungkinkan pengembang untuk mengambil URI masuk, misalnya, "/weather/wa/seattle/cycling", dan mencocokkannya dengan templat yang menjelaskannya, "/weather/{state}/{city}/{activity}".

UriTemplate

UriTemplate adalah kelas yang merangkum templat URI. Konstruktor mengambil parameter string yang menentukan templat. String ini berisi templat dalam format yang dijelaskan di bagian berikutnya. Kelas UriTemplate menyediakan metode yang memungkinkan Anda mencocokkan URI yang masuk ke templat, menghasilkan URI dari templat, mengambil kumpulan nama variabel yang digunakan dalam templat, menentukan apakah dua templat setara, dan mengembalikan string templat.

Match(Uri, Uri) mengambil alamat dasar dan URI kandidat dan mencoba mencocokkan URI dengan templat. Jika kecocokan berhasil, instans UriTemplateMatch dikembalikan. Objek UriTemplateMatch berisi URI dasar, kandidat URI, kumpulan nama/nilai dari parameter kueri, array segmen jalur relatif, kumpulan nama/nilai variabel yang cocok, instans UriTemplate yang digunakan untuk melakukan pencocokan, string yang berisi bagian kandidat URI yang tidak cocok (digunakan saat templat memiliki wildcard), dan objek yang terkait dengan templat.

Catatan

Kelas UriTemplate mengabaikan skema dan nomor port saat mencocokkan URI kandidat dengan templat.

Ada dua metode yang memungkinkan Anda menghasilkan URI dari templat, BindByName(Uri, NameValueCollection) dan BindByPosition(Uri, String[]). BindByName(Uri, NameValueCollection) mengambil alamat dasar dan kumpulan nama/nilai parameter. Parameter ini menggantikan variabel ketika templat terikat. BindByPosition(Uri, String[]) mengambil pasangan nama/nilai dan menggantinya dari kiri ke kanan.

ToString() mengembalikan string templat.

Properti PathSegmentVariableNames berisi kumpulan nama variabel yang digunakan dalam segmen jalur dalam string templat.

IsEquivalentTo(UriTemplate) mengambil UriTemplate sebagai parameter dan mengembalikan nilai Boolean yang menentukan apakah kedua templat tersebut setara. Untuk informasi selengkapnya, lihat bagian Kesetaraan Templat setelahnya dalam topik ini.

UriTemplate dirancang untuk bekerja dengan skema URI apa pun yang sesuai dengan tata bahasa URI HTTP. Berikut ini adalah contoh skema URI yang didukung.

  • http://

  • https://

  • net.tcp://

  • net.pipe://

  • sb://

Skema seperti file:// dan urn:// tidak sesuai dengan tata bahasa HTTP URI dan menyebabkan hasil yang tidak dapat diprediksi saat digunakan dengan templat URI.

Sintaks String Templat

Templat memiliki tiga bagian: jalur, kueri opsional, dan fragmen opsional. Sebagai contoh, lihat templat berikut:

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

Jalur terdiri dari "/weather/{state}/{city}", kueri terdiri dari "?forecast={length}, dan fragmen terdiri dari "#frag1".

Garis miring di awal dan akhir bersifat opsional dalam ekspresi jalur. Ekspresi kueri dan fragmen dapat dihilangkan sepenuhnya. Jalur terdiri dari serangkaian segmen yang dibatasi oleh '/', setiap segmen dapat memiliki nilai harfiah, nama variabel (ditulis dalam {kurung kurawal}), atau wildcard (ditulis sebagai '*'). Pada templat sebelumnya, segmen "\weather\ adalah nilai harfiah sedangkan "{state}" dan "{city}" adalah variabel. Variabel mengambil namanya dari isi kurung kurawalnya dan nantinya dapat diganti dengan nilai konkret untuk membuat URI tertutup. Wildcardi bersifat opsional, tetapi hanya dapat muncul di akhir URI, yang secara logis cocok dengan "jalur lainnya".

Ekspresi kueri, jika ada, menentukan serangkaian pasangan nama/nilai yang tidak diurutkan yang dibatasi oleh '&'. Elemen ekspresi kueri dapat berupa pasangan harfiah (x=2) atau pasangan variabel (x={var}). Hanya sisi kanan kueri yang dapat memiliki ekspresi variabel. ({someName} = {someValue} tidak diperbolehkan. Nilai yang tidak berpasangan (?x) tidak diizinkan. Tidak ada perbedaan antara ekspresi kueri kosong dan ekspresi kueri yang hanya terdiri dari satu '?' (keduanya berarti "kueri apa pun").

Ekspresi fragmen dapat terdiri dari nilai harfiah, tidak ada variabel yang diizinkan.

Semua nama variabel templat dalam string templat harus unik. Nama variabel templat tidak peka huruf besar/kecil.

Contoh string templat yang valid:

  • ""

  • "/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}"

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

Contoh string templat yang tidak valid:

  • "{shoe}/{SHOE}/x=2" – Nama variabel duplikat.

  • "{shoe}/boat/?bed={shoe}" – Nama variabel duplikat.

  • "?x=2&x=3" – Pasangan nama/nilai dalam string kueri harus unik, bahkan jika itu harfiah.

  • "?x=2&" – String kueri salah bentuk.

  • "?2&x={shoe}" – String kueri harus berupa pasangan nama/nilai.

  • "?y=2&&X=3" – String kueri harus berupa pasangan nilai nama, nama tidak dapat dimulai dengan '&'.

Segmen Jalur Campuran

Segmen jalur campuran memungkinkan segmen jalur URI tunggal berisi banyak variabel serta variabel yang digabungkan dengan harfiah. Berikut ini adalah contoh segmen jalur campuran yang valid.

  • /filename.{ext}/

  • /{filename}.jpg/

  • /{filename}.{ext}/

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

Berikut ini adalah contoh segmen jalur yang tidak valid.

  • /{} - Variabel harus diberi nama.

  • /{shoe}{boat} - Variabel harus dipisahkan oleh harfiah.

Segmen Jalur Pencocokan dan Campuran

Segmen jalur campuran memungkinkan Anda untuk menentukan UriTemplate yang memiliki banyak variabel dalam satu segmen jalur. Misalnya, dalam string templat berikut: "Addresses/{state}. {city}" dua variabel (negara bagian dan kota) didefinisikan dalam segmen yang sama. Templat ini akan cocok dengan URL seperti http://example.com/Washington.Redmond tetapi juga akan cocok dengan URL seperti http://example.com/Washington.Redmond.Microsoft. Dalam kasus terakhir, variabel negara bagian akan berisi "Washington" dan variabel kota akan berisi "Redmond.Microsoft". Dalam hal ini, teks apa pun (kecuali '/') akan cocok dengan variabel {city}. Jika Anda menginginkan templat yang tidak cocok dengan teks "ekstra", tempatkan variabel di segmen templat terpisah, misalnya: "Addresses/{state}/{city}.

Segmen Wildcard Bernama

Segmen wildcard bernama adalah segmen variabel jalur apa pun yang nama variabelnya dimulai dengan wildcard '*'. String templat berikut berisi segmen wildcard bernama "shoe".

"literal/{*shoe}"

Segmen wildcard harus mengikuti aturan berikut:

  • Paling banyak ada satu segmen wildcard bernama untuk setiap string templat.

  • Segmen wildcard bernama harus muncul di segmen paling kanan di jalur tersebut.

  • Segmen wildcard bernama tidak dapat berdampingan dengan segmen wildcard anonim dalam string templat yang sama.

  • Nama segmen wildcard bernama harus unik.

  • Segmen wildcard bernama tidak boleh memiliki nilai default.

  • Segmen wildcard bernama tidak dapat diakhir dengan "/".

Nilai Variabel Default

Nilai variabel default memungkinkan Anda menentukan nilai default untuk variabel dalam templat. Variabel default dapat ditentukan dengan kurung kurawal yang mendeklarasikan variabel atau sebagai kumpulan yang diteruskan ke konstruktor UriTemplate. Templat berikut ini memperlihatkan dua cara untuk menentukan UriTemplate dengan variabel dengan nilai default.

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

Templat ini mendeklarasikan variabel bernama a dengan nilai default 1 dan variabel bernama b dengan nilai default 5.

Catatan

Hanya variabel segmen jalur yang diizinkan untuk memiliki nilai default. Variabel string kueri, variabel segmen campuran, dan variabel wildcard bernama tidak diizinkan memiliki nilai default.

Kode berikut menunjukkan bagaimana nilai variabel default ditangani saat mencocokkan 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

Catatan

URI seperti http://localhost:8000/// tidak cocok dengan templat yang tercantum dalam kode sebelumnya, namun URI seperti http://localhost:8000/ cocok dengan templat yang tercantum sebelumnya.

Kode berikut menunjukkan bagaimana nilai variabel default ditangani saat membuat URI dengan templat.

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  

Ketika variabel diberikan nilai default null, ada beberapa batasan tambahan. Variabel dapat memiliki nilai default null jika variabel terkandung dalam segmen paling kanan dari string templat atau jika semua segmen di sebelah kanan segmen memiliki nilai default null. Berikut ini adalah string templat yang valid dengan nilai default null:

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

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

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

Berikut ini adalah string templat yang tidak valid dengan nilai default 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

Nilai Default dan Pencocokan

Saat mencocokkan kandidat URI dengan templat yang memiliki nilai default, nilai default ditempatkan dalam kumpulan BoundVariables jika nilai tidak ditentukan dalam kandidat URI.

Kesetaraan Templat

Dua templat dikatakan setara secara struktural ketika semua harfiah templat cocok dan mereka memiliki variabel dalam segmen yang sama. Misalnya, templat berikut secara struktural setara:

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

Beberapa hal yang perlu diperhatikan:

  • Jika templat berisi garis miring di depan, hanya yang pertama yang diabaikan.

  • Saat membandingkan string templat untuk kesetaraan struktural, kasus diabaikan untuk nama variabel dan segmen jalur, string kueri peka huruf besar/kecil.

  • String kueri tidak diurutkan.

UriTemplateTable

Kelas UriTemplateTable mewakili tabel objek UriTemplate asosiatif yang terikat ke objek yang dipilih pengembang. UriTemplateTable harus berisi setidaknya satu UriTemplate sebelum panggilan MakeReadOnly(Boolean). Konten UriTemplateTable dapat diubah hingga MakeReadOnly(Boolean) dipanggil. Validasi dilakukan ketika MakeReadOnly(Boolean) dipanggil. Jenis validasi yang dilakukan tergantung pada nilai parameter allowMultiple ke MakeReadOnly(Boolean).

Ketika MakeReadOnly(Boolean) dipanggil melewati false, pemeriksaan UriTemplateTable untuk memastikan tidak ada templat dalam tabel. Jika menemukan templat yang setara secara struktural, itu akan menampilkan pengecualian. Ini digunakan bersama dengan MatchSingle(Uri) ketika Anda ingin memastikan hanya satu templat yang cocok dengan URI yang masuk.

Ketika MakeReadOnly(Boolean) disebut melewati true, UriTemplateTable memungkinkan beberapa templat yang setara secara struktural terkandung dalam UriTemplateTable.

Jika sekumpulan objek UriTemplate yang ditambahkan ke UriTemplateTable berisi string kueri, objek tersebut tidak boleh ambigu. String kueri identik diizinkan.

Catatan

Sementara UriTemplateTable memungkinkan alamat dasar yang menggunakan skema selain HTTP, skema dan nomor port diabaikan saat mencocokkan kandidat URI dengan templat.

Ambiguitas String Kueri

Templat yang berbagi jalur yang setara berisi string kueri yang ambigu jika ada URI yang cocok dengan lebih dari satu templat.

Kumpulan string kueri berikut ini tidak ambigu didalamnya:

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

Kumpulan templat string kueri berikut ini ambigu didalam:

  • ?x=1

  • ?x={var}

"x=1" - Cocok dengan kedua templat.

  • ?x=1

  • ?y=2

"x=1&y=2" cocok dengan kedua templat. Hal ini dikarenakan string kueri mungkin berisi lebih banyak variabel string kueri maka templatnya yang cocok.

  • ?x=1

  • ?x=1&y={var}

"x=1&y=3" cocok dengan kedua templat.

  • ?x=3&y=4

  • ?x=3&z=5

Catatan

Karakter á dan Á dianggap sebagai karakter yang berbeda ketika muncul sebagai bagian dari jalur URI atau UriTemplate segmen jalur harfiah (tetapi karakter a dan A dianggap sama). Karakter á dan Á dianggap sebagai karakter yang sama ketika muncul sebagai bagian dari {variableName} UriTemplate atau string kueri (dan a dan A juga dianggap sebagai karakter yang sama).

Lihat juga