HTTP Web Programming with WCF 3.5: Creating a Template based URI
The .NET Framework 3.5 include support for web development using WCF.
In this post I will show how to create template based URI and to use them.
UriTemplate and UriTemplateMatch types
A UriTemplate is composed of two parts: a path and a query. The following examples show valid templates:
finance/nasdaq/quote
finance/{market}/{quote}
finance/*
finance/{market}/{quote}?s=MSFT
finance/{market}/{quote}?s={ticket}
Elemets of the query must consists of pairs: s=MSFT or s={ticket}.
The following sample show how to create a UriTemplate, bind and match it to a candidate URI.
UriTemplate template = new UriTemplate("finance/{market}/quote?s={ticket}");
Uri prefix = new Uri("http://localhost:8080");
foreach (String name in template.PathSegmentVariableNames)
{
Console.WriteLine("{0} ", name); // MARKET
}
foreach (String name in template.QueryValueVariableNames)
{
Console.WriteLine("{0} ", name); // TICKET
}
Two ways for binding the uri template:
// 1) http://localhost:8080/finance/nasdaq/quote?s=MSFT
Uri positionalUri = template.BindByPosition(prefix, "nasdaq", "MSFT");
Console.WriteLine("{0}", positionalUri);
// 2) http://localhost:8080/finance/nasdaq/quote?s=MSFT
NameValueCollection parameters = new NameValueCollection();
parameters.Add("market", "nasdaq");
parameters.Add("ticket", "MSFT");
Uri namedUri = template.BindByName(prefix, parameters);
Console.WriteLine("{0}", namedUri);
URI Template Match:
Uri fullUri = new Uri("http://localhost/finance/nasdaq/quote?s=MSFT");
UriTemplateMatch results = template.Match(prefix, fullUri);
// MARKET: nasdaq
// TICKET: MSFT
if (results != null)
{
foreach (String variableName in results.BoundVariables.Keys)
{
Console.WriteLine("{0}: {1}\n", variableName, results.BoundVariables[variableName]);
}
}
// nasdaq
String market = results.BoundVariables["market"];
// MSTF
String ticket = results.BoundVariables["ticket"];
WebGet and WebInvoke
The following code describe a service contract for the WCF service itself:
[ServiceContract]
public interface IStockService
{
[OperationContract]
[WebGet(UriTemplate = "finance/{market}/quote?s={ticket}")]
String GetQuote(String market, String ticket);
[OperationContract]
[WebInvoke(UriTemplate = "Hello", Method="POST")]
String GetPrice();
}
For each parameter in the UriTemplate, there is a corresponding parameter in the GetQuote method.
The implementation of the web service is simple:
public class StockService : IStockService
{
public String GetQuote(String market, String ticket)
{
return "33.91";
}
public String GetPrice()
{
return "33";
}
}
WCF Hosting using the WebHttpBehavior and WebHttpBinding:
using (ServiceHost host = new ServiceHost(typeof(StockService),
new Uri("http://localhost:8080/")))
{
WebHttpBinding binding = new WebHttpBinding();
ServiceEndpoint ep = host.AddServiceEndpoint(
typeof(IStockService), binding, String.Empty);
ep.Behaviors.Add(new WebHttpBehavior());
host.Open();
Console.ReadKey();
}
The Client
And finally, the client can be any http client as show in the following sample code:
using (WebClient client = new WebClient())
{
String address = "http://localhost:8080/finance/nasdaq/quote?s=MSFT";
String price = client.DownloadString(address);
// Results:
// <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">33.91</string>
String address2 = "http://localhost:8080/Hello";
client.Headers.Add(HttpRequestHeader.ContentType, "text/xml");
String price2 = client.UploadString(address2, "POST", "MSFT");
// Result:
// <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">33</string>
}
You can download here the source code.