Category Archives: WCF

WCF – Visual Studio 2010 REST Web Service Project Download

Since I’ve had a few requests for a download of a Visual Studio project for a WCF REST web service, here’s a a working project that incorporates all the WCF and most of the REST tips from my blog to date.

RESTFUL WCF Demo

Please see my “About” page for copyright and disclaimer information when using any code downloaded from my blog or other sites.

WCF – Including XML Attributes in Your DataContract

RESTful web services must include hypertext within their resource representations to fulfill the HATEOAS constraint.1 XML attributes within a <link> element have become a standard part of this hypertext. The Atom Publishing Protocol is considered to be quite RESTful2 and defines several attributes for a <link>. This Atom <links> has “rel” and “href” attributes that indicate where to PUT data to edit the resource:

<link rel=”edit” href=”http://example.org/blog/entries/1″ />

Unfortunately, WCF’s default “…DataContractSerializer does not support the programming model used by the XmlSerializer and ASP.NET Web services. In particular, it does not support attributes like XmlElementAttribute and XmlAttributeAttribute. To enable support for this programming model, WCF must be switched to use the XmlSerializer instead of the DataContractSerializer.”3 This post shows you how to switch to the XmlSerializer.

First, use Visual Studio 2010 to create a new WCF Service application. Next, open the IService1.cs file and replace the auto-generated code with this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web; //add reference if needed
using System.Text;
using System.Xml.Serialization; //add reference if needed

namespace YourNameSpaceHere
{

   [ServiceContract]
   [XmlSerializerFormat]
   public interface IService1
   {
      [OperationContract]
      [WebInvoke(Method = "GET",
          ResponseFormat = WebMessageFormat.Xml,
          UriTemplate = "artist")]
      Artist GetArtist();
   }

   [DataContract]
   [XmlRoot(ElementName = "Artist")]
   public class Artist
   {
      [XmlAttribute("rel")]
      public string theUri { get; set; }

      public string FirstName { get; set; }
      public string LastName { get; set; }
      public string Grammys { get; set; }

      public Artist() { }

      public Artist(string firstName, string lastName, string grammys)
      {
         this.theUri = "edit";
         this.FirstName = firstName;
         this.LastName = lastName;
         this.Grammys = grammys;
      }
   }
}

The code above tells WCF to use the XmlSerializerFormat for your service contract. Then we decorate the DataContract with the attributes required to tell WCF which property is the XML root, an XML attribute and an XML element. When using the XmlSerializer, unlike the DataContractSerializer, if an attribute is not defined for a public data member (like the FirstName property) WCF serializes the member as an XML element. This is important to remember! Otherwise you could accidentally expose a property that had not been exposed using the default WCF DataContract serialization.

Now open Service1.svc.cs and replace the existing code with the following. There’s nothing new in this file related to the XmlSerializer. I’m just including it so you’ll have a working service to test.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;        //add reference if needed
using System.Text;
using System.ServiceModel.Activation; //add reference if needed

namespace YourNameSpaceHere
{
   public class Service1 : IService1
   {
      public Artist GetArtist()
      {
         Artist player = new Artist("LastName", "FirstName", "0");
         return player;
      }
   }
}

Finally, right click the Services1.svc file and View Markup:

Add the Factory=”System.ServiceModel.Activation.WebServiceHostFactory” attribute as follows. This tells WCF to dynamically generate the host instance in IIS, and therefore the endpoints configurations, so we can avoid doing it in the Web.config. It’s not related to using the XmlSerializer:

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

Build and test your service. You can test your service by right clicking the Service1.svc file and then “View in Browser”. This will take you to http://localhost:55802/Service1.svc which is not defined as an endpoint. Now browse to http://localhost:55802/Service1.svc/artist. You’ll get this following XML with the attribute rel=”edit” in the Artist element on line 2.

<?xml version="1.0" encoding="utf-8" ?> 
<Artist rel="edit" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <FirstName>LastName</FirstName> 
  <LastName>FirstName</LastName> 
  <Grammys>0</Grammys> 
</Artist>

1. Fielding, Roy T. REST APIs must be hypertext-driven. Untangled – Musings of Roy T. Fielding, October 20, 2008

2. Richardson, Leonard and Ruby, Sam. RESTful Web Services. Sebastopol: O’Reilly Media, Inc., 2008. Ebook

3. MSDN. Types Supported by the Data Contract Serializer 2012-08-02

WCF – Removing .svc from RESTful URIs

