UriTemplate 및 UriTemplateTable

웹 개발자는 서비스가 응답하는 URI의 모양과 레이아웃에 대해 설명할 수 있어야 합니다. WCF(Windows Communication Foundation)에서는 개발자가 URI를 제어할 수 있도록 두 개의 새 클래스가 추가되었습니다. UriTemplateUriTemplateTable은 WCF에서 URI 기반 발송 엔진의 기본이 됩니다. 이러한 클래스를 자체적으로 사용하면 개발자가 WCF 서비스를 구현하지 않고도 URI 매핑 메커니즘과 템플릿을 활용할 수 있습니다.

템플릿

템플릿을 사용하면 상대 URI 집합을 설명할 수 있습니다. 다음 표의 URI 템플릿 집합은 다양한 날씨 정보를 검색하는 시스템을 정의하는 방법을 보여 줍니다.

데이터 템플릿

전국 예보

weather/national

시/도 예보

weather/{state}

구/군/시 예보

weather/{state}/{city}

활동 예보

weather/{state}/{city}/{activity}

이 표에서는 구조적으로 비슷한 URI 집합을 보여 줍니다. 각 항목은 URI 템플릿에 해당합니다. 중괄호로 묶인 세그먼트는 변수를 설명하며, 중괄호가 없는 세그먼트는 리터럴 문자열을 설명합니다. 개발자는 WCF 템플릿 클래스를 사용하여 수신 URI(예: "/weather/wa/seattle/cycling")를 가져와서 해당 URI를 설명하는 템플릿("/weather/{state}/{city}/{activity}")과 일치시킬 수 있습니다.

UriTemplate

UriTemplate은 URI 템플릿을 캡슐화하는 클래스입니다. 생성자는 템플릿을 정의하는 문자열 매개 변수를 사용합니다. 이 문자열에는 다음 단원에 설명된 형식의 템플릿이 포함되어 있습니다. UriTemplate 클래스는 수신 URI를 템플릿에 일치시키고, 템플릿에서 URI를 생성하고, 템플릿에 사용되는 변수 이름 컬렉션을 검색하고, 두 템플릿이 동일한지 확인하고, 템플릿의 문자열을 반환할 수 있는 메서드를 제공합니다.

Match는 기본 주소와 후보 URI을 사용하고 URI을 템플릿에 일치시키려고 시도합니다. 일치가 성공적으로 수행되면 UriTemplateMatch 인스턴스가 반환됩니다. UriTemplateMatch 개체에는 기본 URI, 후보 URI, 쿼리 매개 변수의 이름/값 컬렉션, 상대 경로 세그먼트 배열, 일치된 변수의 이름/값 컬렉션, 일치를 수행하는 데 사용된 UriTemplate 인스턴스, 후보 URI의 일치하지 않는 부분을 포함하는 문자열(템플릿에 와일드카드가 있는 경우에 사용됨) 및 템플릿에 연결된 개체 등이 포함되어 있습니다.

참고

UriTemplate 클래스는 후보 URI를 템플릿에 일치시킬 때 구성표 및 포트 번호를 무시합니다.

템플릿에서 URI를 생성할 수 있게 해주는 두 메서드(BindByNameBindByPosition)가 있습니다. BindByName은 기본 주소와 매개 변수의 이름/값 컬렉션을 사용합니다. 템플릿이 바인딩되면 이러한 매개 변수가 변수를 대체합니다. BindByPosition은 이름/값 쌍을 가져와서 왼쪽에서 오른쪽으로 대체합니다.

ToString은 템플릿 문자열을 반환합니다.

PathSegmentVariableNames 속성은 템플릿 문자열의 경로 세그먼트에 사용되는 변수 이름 컬렉션을 포함합니다.

IsEquivalentToUriTemplate을 매개 변수로 사용하고 두 템플릿이 일치하는지 여부를 지정하는 부울 값을 반환합니다. 자세한 내용은 이 항목의 뒷부분에 있는 템플릿 동등성 단원을 참조하십시오.

T:System.UriTemplate은 HTTP URI 문법을 따르는 모든 URI 구성표와 함께 사용되도록 만들어졌습니다. 다음은 지원되는 URI 구성표의 예입니다.

  • http://
  • https://
  • net.tcp://
  • net.pipe://
  • sb://

file:// 및 urn://와 같은 구성표는 HTTP URI 문법을 따르지 않으며 URI 템플릿과 함께 사용되면 예측할 수 없는 결과를 발생시킵니다.

템플릿 문자열 구문

템플릿에는 경로, 선택적 쿼리 및 선택적 조각의 세 부분이 있습니다. 예제를 보려면 다음 템플릿을 참조하십시오.

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

경로는 "/weather/{state}/{city}"로 구성되고, 쿼리는 "?forecast={length}"로 구성되며, 조각은 "#frag1"로 구성됩니다.

