Friday, May 28, 2010
This article presumes that you know the backgrounds to REST and WCF, and provides a practical example of creating a RESTful Web Service - without the help of the REST Starter Kit.

Step 1 - Create your Web Service Library


Good practice is to separate the actual service code from the service definition.  I do this by creating two projects - a ServiceLibrary and the Service itself.  I always start by creating the Library.

Create a Plain Old new C# Library. 

Create your IService interface, like so:

[ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        TestObject GetDataUsingDataContract(TestObject composite);

        [WebInvoke(UriTemplate="/users", Method="POST")]
        [OperationContract]
        void Submit(TestObject eval);

        [OperationContract]
        [WebGet(UriTemplate="*")]
        string Test();

        [OperationContract]
        [WebGet(UriTemplate = "test2")]
        string Test2();

        [OperationContract]
        [WebGet(UriTemplate="users")]
        List<TestObject> Get();

        [OperationContract]
        [WebGet(UriTemplate = "users/{userid}")]
        TestObject GetUser(string userid);
        
        [OperationContract]
        void Remove(string id);

        // TODO: Add your service operations here
    }

    // Use a data contract as illustrated in the sample below to add composite types to service operations
    [DataContract(Name="testobject", Namespace = "")]
    public class TestObject
    {
        [DataMember]
        public string Id { get; set; }

        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }

        public TestObject()
        {
            
        }

        public TestObject(string id, string val)
        {
            Id = id;
            StringValue = val;
        }
    }

I've also created my TestObject class here, which is the resource we will deal with in our service.

As you can see, IService1 looks like a bog standard WCF service definition

Now create your concrete implementation, as so:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1 : IService1
    {
        List<TestObject> objects = new List<TestObject>();

        public Service1()
        {
            objects.Add(new TestObject("1", "Duncan"));
            objects.Add(new TestObject("2", "Joe Bloggs"));
            objects.Add(new TestObject("3", "Alice Anderson"));
        }

        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public string Test()
        {
            return "Hello World!";
        }

        public string Test2()
        {
            return "We got some REST goin' on";
        }

        public TestObject GetDataUsingDataContract(TestObject composite)
        {
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }

        public void Submit(TestObject eval)
        {
            eval.Id = Guid.NewGuid().ToString();
            objects.Add(eval);
        }

        public List<TestObject> Get()
        {
            return objects;
        }

        public TestObject GetUser(string userid)
        {
            return objects.Find(e => e.Id.Equals(userid));
        }

        public void Remove(string id)
        {
            objects.Remove(objects.Find(e => e.Id.Equals(id)));
        }

    }

What I've done here is create my service as a single instance, by using the InstanceContextMode parameter in the ServiceBehaviour attribute.  This means that we can keep an in-memory list of objects which will be preserved between calls to the service.

Step 2 - Create your Service

Okay, so that is the inner workings of the service created.  But all we have is now a .NET assembly - it's still not a WCF service. 

Create your service by adding a new project and selecting WCF Service Application, like below:





Call it RESTService.

Delete everything except RESTService.svc - including the .cs files under RESTService.svc.

Add a project reference to the REST Service Library project you created in Step 1.

Edit the markup of RESTService.svc so that it looks like the following:

<%@ ServiceHost Language="C#" Debug="true" Service="RESTWCFLibrary.Service1" Factory="System.ServiceModel.Activation.WebServiceHostFactory"  %>

Step 3 - Install into IIS and edit the bindings


Now the fiddly bit.

Edit the web.config so that your bindings look like (most important things to note are in red) :


<system.serviceModel>
      <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
      <behaviors>
        <endpointBehaviors>
          <behavior name="RESTServiceBehavior">
            <webHttp />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <services>
        <service name="RESTWCFLibrary.Service1">
          <endpoint name="default" address="" binding="basicHttpBinding" contract="RESTWCFLibrary.IService1"/>
          <endpoint name="RESTEndpoint" address="REST" behaviorConfiguration="RESTServiceBehavior"
                  binding="webHttpBinding"
                  contract="RESTWCFLibrary.IService1">
          </endpoint>
        </service>
      </services>
      <bindings />
      <client />
    </system.serviceModel>


REST WCF services will only work under the webHttp binding.  By adding a new endpoint under the "REST" address, your service will be available (for REST calls) under RestServiceName/REST/[resources here...]

Installing under IIS is easy.  Create a new website/vdir and point the physical path to the directory that hosts your .svc file.  And that's it - hosted!

Step 4 - Testing - GETs and POSTs


Now to test your service.  Open a browser and enter a URL similar to the following:

http://localhost/restWCFSite/RESTservice.svc/rest

If you implemented your ServiceContract as above, this will hit the default method on the Service - which is the method Test.  You should see an XML packet returned with "Hello World!" as the string.

Entering the following

http://localhost/restWCFSite/RESTservice.svc/rest/users

will list all the users in the 'database' and

http://localhost/restWCFSite/RESTservice.svc/rest/users/1

will query that user by id - returning only that specified user.

To add data, you'll need to use Fiddler and construct the POST request yourself.

To do this, open up Fiddler, go to the Request Builder tab, and enter the following:





Note that the attributes MUST be in upper-case, if you put <stringvalue> instead of <StringValue> then it will not be able to parse these into the correct fields of the testobject class.

Execute this request.

If you go back to your previous GET and list the users, you should see your new user appear in the list.

That's it - your first REST service.



Friday, May 28, 2010 4:11:44 PM (GMT Standard Time, UTC+00:00) | Comments [2] | ASP.NET | wcf#
Wednesday, June 02, 2010 9:46:54 AM (GMT Standard Time, UTC+00:00)
Nice post Duncan. What are the main benefits of using REST over SOAP web services? I know its lightweight and platform independent...
Wednesday, June 02, 2010 2:13:12 PM (GMT Standard Time, UTC+00:00)
It's the future dude.

Not really.

As with most things, the answer as to whether it is better is "it depends".

Think of SOAP like RPC over the web - that's all your doing. It's procedure-oriented.

Think of REST like object (or rather RESOURCE) -oriented. You always have the same Operations (HTTP verbs) - GET/POST/PUT/DELETE.

In short - it gives a much nicer interface, thereby encouraging people to consume your data. I'm betting that Twitter wouldn't have been half as popular if it didn't have a REST interface.
Duncan
Comments are closed.
Search
Archive
Links
Categories
Admin Login
Sign In
Blogroll