In some previous posts, I highlighted some of the major functionality for UriTemplate and UriTemplateMatch. Before I move on to the new functionality that really begins to consume these building blocks, it only seemed fair to also point out another useful new class related to working with uris. As you could probably judge by the title of the post, I am referring to the UriTemplateTable.
So, what exactly does UriTemplateTable do for you? You can essentially think of it as UriTemplateMatch on steroids. The name really gives it away. The UriTemplateTable provides support for storing a set of related UriTemplates. A candidate uri can be run against the UriTemplate objects within the table to determine the most appropriate match or matches.
Let's look at some code to clarify what I am talking about. Here is an example using Keith Elder's Flickr archive.
// Setup a template table for the base address.
UriTemplateTable table = new UriTemplateTable(new Uri("http://www.flickr.com/photos/keithelder/archives"));
// Add the templates to the table.
table.KeyValuePairs.Add(
new KeyValuePair<UriTemplate, object>(
new UriTemplate("{takenOrPosted}/{year}/calendar/"),
"some info about the template"));
table.KeyValuePairs.Add(
new KeyValuePair<UriTemplate, object>(
new UriTemplate("takenOrPosted}/{year}/{month}/calendar/"),
"more info about the template"));
table.KeyValuePairs.Add(
new KeyValuePair<UriTemplate, object>(
new UriTemplate("takenOrPosted}/{year}/{month}/{day}/"),
"yet even more info about the template"));
So far, all we have done is setup a UriTemplateTable that contains a set of related UriTemplates. If you look closely, you can see there are some similarities between the UriTemplates. Each one adds an extra level of detail to the possible date. This could have been taken a step further and the user made into a parameter as well, but we are keeping this example specific to Zorka. :)
You may be wondering what is this KeyValuePair business all about? This is one of the other nice features in UriTemplateTable. The UriTemplates are stored as an ILIst of KeyValuePairs. The key is the UriTemplate and the value is an object of your choosing. Unfortunately, you are forced to use the Object type rather than supplying a type parameter. Regardless, this could potentially be quite useful. You can essentially store any information that you deem to be relevant with each instance of UriTemplate.
Now that a UriTemplateTable is setup with our UriTemplates, it's time to unleash its matching capabilities.
// Create a candidate uri for a match.
Uri candidateUri = new Uri("http://www.flickr.com/photos/keithelder/archives/date-posted/2007/01/calendar/");
// Tell the table to match against the uri.
Collection<UriTemplateMatch> matchResults = table.Match(candidateUri);
// Check if a match was found.
if ((matchResults != null) && (matchResults.Count > 0))
{
// Write out each result.
foreach (UriTemplateMatch match in matchResults)
{
Console.WriteLine();
Console.WriteLine("Template: " + match.Template.ToString());
Console.WriteLine("Parameters");
foreach (string key in match.BoundVariables.Keys)
{
Console.WriteLine(" Name: {0} | Value: {1}", key, match.BoundVariables[key]);
}
}
}
Output:
Template: {takenOrPosted}/{year}/{month}/calendar/
Parameters
Name: TAKENORPOSTED | Value: date-posted
Name: YEAR | Value: 2007
Name: MONTH | Value: 01
Notice the Match method returns a Collection of UriTemplateMatch objects. This is a result of the possibility that more than one template could match against the candidate uri. It may be necessary to do some additional work to narrow down your results, but it's better than the alternative of manually writing the code to support this behavior. There is also a MatchSingle method that will attempt to return only one match. However, it will result in a UriTemplateMatchException if more than one match is found. So, proceed with caution.
As a final note, there is another method that I haven't included in the sample code named MakeReadOnly. As the name suggests, it prevents any additional changes from being made to the UriTemplateTable when true is passed as a parameter. However, an exception will be thrown if you pass true and the UriTemplateTable contains more than one UriTemplate that is structurally equivalent.
In the next WCF 3.5 post, I will begin getting into how these new Uri support classes are leveraged by WCF's new features.