Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Restful Crud Operation on a WCF Service

4.83/5 (30 votes)
3 Oct 2010CPOL5 min read 117.8K   3.6K  
In this article, I have introduced how easily you can create a RESTful service in WCF

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.
REST2.JPG

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.

C#
[ServiceContract]
public interface ICRUDContact
{
    [OperationContract]
    Contact GetContact(string roll);

    [OperationContract]
    bool SaveContact(Contact currentContact);

    [OperationContract]
    bool RemoveContact(string roll);

    [OperationContract]
    List<Contact> GetAllContacts();
}

// Use a data contract as illustrated in the sample below 
//to add composite types to service operations
[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 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:

C#
[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:

  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:

C#
[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.

XML
<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,

rest3.JPG

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.

rest4.JPG

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)