URI and UriTemplates
Microsoft has provided support for URIs since .NET Framework v1.0. The System.Uri class allows developers to define and parse basic information within a URI. This class allows developers to access information such as the scheme, path, and hostname. This is great for passing a URI to Web clients such as the System.Windows.Forms.WebBrowser control or the System.Net.WebClient class. A companion to the System.Uri class is the System.UriBuilder class. This class provides a way to modify the System.Uri class without creating another System.Uri instance. These classes are the foundation for working with URIs based on the HTTP protocol. Additional capabilities are needed to support the REST architectural style used by developers today.
Table 13.1 showed that developers embed parameters in URIs as either query string parameters or as parts of the path. The System.Uri or System.UriBuilder classes do not allow building and parsing of URIs based on this approach. Another approach that has been used is to build and parse URIs based on patterns that specify named tokens. The tokens represent the parameters that are needed to build URIs using logical substitution. They also define how parameters can be parsed from URIs. .NET Framework 3.5 introduces a new class called the System.UriTemplate that provides a consistent way for building and parsing URIs based on patterns. This class defines a pattern based on named tokens. Tokens are represented in curly braces within a pattern. For example, the pattern /finance/info?q={symbol} specifies a stock symbol that is sent as a query string parameter. Named tokens can also be embedded as a part of the URI path and are not limited to query string parameters. For example, the following pattern, /browse/{word}, specifies a parameter within the URI path. System.Uri instances can be built or parsed based on these patterns. We will now examine how we can use the System.UriTemplate class do this.
Building URIs
Listing 13.1 shows two examples of how we can build System.Uri instances based on System.UriTemplate classes. The first example uses the BindByPosition method to create a System.Uri instance to retrieve Yahoo! stock quotes. The second example uses the BindByName method to pass a collection of name/value pairs to create a System.Uri instance to retrieve Google stock quotes.
Listing 13.1. Binding Parameters with UriTemplate
using System; using System.Collections.Specialized; namespace EssentialWCF { class Program { static void Main(string[] args) { string symbol = "MSFT"; // BindByPosition Uri YahooStockBaseUri = new Uri("http://finance.yahoo.com"); UriTemplate YahooStockUriTemplate = new UriTemplate("/d/quotes?s={symbol}&f=sl1t1d1"); Uri YahooStockUri = YahooStockUriTemplate.BindByPosition( YahooStockBaseUri, symbol); Console.WriteLine(YahooStockUri.ToString()); // BindByName Uri GoogleStockBaseUri = new Uri("http://finance.google.com"); UriTemplate GoogleStockUriTemplate = new UriTemplate("/finance/info?q={symbol}"); NameValueCollection GoogleParams = new NameValueCollection(); GoogleParams.Add("symbol", symbol); Uri GoogleStockUri = GoogleStockUriTemplate.BindByName( GoogleStockBaseUri, GoogleParams); Console.WriteLine(GoogleStockUri.ToString()); Console.ReadLine(); } } }
Parsing URIs
We just saw how easy it was to create System.Uri instances based on patterns. Listing 13.2 shows how we can take existing URIs and parse out parameters. Again we have two examples. The first example shows how we can parse out parameters based on query string parameters. The second example shows how we can parse out parameters based on a path. In both cases, we are able to extract a set of name/value pairs based on a pattern. We will see in the "Creating Operations for the Web" section how the UriTemplate can be used to dispatch Web service methods based on URIs.
Listing 13.2. Matching Parameters with UriTemplate
using System; namespace UriTemplate102 { class Program { static void Main(string[] args) { Uri YahooBaseUri = new Uri("http://finance.yahoo.com"); UriTemplate YahooStockTemplate = new UriTemplate("/d/quotes?s={symbol}"); Uri YahooStockUri = new Uri("http://finance.yahoo.com/d/quotes?s=MSFT&f=spt1d"); UriTemplateMatch match = YahooStockTemplate.Match(YahooBaseUri, YahooStockUri); foreach (string key in match.BoundVariables.Keys) Console.WriteLine(String.Format("{0}: {1}", key, match.BoundVariables[key])); Console.WriteLine(); Uri ReferenceDotComBaseUri = new Uri("http://dictionary.reference.com"); UriTemplate ReferenceDotComTemplate = new UriTemplate("/browse/{word}"); Uri ReferenceDotComUri = new Uri("http://dictionary.reference.com/browse/opaque"); match = ReferenceDotComTemplate.Match(ReferenceDotComBaseUri ReferenceDotComUri); foreach (string key in match.BoundVariables.Keys) Console.WriteLine(String.Format("{0}: {1}", key, match.BoundVariables[key])); Console.ReadLine(); } } }