Addressability is one of the four properties of Resource-Oriented Architectures. An application is addressable if it exposes the interesting aspects of its data set through resources. And resources are exposed through their unique URIs.1 By default, the endpoints of an IIS hosted WCF service have the service file name in their URLs.2 For example,

http://www.mydomain.com/Service1.svc/resource1

While not un-RESTful, the “Service1.svc” part doesn’t add to the addressability of an ROA service. A resource URI should indicate the relationship of its resource to other resources. The example above would typically mean that resource1 is subordinate to Service1.svc, which isn’t the case. In fact, Service1.svc isn’t a resource at all and does not relate to any interesting aspect of our data.

With WCF we have the option of removing the .svc file reference from our URIs. First, use Visual Studio 2010 to create a new .Net 4(+) WCF Service Application.

Open the web.config.

The default, VS generated configuration is:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

Add the aspNetCompatibilityEnabled=”true” attribute to the serviceHostingEnvironment element on line 18:

...
      </serviceBehaviors>
    </behaviors>
 <serviceHostingEnvironment multipleSiteBindingsEnabled="true"  aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
...

Now add a Global.asax file to your project.

Open the Global.asax and add the following code on line 17:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;
using System.ServiceModel.Activation;

namespace YourNameSpaceHere
{
   public class Global : System.Web.HttpApplication
   {