선행/후행 슬래시는 경로 식에서 선택적 요소입니다. 쿼리 식과 조각 식 모두 완전히 생략할 수 있습니다. 경로는 '/'로 구분된 세그먼트로 구성되며, 각 세그먼트는 리터럴 값, 변수 이름({중괄호}로 표시) 또는 와일드카드('*'로 표시)를 포함할 수 있습니다. 이전 템플릿에서 "\weather\ 세그먼트는 리터럴 값이고 "{state}" 및 "{city}"는 변수입니다. 변수는 중괄호 안의 내용에서 이름을 가져온 다음 나중에 구체적인 값으로 대체되어 닫힌 URI를 만들 수 있습니다. 와일드카드는 선택적 요소이지만 URI의 끝에만 표시될 수 있고, "경로의 나머지 부분"과 논리적으로 일치합니다.

쿼리 식(있는 경우)은 순서가 지정되지 않은, '&'로 구분된 이름/값 쌍을 지정합니다. 쿼리 식의 요소는 리터럴 쌍(x=2) 또는 변수 쌍(x={var})이 될 수 있습니다. 쿼리의 오른쪽에만 변수 식을 포함할 수 있습니다. ({someName} = {someValue}는 허용되지 않습니다. 짝이 없는 값(?x)은 사용할 수 없습니다. 빈 쿼리 식과 단일 '?' 만으로 구성된 쿼리 식은 차이가 없습니다. 모두 "any query"를 의미합니다.

조각 식은 리터럴 값으로 구성될 수 있으며 변수는 사용할 수 없습니다.

템플릿 문자열 내의 모든 템플릿 변수 이름은 고유해야 합니다. 템플릿 변수 이름은 대/소문자를 구분하지 않습니다.

올바른 템플릿 문자열의 예:

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

잘못된 템플릿 문자열의 예:

  • “{shoe}/{SHOE}/x=2” – 중복 변수 이름
  • “{shoe}/boat/?bed={shoe}” – 중복 변수 이름
  • “?x=2&x=3” - 쿼리 문자열의 이름/값 쌍은 리터럴인 경우에도 고유해야 합니다.
  • “?x=2&” - 쿼리 문자열의 형식이 잘못되었습니다.
  • “?2&x={shoe}” - 쿼리 문자열은 이름/값 쌍이어야 합니다.
  • “?y=2&&X=3” - 쿼리 문자열은 이름/값 쌍이어야 하며, 이름은 '&'로 시작할 수 없습니다.

복합 경로 세그먼트

복합 경로 세그먼트를 사용하면 단일 URI 경로 세그먼트에 여러 변수는 물론 리터럴과 함께 사용하는 변수를 포함할 수 있습니다. 다음은 올바른 복합 경로 세그먼트의 예입니다.

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

다음은 잘못된 경로 세그먼트의 예입니다.

  • /{} - 변수의 이름을 지정해야 합니다.
  • /{shoe}{boat} - 변수를 리터럴로 구분해야 합니다.

명명된 와일드카드 세그먼트

명명된 와일드카드 세그먼트는 변수 이름이 와일드카드 문자 ‘*’로 시작하는 경로 변수 세그먼트입니다. 다음 템플릿 문자열에는 이름이 “shoe”인 명명된 와일드카드 세그먼트가 포함되어 있습니다.

“literal/{*shoe}”

와일드카드 세그먼트는 다음 규칙을 따라야 합니다.

  • 각각의 템플릿 문자열에 대해서는 명명된 와일드카드 세그먼트가 최대 하나만 있을 수 있습니다.
  • 명명된 와일드카드 세그먼트는 경로의 맨 오른쪽 세그먼트에 표시되어야 합니다.
  • 명명된 와일드카드 세그먼트는 동일한 템플릿 문자열 내에서 익명 와일드카드 세그먼트와 함께 사용할 수 없습니다.
  • 명명된 와일드카드 세그먼트의 이름은 고유해야 합니다.
  • 명명된 와일드카드 세그먼트는 기본값을 가질 수 없습니다.
  • 명명된 와일드카드 세그먼트는 “/”로 끝날 수 없습니다.

기본 변수 값

기본 변수 값을 사용하면 템플릿 내에서 변수에 대한 기본값을 지정할 수 있습니다. 기본 변수는 변수를 UriTemplate 생성자에 전달된 컬렉션으로 선언하는 중괄호로 지정할 수 있습니다. 다음 템플릿에서는 기본값을 포함하는 변수를 사용하여 UriTemplate을 지정하는 두 가지 방법을 보여 줍니다.

UriTemplate t = new UriTemplate(“/test/{a=1}/{b=5}”);
Dictionary<string,string> defVals = new Dictionary<string,string> {{"a","1"}, {"b", "5"}};
UriTemplate t = new UriTemplate("/test/{a}/{b}", defVals);

이 템플릿은 기본값 1을 사용하여 이름이 a인 변수를 선언하고 기본값 5를 사용하여 이름이 b인 변수를 선언합니다.

경로 세그먼트 변수만 기본값을 가질 수 있습니다. 쿼리 문자열 변수, 복합 세그먼트 변수 및 명명된 와일드카드 변수는 기본값을 가질 수 없습니다.

다음 코드에서는 후보 URI와 일치할 때 기본 변수 값을 처리하는 방법을 보여 줍니다.

Uri baseAddress = new Uri("https://localhost:8000");
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

참고

https://localhost:8000///과 같은 URI는 위의 코드에 나열된 템플릿과 일치하지 않지만 https://localhost:8000/과 같은 URI는 일치합니다.

다음 코드에서는 템플릿을 사용하여 URI를 만들 때 기본 변수 값을 처리하는 방법을 보여 줍니다.

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 above code is
// BaseAddress: https://localhost:8000/
// Template: /test/{a}/{b}
// Values:
//     Key = a, Value = 10
// Bound URI: https://localhost:8000/test/10/5

변수에 기본값 null이 지정되면 약간의 추가 제약 조건이 있습니다. 템플릿 문자열의 맨 오른쪽 세그먼트 내에 변수가 포함되어 있는 경우 또는 세그먼트 오른쪽에 있는 모든 세그먼트가 기본값 null을 가지는 경우 변수가 기본값 null을 가질 수 있습니다. 다음은 기본값이 null인 올바른 템플릿 문자열입니다.

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

다음은 기본값이 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
    

기본값 및 일치

기본값을 가진 템플릿을 사용하여 후보 URI와 일치시킬 때 후보 URI에 값이 지정되지 않은 경우 BoundVariables 컬렉션에 기본값이 지정됩니다.

템플릿 동등성

템플릿의 모든 리터럴이 일치하고 동일한 세그먼트에 변수가 있는 경우 두 템플릿이 구조적으로 동등한 것으로 간주됩니다. 예를 들어 다음 템플릿은 구조적으로 동등합니다.

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

다음 몇 가지 사항에 주의해야 합니다.

  • 템플릿에 선행 슬래시가 있는 경우 첫 번째 슬래시만 무시됩니다.
  • 템플릿 문자열의 구조적 동등성을 비교할 때 변수 이름과 경로 세그먼트의 대/소문자는 무시되고, 쿼리 문자열의 대/소문자는 구분됩니다.
  • 쿼리 문자열은 순서가 없습니다.

UriTemplateTable

UriTemplateTable 클래스는 개발자의 선택 개체에 바인딩된 UriTemplate 개체의 연결 테이블을 나타냅니다. MakeReadOnly를 호출하기 전에 UriTemplateTable에 하나 이상의 UriTemplate이 있어야 합니다. MakeReadOnly가 호출되기 이전에는 UriTemplateTable의 내용을 변경할 수 있습니다. MakeReadOnly가 호출되면 유효성 검사가 수행됩니다. 수행되는 유효성 검사 형식은 MakeReadOnly에 대한 allowMultiple 매개 변수 값에 따라 다릅니다.

false를 전달하여 MakeReadOnly를 호출하면 UriTemplateTable에서 테이블에 템플릿이 없는지 확인합니다. 구조적으로 동등한 템플릿이 있으면 예외를 throw합니다. 하나의 템플릿만 수신 URI와 일치하게 하려면 MatchSingle과 함께 사용합니다.

true를 전달하여 MakeReadOnly를 호출하면 UriTemplateTable에서 UriTemplateTable에 구조적으로 동등한 여러 템플릿을 포함하도록 허용합니다.

UriTemplateTable에 추가된 UriTemplate 개체 집합에 쿼리 문자열이 있는 경우 해당 문자열은 모호하지 않아야 합니다. 동일한 쿼리 문자열을 사용할 수 있습니다.

참고

UriTemplateTable에서 HTTP가 아닌 구성표를 사용하는 기본 주소를 허용하는 동안 후보 URI를 템플릿에 일치시킬 때 구성표 및 포트 번호가 무시됩니다.

쿼리 문자열 모호성

동일한 경로를 공유하는 템플릿은 여러 템플릿과 일치하는 URI가 있을 경우 모호한 쿼리 문자열을 포함합니다.

다음 쿼리 문자열 집합은 모호하지 않습니다.

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

다음 쿼리 문자열 템플릿 집합은 모호합니다.

  • ?x=1
  • ?x={var}

"x=1" - 두 템플릿 모두와 일치합니다.

  • ?x=1
  • ?y=2

"x=1&y=2"는 두 템플릿 모두와 일치합니다. 쿼리 문자열이 일치하는 템플릿보다 더 많은 쿼리 문자열 변수를 포함할 수 있기 때문입니다.

  • ?x=1
  • ?x=1&y={var}

"x=1&y=3"은 두 템플릿 모두와 일치합니다.

  • ?x=3&y=4
  • ?x=3&z=5

참고

문자 á와 Á는 URI 경로 또는 UriTemplate 경로 세그먼트 리터럴에 표시될 경우 서로 다른 문자로 간주됩니다. 그러나 문자 a와 A는 동일한 문자로 간주됩니다. 문자 á와 Á는 UriTemplate {variableName} 또는 쿼리 문자열에 표시될 경우 동일한 문자로 간주됩니다. a와 A도 동일한 문자로 간주됩니다.

참고 항목

개념

WCF 웹 프로그래밍 모델 개요
WCF 웹 프로그래밍 개체 모델

기타 리소스

UriTemplate Sample
UriTemplate Table Sample
UriTemplate Table Dispatcher Sample