Lately, I have been neglecting my coding duties a bit in order to go out and get drunk actually. Which I have become a bit tired of now, so I am back onto the code, which is a good place.
Now I am in the process of creating another article, and though I can not reveal what I am working on, as there is a competition involved, which I would like to have a pop at, I thought I may share bits of information about parts of it along the way.
I can say that I am using some new WCF stuff that came with .NET 3.5, namely the System.ServiceModel.Web namespace
which allows us to create RESTful WCF services.
For those that do not know what REST is, here is what Wikipedia has to say about it.
"Representational state transfer (REST) is a style of software architecture for distributed hypermedia systems such as the World Wide Web. As such, it is not strictly a method for building "web services." The terms "representational state transfer" and "REST" were introduced in 2000 in the doctoral dissertation of Roy Fielding,[1] one of the principal authors of the Hypertext Transfer Protocol (HTTP) specification.
REST strictly refers to a collection of network architecture principles which outline how resources are defined and addressed. The term is often used in a looser sense to describe any simple interface which transmits domain-specific data over HTTP without an additional messaging layer such as SOAP or session tracking via HTTP cookies. These two meanings can conflict as well as overlap. It is possible to design a software system in accordance with Fielding’s REST architectural style without using HTTP and without interacting with the World Wide Web.[2] It is also possible to design simple XML+HTTP interfaces which do not conform to REST principles, and instead follow a model of remote procedure call. The difference between the uses of the term "REST" therefore causes some confusion in technical discussions.
Systems which follow Fielding’s REST principles are often referred to as "RESTful"."
http://en.wikipedia.org/wiki/Representational_State_Transfer
Basically what it means as a WCF developer is that you will expose resources which are accessible via Urls, which means all a client needs to use your service is a browser.
The schedule of posts is probably going to be something like this:
- The new RESTful WCF attributes (this article)
- Serialization options
- Hosting
- CRUD operations using RESTful WCF
Ok so let's get on to some code.
This blog post will simply cover the new attributes that enable RESTful WCF.
In fact, there are really only 2 attributes that in my mind are the lynchpins for the whole RESTful way of doing things using WCF. These attributes are:
"The WebGetAttribute attribute is applied to a service operation in addition to the OperationContractAttribute and associates the operation with a UriTemplate as well as the HTTP protocol Get verb. The association with HTTP Get verb means that the operation is used to retrieve information from the service. The WebGetAttribute attribute is a passive operation behavior (the IOperationBehavior methods do nothing) that adds metadata to the operation description. Applying the WebGetAttribute attribute to a service operation has no effect unless a behavior that is looking for this metadata in the operation description (such as WebHttpBehavior) is added to the service’s behavior collection."
MSDN
"The WebInvokeAttribute attribute is applied to a service operation in addition to the OperationContractAttribute and associates the operation with a UriTemplate as well as an underlying transport verb that represents an invocation (for example, HTTP POST, PUT, or DELETE). The WebInvokeAttribute attribute is a passive operation behavior (the IOperationBehavior methods do nothing) that adds metadata to the operation description. Applying the WebInvokeAttribute attribute to a service operation has no effect unless a behavior that looks for this metadata in the operation description (such as WebHttpBehavior) is added to the service’s behavior collection. The WebInvokeAttribute determines what HTTP method that a service operation responds to. By default, all methods that have the WebInvokeAttribute applied respond to POST requests. The Method property allows you to specify a different HTTP method. If you want a service operation to respond to GET, use the WebGetAttribute instead."
MSDN
Let us now see some WCF code that uses one of these attributes. I am going to only discuss the usage of the WebGetAttribute
in this post as I do not want to talk about all the CRUD operations that can be done with RESTful WCF just yet.
So in order to expose resources over a URL, we can use the WebGetAttribute
to adorn our WCF service operations. Here is an example:
1: [ServiceContract(SessionMode =
2: SessionMode.NotAllowed)]
3: public interface ISomeService
4: {
5:
6: [OperationContract]
7: [WebGet(UriTemplate = "/")]
8: Message GetRoot();
9:
10: [OperationContract]
11: [WebGet(UriTemplate = "/{userName}/")]
12: Message GetFavouriteBarsForUser(
13: String userName);
14: }
Notice that I have used the WebGetAttribute
to adorn the WCF OperationContract
methods. Also notice that there is a UriTemplate
property which is set to either a root terminator "/
" or has some more parts to the URL, where the extra parts of the Url are treated as method parameters, which allow more specific resources to be exposed.
In essence, that is all there is to allowing a service to expose resources. Now we need to test this. In order to do that, we need to implement this example service, so let's have a look at a small demo app I knocked up.
1: [ServiceBehavior(IncludeExceptionDetailInFaults = false,
2: InstanceContextMode = InstanceContextMode.Single,
3: ConcurrencyMode = ConcurrencyMode.Single)]
4: public class SomeService : ISomeService
5: {
6:
7: #region ISomeService Members
8:
9: public Message GetRoot()
10: {
11:
12: Message message = GetRootMessage();
13: return message;
14: }
15:
16:
17:
18: public Message
19: GetFavouriteBarsForUser(string userName)
20: {
21: Message message =
22: GetFavouriteBarsForUserMessage(userName);
23: return message;
24: }
25:
26: #endregion
27:
28: #region Private Methods
29:
30: 31: 32: 33: private Message
34: GetFavouriteBarsForUserMessage(String userName)
35: {
36: var stream = new MemoryStream();
37: XmlDictionaryWriter writer =
38: XmlDictionaryWriter.CreateTextWriter(stream);
39: writer.WriteStartDocument();
40: writer.WriteStartElement("Root");
41: writer.WriteStartElement("Bar");
42: writer.WriteElementString("user", userName);
43: writer.WriteEndElement();
44: writer.WriteEndElement();
45: writer.WriteEndDocument();
46: writer.Flush();
47: stream.Position = 0;
48:
49: XmlDictionaryReader reader =
50: XmlDictionaryReader.CreateTextReader(stream,
51: XmlDictionaryReaderQuotas.Max);
52: return Message.CreateMessage(
53: MessageVersion.None, "", reader);
54: }
55:
56:
57: 58: 59: 60: private Message GetRootMessage()
61: {
62: var stream = new MemoryStream();
63: XmlDictionaryWriter writer =
64: XmlDictionaryWriter.CreateTextWriter(stream);
65: writer.WriteStartDocument();
66: writer.WriteStartElement("Root");
67: writer.WriteStartElement("Hello");
68: writer.WriteElementString("Name", "sacha");
69: writer.WriteEndElement();
70: writer.WriteEndElement();
71: writer.WriteEndDocument();
72: writer.Flush();
73: stream.Position = 0;
74:
75: XmlDictionaryReader reader =
76: XmlDictionaryReader.CreateTextReader(
77: stream, XmlDictionaryReaderQuotas.Max);
78: return Message.CreateMessage(
79: MessageVersion.None, "", reader);
80: }
81: #endregion
82: }
So you can see for each of the WebGetAttribute
adorned WCF OperationContract
methods, we will return a Message
, which is really just some XML, which browsers will know how to display. If you don’t know what a Message Type is, do not worry, we will be covering that in a subsequent post.
For now, the important thing to note is that the service is exposing resources over REST using URLs.
The attached demo code includes a simply host, which when run will allow you to test various REST calls.
Here is what you need to do:
- Run the simple host (SomeServiceTestConsole.exe)
- Open a browser and try the following URLs:
- http://localhost:8085/SomeService
- http://localhost:8085/SomeService/sacha
- http://localhost:8085/SomeService/peter
And here is what you should see:
http://localhost:8085/SomeService
http://localhost:8085/SomeService/sacha
I hope you can see that by using these new RESTful attributes, we can expose resources via URLs, which is accessible simply using a Browser. Of course, to parse the XML, there are many options.
Here is a small demo app that has a very simple RESTful service and a very simple Console host.