      protected void Application_Start(object sender, EventArgs e)
      {
         RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(Service1)));
      }

      protected void Session_Start(object sender, EventArgs e)
      {
          //...

Add a reference to System.ServiceModel.Activation if it is not already there:

Open the IService1.cs file and replace the auto-generated code with the following. This has nothing to do with removing the .svc file. It’s just to give you a working service. Don’t forget to use your namespace on line 9.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace YourNameSpaceHere
{
   [ServiceContract]
   public interface IService1
   {
      [OperationContract]
      [WebInvoke(Method = "GET",
          ResponseFormat = WebMessageFormat.Xml,
          UriTemplate = "artist")]
      Artist GetArtist();

   }

   [DataContract] 
   
   public class Artist
   {  [DataMember]
      public string FirstName { get; set; }
      [DataMember]
      public string LastName { get; set; }
      [DataMember]
      public string Grammys { get; set; }
      
      public Artist(string firstName, string lastName, string grammys)
      {
         this.FirstName = firstName;
         this.LastName = lastName;
         this.Grammys = grammys;
      }
   }
}

Open Service1.svc.cs and replace the code with this. Again, this is just for a working service.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace YourNameSpaceHere
{
   public class Service1 : IService1
   {
      public Artist GetArtist()
      {
         Artist player = new Artist("LastName", "FirstName", "0");
         return player;
      }

   }
}

Now modify Service1.svc.cs by adding a reference to System.ServiceModel.Activation and decorating the implementation class with the [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] attribute. This is part of removing the .svc file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using System.ServiceModel.Activation;

namespace YourNameSpaceHere
{
   [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
   public class Service1 : IService1
   {
      public Artist GetArtist()
      {
         Artist player = new Artist("LastName", "FirstName", "0");
         return player;
      }

   }
}

Finally, right click the Services1.svc file and View Markup:

Add the Factory=”System.ServiceModel.Activation.WebServiceHostFactory” attribute as follows:

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

And that’s all there is to do! Right click on the Services1.svc file and View in Browser. You’ll find the .svc file is no longer an endpoint:

Now browse to http://localhost:55685/artist to see the results:

<Artist xmlns="http://schemas.datacontract.org/2004/07/rest" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <FirstName>LastName</FirstName> 
  <Grammys>0</Grammys> 
  <LastName>FirstName</LastName> 
</Artist>

If you’ve built a WCF rest service before, you’ll also notice how we avoided all that configuration mess in the Web.config!

Many thanks to Steve Michelotti and his blog post “RESTful WCF Services with No svc file and No config”. Check out his article for more details on configuring WCF to not use the .svc file. He’ll also show you how to configure WCF to generate a help file for your services.


1. Richardson, Leonard and Ruby, Sam. RESTful Web Services. Sebastopol: O’Reilly Media, Inc., 2008. Ebook

2. WCF services hosted in IIS are represented as special content files (.svc files) inside the IIS application. It provides information used by IIS to initiate the WCF runtime and start the service. By default, the .svc file name is used as the base address for the service.

WCF- Changing Data Contract Names and Namespaces

When posting XML data to a Windows Communication Foundation (WCF) web service1, you need to specify the XML namespace of the data sent in the entity-body of your HTTP POST. This lets WCF know how to deserialize the input you’ve sent. By default, WCF maps the namespace to:

http://schemas.datacontract.org/2004/07/Clr.Namespace

where Clr.Namespace is the namespace of your data contract.2 For example, if my data contract namespace is “RESTful”:

namespace RESTful
{
    [DataContract]
    public class Person
    {
        [DataMember]
        public int ArtistID { get; set; }
        //...

then the namespace to use when consuming this service is:

http://schemas.datacontract.org/2004/07/RESTful

Here’s a code snippet that uses jQuery and Ajax to post a Person to the WCF web service:

        $.ajax({
            type: 'POST',
            data: '<Person xmlns="http://schemas.datacontract.org/2004/07/RESTful">'
                  + '<ArtistID>0</ArtistID>'
                  + '<FirstName>Ella</FirstName>'
                  + '<Grammys>14</Grammys>'
                  + '<LastName>Fitzgerald</LastName>'
                  +'</Person>',
            dataType: 'xml',
            // ...

That’s not a descriptive namespace. Let’s change it to something a bit more informative by specifying a ContractNamespace for our assembly.

[assembly: ContractNamespace("http://schemas.dlwelch.com/JazzService", ClrNamespace = "RESTful")]
namespace RESTful
{
    [DataContract]
    public class Person
    {
        [DataMember]
        public int ArtistID { get; set; }
        //...

Putting this at the assembly level changes the namespace for all data contracts in the RESTful namespace. If we didn’t want to change them all, we could have changed a single contract like this:

namespace RESTful
{
    [DataContract (Namespace="http://schemas.dlwelch.com/JazzService")]
    public class Person
    {
        [DataMember]
        public int ArtistID { get; set; }
        //...

I’m going to leave all of the RESTful data contracts in the same namespace (line 1). And while I’m under the hood, I’m going to change the contract name to something more meaningful (line 4):

[assembly: ContractNamespace("http://schemas.dlwelch.com/JazzService", ClrNamespace = "RESTful")]
namespace RESTful
{
    [DataContract(Name = "Artist")]
    public class Person
    {
        [DataMember]
        public int ArtistID { get; set; }
        //..

Now, when we POST to the service, the request details are a lot nicer:

        $.ajax({
            type: 'POST',
            data: '<Artist xmlns="http://schemas.dlwelch.com/JazzService">'
                  + '<ArtistID>0</ArtistID>'
                  + '<FirstName>Ella</FirstName>'
                  + '<Grammys>14</Grammys>'
                  + '<LastName>Fitzgerald</LastName>'
                  + '</Artist>',
            dataType: 'xml',
            // ...         

My ultimate goal is to create a truly RESTful web service. That’s why I want everything to be self-describing – including the namespace for my data contracts. It also means I’m not interested in the WSDL which is auto-generated by WCF. However, changing the contract names and namespaces has the added bonus of making your WSDL nicer too!

A default WSDL would be similar to this:

<?xml version="1.0" encoding="UTF-8"?>
 <wsdl:definitions name="JazzArtists" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" 
    ... 
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" 
    xmlns:tns="http://tempuri.org/" 
    ... 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
                targetNamespace="http://tempuri.org/">
 <wsdl:types>
  <xsd:schema targetNamespace="http://tempuri.org/Imports">
    <xsd:import namespace="http://tempuri.org/"
         schemaLocation="http://development.dlwelch.com/examples/RestService/JazzArtists.svc?xsd=xsd0"/>
    <xsd:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" 
       schemaLocation="http://development.dlwelch.com/examples/RestService/JazzArtists.svc?xsd=xsd1"/>
    <xsd:import namespace="http://schemas.datacontract.org/2004/07/RestService" 
       schemaLocation="http://development.dlwelch.com/examples/RestService/JazzArtists.svc?xsd=xsd2"/>
   </xsd:schema>
 </wsdl:types>
 <wsdl:message name="IJazzArtists_XMLData_InputMessage">
 <wsdl:part name="parameters" element="tns:XMLData"/>
  ... 
</wsdl:definitions>

There are multiple references to “http://tempuri.org/” in addition to the data contract namespace “http://schemas.datacontract.org/2004/07/RestService”. We’ve already cleaned up the latter (line 15), now let’s get rid of tempuri.org. First, we’ll change the namespace for the service contract:

[ServiceContract ( Namespace = "http://schemas.dlwelch.com/JazzService" )]
public interface IJazzService
{

and then the service implementation:

namespace RESTful
{
    [ServiceBehavior(Namespace = "http://schemas.dlwelch.com/JazzService")]
    public class JazzService : IJazzService
    { 
      //...

Finally, we’ll change the namespace for the binding in the web.config:

  <system.serviceModel>
    <services>
      <service behaviorConfiguration="RESTful.JazzServiceBehavior" name="RESTful.JazzService">
        <endpoint address="" binding="webHttpBinding" 
                             bindingNamespace="http://schemas.dlwelch.com/JazzService" 
                             contract="RESTful.IJazzService" behaviorConfiguration="web">
        </endpoint>
   ...

This gives us WSDL using our custom namespaces instead of the WCF defaults:

<?xml version="1.0" encoding="UTF-8"?>
 <wsdl:definitions name="JazzService" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" 
    ... 
    xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" 
    xmlns:tns="http://schemas.dlwelch.com/JazzService" 
    ...
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
                targetNamespace="http://schemas.dlwelch.com/JazzService">
  <wsdl:types>
  <xsd:schema targetNamespace="http://schemas.dlwelch.com/JazzService/Imports">
    <xsd:import namespace="http://schemas.dlwelch.com/JazzService" 
         schemaLocation="http://development.dlwelch.com/examples/restful/JazzService.svc?xsd=xsd0"/>
    <xsd:import namespace="http://schemas.microsoft.com/2003/10/Serialization/" 
         schemaLocation="http://development.dlwelch.com/examples/restful/JazzService.svc?xsd=xsd1"/>
  </xsd:schema>
  </wsdl:types>
 <wsdl:message name="IJazzService_GetArtist_InputMessage">
 <wsdl:part name="parameters" element="tns:GetArtist"/>
...
</wsdl:definitions>

I haven’t “switched off” the WSDL for my JazzService even though the service will eventually be RESTful. There’s no harm to ROA by leaving it on. So if someone wants to create a client by importing the WSDL, it’s now available with our nice namespaces.


1. Please see my blog post Creating RESTful WCF Web Services Using Visual Studio 2010 for an example of creating WCF web services.
2. Data Contract Names – http://msdn.microsoft.com/en-us/library/ms731045.aspx

Creating RESTful WCF Web Services Using Visual Studio 2010

Representational State Transfer (REST) is an architectural style used to build distributed systems. First proposed in 2000 by Roy Thomas Fielding in his doctoral dissertation “Architectural Styles and the Design of Network-based Software Architectures”, REST is now, or will soon be, the predominant architecture for building web services. However, there’s a lot of discussion about the true definition of a RESTful web service. One real world discussion that helped me understand RESTfulness is this article from IBM’s Alex Rodriguez. My own, rather distilled, working definition of a RESTful service is one that uses the standard HTTP verbs POST, GET, PUT and DELETE – as intended and defined in RFC 2616 – and a URI to accomplish resource CRUD (create, read, update, delete).1

As a .NET developer, I use Windows Communication Foundation (WCF) to create web services. This post shows you how to use Visual Studio 2010 to create a basic REST service that supports each HTTP verb.

Create a WCF Service Application project named RestService:

Delete IService1.cs and Service1.cvs that were created for you by VS:

Add a new WCF service named JazzArtists:

Visual studio will add 2 files to your project named IJazzArtists.cs and JazzArtists.svc and its associated code behind page.

Next, we need to write the service contract. Replace the contents of IJazzArtists.cs with the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;

namespace RestService
{
    [DataContract]
    public class Person
    {
        [DataMember]
        public string FirstName { get; set; }

        [DataMember]
        public string LastName { get; set; }

        [DataMember]
        public int Grammys { get; set; }

        public Person(string firstName, string lastName, int grammys)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Grammys = grammys;
        }
    }

    [ServiceContract]
    public interface IJazzArtists
    {
        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Xml,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "xml/{id}")]
        string XMLData(string id);

        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json/{firstn}")]
        List<Person> JSONData(string firstn);

        [OperationContract]
        [WebInvoke(Method = "GET",
            ResponseFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json")]
        List<Person> JSONDataAll();

        [OperationContract]
        [WebInvoke(Method = "POST",
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json")]
        bool JSONDataPost(Person PersonObject);

        [OperationContract]
        [WebInvoke(Method = "DELETE",
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json")]
        bool JSONDataDelete(Person PersonObject);

        [OperationContract]
        [WebInvoke(Method = "PUT",
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json,
            BodyStyle = WebMessageBodyStyle.Wrapped,
            UriTemplate = "json")]
        bool JSONDataPut(Person PersonObject);


    }
}

The [DataContract] defines the data types and structures of resources that will be transferred between your application and the web service. The [ServiceContract] defines how each HTTP verb request to the specifed URI will be handled by the web service.

In this example, the first [OperationContract] is for GET requests made to URLs constructed like http://yourdomain.com/RestService.svc/xml/Shirley. All requests to this URL will receive an XML response since ResponseFormat = WebMessageFormat.Xml on code line 36. The XML returned data

  <XMLDataResponse xmlns="http://tempuri.org/">
  <XMLDataResult>Your name is Shirley</XMLDataResult> 
  </XMLDataResponse>

is the result of the method XMLData(string id) – which we’ll discuss momentarily.

The next [OperationContract] is for a GET request to URLs like http://yourdomain.com/RestService.svc/json/Shirley. The result returned from this request is a in JSON formatted Person list with one row, for example:

{"JSONDataResult":[{"FirstName":"Shirley","Grammys":1,"LastName":"Horn"}]}

The next GET contract is used to read all Persons. Notice it has a different URI than the previous. In the first URI – /json/{firstn} – we specified which person to get. The second URI does not. So when you GET from http://yourdomain.com/RestService.svc/json, the return is a list of all Persons:

{"JSONDataAllResult":[{"FirstName":"Billie","Grammys":10,"LastName":"Holiday"},
                      {"FirstName":"Shirley","Grammys":4,"LastName":"Horn"},
                      {"FirstName":"Ella","Grammys":20,"LastName":"Fitzgerald"}]}

The POST [OperationContract] for the URL http://yourdomain.com/RestService.svc/json expects the posted data in the request package to conform to the Person class definition and to be in JSON format:

{"PersonObject":{"FirstName":"Shirley","LastName":"Horn","Grammys":4}}

Notice the JSON wrapper key name “PersonObject” is the same name used in the POST [OperationContract] on code line 61. We will discuss the requirements for the “input” data of the POST request in greater detail in my next post.

The response to the POST request is the JSON formatted result of method JSONDataPost(Person PersonObject).

{"JSONDataResult":true}

PUT and DELETE are similarly implemented.

Now we need to define the methods that run when the HTTP requests are made to the URIs. Replace the contents of JazzArtists.svc.cs with this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace RestService
{
    public class JazzArtists : IJazzArtists
    {

        public string XMLData(string id)
        {
            return "Your name is " + id;
        }

        public List<Person> JSONData(string firstn)
        {   //code to Read ONE person goes here
            string lastn = "Horn";
            int nogrammys = 1;
            List<Person> players = new List<Person>();
            players.Add(new Person(firstn, lastn, nogrammys));
            return players;
        }

        public List<Person> JSONDataAll()
        {   //code to Read ALL Persons go here
            List<Person> players = new List<Person>();
            players.Add(new Person("FirstName", "LastName", 0));
            return players;
        }

        public bool JSONDataPost(Person PersonObject)
        {   //code to Create the Person goes here
            return true;
        }

        public bool JSONDataDelete(Person PersonObject)
        {   //code to Delete the specified Person
            return true;
        }

        public bool JSONDataPut(Person PersonObject)
        {   //code to Update the specified Person goes here
            return true;
        }
    }
}

How easy is that! Just fill in the details for your project and make sure your method names and types are the same as those specifed in the contract.

Finally, since the default communication binding for a WCF web services is SOAP, we need to change the web.config to use REST instead.

In the system.serviceModel section, delete both the service for Service1:

and the associated behavior:

since we have deleted Service1 from the project. Also delete the indentity in your JazzArtists service:

WCF will infer an appropriate identity automatically.

Now change the endpoint binding for JazzArtists to webHttpBinding and the behaviorConfiguration to web. Add the endpointBehaviors section as well:

The system.serviceModel should look like this:

<system.serviceModel>
    <services>
      <service behaviorConfiguration="RestService.JazzArtistsBehavior"
        name="RestService.JazzArtists">
        <endpoint address="" binding="webHttpBinding" 
          contract="RestService.IJazzArtists" behaviorConfiguration="web">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="RestService.JazzArtistsBehavior">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>

You may need to make more changes to your web.config depending upon the hosting environment. Mine runs on a shared hosting plan so I had to add a serviceHostingEnvironment section to my system.serviceModel to specify the correct prefix:

I also had to add a buildProviders in the compilation section to properly handle .svc files:

You can test drive a working REST service similar to this one on my development site example WCF RESTful Web Service. My next post will demonstrate how to consume a REST service using client side jQuery and Ajax.


1. This post concentrates on the details of creating a REST service using WCF and Visual Studio 2010. However, the service we built is not as RESTful as it could be. A future post will demonstrate a few changes that will better align this web service with the principles of REST and Resource Oriented Architecture.