Introduction
WCF is beginning to gain popularity day by day. Many of us build services using WCF and want other applications made on different architecture (from Java, PHP, etc.) to communicate or inter operate with each other. REST or Representational State Transfer is a Design Pattern to build a service so that it works the same way as any normal service but it will eventually use Web Request - Response mechanism to communicate between client and server rather than SOAP messages. In this post, I will give you a step by step approach of how you could build your own WCF service using REST.
REST abbreviated as Representational State Transfer is coined by Roy Fielding is a Design pattern for Networked system. In this pattern, the Client invokes a Web request using an URL, so the basics of REST pattern is to generate a unique URI to represent data.
Background
If you look into Roy Fielding's quote on REST, it says:
"Representational State Transfer is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through an application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use."
That means REST is intended for Web applications where the browser invokes each request by specifying unique URI.
Why REST?
There are a few basic thoughts behind the implementation of REST services. Let's look into it:
- Web is very simple and successful.
- Web Standards are fixed over time.
- Web Services should follow the standards of Web.
REST uses Web Verbs to communicate to the services. The verbs like GET
, POST
, DELETE, PUT
are major verbs for REST based applications. If you consider Hi - REST for your application, you should be strict of choosing these Verbs. According to the norms:
- GET - Used to Retrieve Data
- POST - To Append Data into the server
- PUT - Used for Inserts and Updates
- DELETE - Used to delete data
So each of these verbs produces a complete CRUD (Create, Retrieve, Update, Delete)
for a Data centric service and which works the same way as Web works.
Steps to Create REST Based Service
Now let us take a quick pick on how you could build a REST based service. I will use standard CRUD operation for my application and also try to look into it through a Browser.
REST services work the same way. First you need to create a Service with OperationContract
and DataContract
. The DataContract
will have the Complex type if you want to use and the OperationContract
will place all the operation on Data. So let's build one normal WCF application.
[ServiceContract]
public interface ICRUDContact
{
[OperationContract]
Contact GetContact(string roll);
[OperationContract]
bool SaveContact(Contact currentContact);
[OperationContract]
bool RemoveContact(string roll);
[OperationContract]
List<Contact> GetAllContacts();
}
[DataContract]
public class Contact
{
[DataMember]
public int Roll { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Address { get; set; }
[DataMember]
public int Age { get; set; }
}
[ServiceBehavior(InstanceContextMode= InstanceContextMode.Single)]
public class CRUDContact : ICRUDContact
{
private List<Contact> _store;
internal List<Contact> Store
{
get
{
this._store = this._store ?? new List<Contact>();
return this._store;
}
}
#region ICRUDContact Members
public Contact GetContact(string roll)
{
return this.Store.FirstOrDefault(item => item.Roll.ToString().Equals(roll));
}
public bool SaveContact(Contact currentContact)
{
if (this.Store.Any(item => item.Roll == currentContact.Roll))
return false;
this.Store.Add(currentContact);
return true;
}
public bool RemoveContact(string roll)
{
var currentContacts = this.Store.Where(item => item.Roll.ToString().Equals(roll));
if (currentContacts.Count() <= 0)
return false;
foreach (Contact currentContact in currentContacts)
this.Store.Remove(currentContact);
return true;
}
public List<Contact> GetAllContacts()
{
return this.Store;
}
#endregion
}
The code above is very straight forward, where the service exposes four Operations:
GetContact
: Retrieves an individual contact from the listSaveContact
: Saves the contact into a list and returns status RemoveContact
: Removes an existing contact and returns statusGetAllContacts
: Retrieves all contacts as List
So now if you use BasicHttpBinding
for the service and create a servicehost for the application, you could easily consume the service and work on it. Notably I have used:
[ServiceBehavior(InstanceContextMode= InstanceContextMode.Single)]
to ensure that the service will create only one instance of the class and hence every request will work on the same List.
Convert the Application to REST
Now let's see how easily you can convert the application to use REST services. REST needs you to create UriTemplate
for each Service Operations. To do this, let's follow the steps:
- Add
System.ServiceModel.Web.dll
. This DLL allows you to produce REST based service. It exposes attributes like WebGet
or WebInvoke
which lets you to specify the UriTemplate
for the current operation and also lets you specify the Method
. - Apply
WebGet
attribute for Get
requests and specify complete Uri
for the service operation. You could use {0} to specify the parameters to the request. Please make sure the name of the parameter and the name of the variable in the service matches exactly and each of those parameters are of type String
. WebInvoke
allows you to specify the Method
thorough which the request to be made. Unlike WebGet
, WebInvoke
allows you to specify Method
parameter which could be POST, PUT, DELETE
or even GET
.
So after changing the contract, my service would look like:
[ServiceContract]
public interface ICRUDContact
{
[WebGet(UriTemplate="contact/{roll}")]
[OperationContract]
Contact GetContact(string roll);
[WebInvoke(Method="POST", UriTemplate="contacts")]
[OperationContract]
bool SaveContact(Contact currentContact);
[WebInvoke(Method = "DELETE", UriTemplate = "contact/{roll}")]
[OperationContract]
bool RemoveContact(string roll);
[WebGet(UriTemplate = "contacts")]
[OperationContract]
List<Contact> GetAllContacts();
}
So basically, I have to specify the UriTemplate
for each of the service contracts for the existing operations. The first operation GetContact
will operate on WebGet
which will be mapped into contact/{roll}. So if you call the service contact/1 it will map to the Service contract GetContact
with roll 1.
WebInvoke
on the other hand allows you to specify Method
, as in RemoveContact
and SaveContact
I have used DELETE and POST
methods.
Note: The notion of building UriTemplate
is to specify some form of unique URI. Always keep in mind, the external world will request the service using the URI.
Now let's go to our ServiceHost
application and configure the service to use REST based approach. Basically for REST based service, you need to use webHttpBinding
as Binding configuration.
<system.serviceModel>
<services>
<service name="ContactService.CRUDContact" behaviorConfiguration="httpBehaviour">
<endpoint address="" binding="webHttpBinding"
contract="ContactService.ICRUDContact"
behaviorConfiguration="httpEndpointBehavour">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/ContactService/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="httpBehaviour">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="httpEndpointBehavour">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
As you can see, my service now uses WebHttpBinding
rather than BasicHttpBinding
and also created one EndpointBehaviour
to have webHttp
for the service configured for my endpoint. You don't need to change anything here.
Now if you run your service host, you will see that the service is running.
To Test the Application
REST services are being called from WebBrowsers, so let's open a web browser and see the list of all contacts.
Let's browse http://localhost:8086/ContactService/contacts,
So it will produce an XML with all ArrayOfContact
. Basically REST services communicate using XML. If you want to send a form using POST
or PUT
, you need to create an XML document with the same schema as specified in the DataMember
, the REST service will parse your XML and produce the .NET objects.
Let us call another service method.
Here the URL is called using the Roll 1 which is passed as argument. And hence you receive the XML data as Response from the service containing the Contact Info.
Conclusion
It is fun creating RESTful service. I am still in the learning phase of WCF, so if there are any mistakes, please let me know.
Looking for your feedback.
History
- 3rd October, 2010: Initial post