Sunday, October 3, 2010

Building a CRUD in RESTful Services of WCF

WCF is being popular day by day. Many of us is building services using WCF and want other application made on different architecture 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 service works but it will eventually use Web Request - Response mechanism to communicate between clients rather than using SOAP messages.  In this post, I will give you a step by step approach how you could build your own WCF service using REST.

What is 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 basic of REST pattern is to generate unique URI to represent data.

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.

REST Based Services


Download Sample Application - 200KB



Why REST? 
There are few basic thought behind the implementation of REST services. Lets 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 to 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 works 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 lets 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 :
  1. GetContact : Retrieves an individual contact from the list.
  2. SaveContact : Saves the contact into a list and returns status
  3. RemoveContact : Removes an existing contact and returns status.
  4. GetAllContacts : Retrieves all contact 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 lets 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 lets follow the steps :

  1. 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. 
  2. 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. 
  3. 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 lets 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:8086/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 dont need to change anything here.

Now if you run your service host, you will see the service to be running.

To test the application :

1. REST services are been called from WebBrowsers, so lets open a web browser and see the list of all contacts.
Lets browse http://localhost:8086/ContactService/contacts,

So it will produce an XML with all ArrayOfContact. Basically REST services communicates using XML. If you want to send a form using POST, you need to create an XML with the same schema as specified in the DataMember, the REST service will parse your xml and produce the object.

Download Sample Application - 200KB

I hope the article will help you.

8 comments:

  1. Very good article. All realy simply to understand. Thanks!

    ReplyDelete
  2. @calabonga

    I am glad you liked it. Thanks.

    ReplyDelete
  3. Dear Abhishek,

    Please provide the URL of POST method, I have created for GET method, but not able to write POST method URL, Kindly provide it.

    Thanks,
    Deepak

    ReplyDelete
  4. @Depak

    Did you try

    [WebInvoke
    (Method = "POST",
    RequestFormat = WebMessageFormat.Xml,
    UriTemplate = "/contacts/{Name}"
    )]

    It would work if you post your xml to the method.

    ReplyDelete
  5. Yes abhishek,
    I have written that, at calling time I have written the code, Please correct, If i missed something here...

    HttpWebRequest request1 = WebRequest.Create("http://localhost:8086/ContactService/contacts") as HttpWebRequest;
    request1.Method = "POST";

    string requestBody = "<ArrayOfContact><Contact><Address>ABCD</Address><Age>21</Age><Name>AB</Name><Roll>15</Roll></Contact></ArrayOfContact>";
    byte[] bytes = Encoding.UTF8.GetBytes(requestBody);
    request1.ContentLength = bytes.Length;
    request1.Headers.Add("Rest-User-Token", Convert.ToBase64String(Encoding.UTF8.GetBytes(string.Format("{0}:{1}", "Admin's API Key", "admin"))));
    Stream requestStream = request1.GetRequestStream();
    requestStream.Write(bytes, 0, bytes.Length);
    requestStream.Close();

    using (HttpWebResponse webResponse = request1.GetResponse() as HttpWebResponse)
    {
    using (var reader = new StreamReader(webResponse.GetResponseStream()))
    { Console.WriteLine(reader.ReadToEnd());
    }
    }
    }

    ReplyDelete
  6. goygoygoioi
    lkljlkролдрод момпромпорм пл
    ромрммп

    ReplyDelete
  7. Good one, simple and interesting. Please also include how to process JSON responses...

    Thanks
    http://www.technobits.net - Always remain technically updated.

    ReplyDelete
  8. @Aamir Maniar

    Have you used JavascriptSerializer?
    Check :
    http://jalpesh.blogspot.com/2011/01/converting-generic-list-into-json.html

    ReplyDelete

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.

Author's new book

Abhishek authored one of the best selling book of .NET. It covers ASP.NET, WPF, Windows 8, Threading, Memory Management, Internals, Visual Studio, HTML5, JQuery and many more...
Grab it now !!!