Monday, July 9, 2012

Create a WCF REST Service (JSON & XML)

REST (Representational State Transfer) services are quickly becoming the de-facto standard for web services in SOA (Solution Oriented Architecture) architectures.  This example demonstrates how to create a REST service in WCF (Windows Communication Foundation) with Visual Studio 2010 with support for JSON (Javascript Object Notation) and XML formats.  The basic steps in this process consist of creating the interface contract, implementing the interface methods, configuring the interface in Web.config and testing basic methods to prepare for consumption.
This project, with complete source code is available for download at  https://bitbucket.org/barkes/presidentsservice.

To create a WCF REST Service

  1. Create a new project in Visual Studio named PresidentsService by selecting the WCF Service Application project template in the WCF category.

  2. Delete the automatically generated IService1.cs and IService1.svc files.  Right-click the files in the Solution Explorer, select the Delete menu.


  3. Add a new WFC Service named PresidentsService.svc.  Right-click your project, click Add.  Then click New Item.  Select the WCF Service item from the Web category in the Add New Item dialog.


  4. Open IPresidentsService.cs and add the following OperationContracts with JSON and XML formatted responses:


    Web Method URI Format Description
    GET
    presidents/{lastname}
    JSON
    Returns president based on last name.
    GET
    presidents
    JSON
    Returns all presidents.
    POST
    presidents
    JSON
    Add or update a president.
    DELETE
    presidents/{lastname}
    JSON
    Delete a president based on last name.
    GET
    xml/presidents/{lastname}
    XML
    Returns president based on last name.
    GET
    xml/presidents
    XML
    Returns all presidents.
    POST
    xml/presidents
    XML
    Add or update a president.
    DELETE
    xml/presidents/{lastname}
    XML
    Delete a president based on last name.

    Although there are several techniques for supporting both JSON and XML formats, this example simply uses a different URI, with an 'xml' prefix and corresponding response formats of WebMessageFormat.Json and WebMessageFormat.Xml, respectively.
     IPresidentsService.cs
    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "presidents/{lastname}")]
    President GetPresident(string lastname);
     
    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "presidents")]
    List<President> GetAllPresidents();
     
    [OperationContract]
    [WebInvoke(Method = "POST",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "presidents")]
    bool AddPresident(President president);
     
    [OperationContract]
    [WebInvoke(Method = "DELETE",
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "presidents/{lastname}")]
    bool DeletePresident(string lastName);
    
    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "xml/presidents/{lastname}")]
    President GetPresidentXml(string lastname);
     
    [OperationContract]
    [WebInvoke(Method = "GET",
        ResponseFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "xml/presidents")]
    List<President> GetAllPresidentsXml();
     
    [OperationContract]
    [WebInvoke(Method = "POST",
        ResponseFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "xml/presidents")]
    bool AddPresidentXml(President president);
     
    [OperationContract]
    [WebInvoke(Method = "DELETE",
        ResponseFormat = WebMessageFormat.Xml,
        BodyStyle = WebMessageBodyStyle.Bare,
        UriTemplate = "xml/presidents/{lastname}")]
    bool DeletePresidentXml(string lastName);
  5. Open PresidentsService.svc.cs and implement the service methods.  The following is the GetPresident method that returns a president based on last name.  Please note the rest of the code is included in the download.
     PresidentsService.svc.cs
    public President GetPresident(string lastName)
    {
        MIMEType = WebHelper.MimeTypes["htm"];
                
        var query = from President president in Presidents
                    where president.LastName.ToLower() == lastName.ToLower()
                    select president;
     
        return query.FirstOrDefault();
    }
    Notice, this implementation uses a custom helper named WebHelper.MimeType to set the outgoing response's ContentType to text/html so the JSON responses can be viewed directly in a browser.

    internal string MIMEType
    {
        get { return _mimeType; }
        set 
        { 
            _mimeType = value; 
            WebOperationContext.Current.OutgoingResponse.ContentType = _mimeType; 
        }
    }
    
  6. Open Web.config to configure the service Endpoint and Bindings.  The key here is using the REST webHttpBinding binding (not SOAP-based wsHttpBinding) to provide JSON and XML from the service through direct URL access.

    <?xml version="1.0"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <services> <service name="PresidentsService.PresidentsService" behaviorConfiguration="PresidentsServiceBehavior"> <endpoint address="" binding="webHttpBinding" contract="PresidentsService.IPresidentsService" behaviorConfiguration="web"> </endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior name="PresidentsServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="web"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer> </configuration>

Test the WCF REST Service

  1. Since REST services are accessed via standard web methods, a web browser is the simplest way to quickly test service wiring and basic operations.  Navigate to the REST service by entering URI for the specified method into the browser's address bar (URL).  Right-click on PresidentsService.svc in the Solution Explorer.  Click View in Browser.

    The following returns a complete list of presidents in JSON:




    The following returns a complete list of presidents in XML:

  2. There is also a useful REST add-on for Firefox named RESTClient that can be extremely valuable developing, testing and debugging REST and XML services.
Now that we have a REST service, the next step is Consuming a WCF REST Service.

4 comments:

  1. Great article - easy to follow and understand...what can I do if I don't want to use the MIMEType helper? thanks again!

    ReplyDelete
    Replies
    1. The MIMEType helper is just an aid so you can quickly see the actual results in the browser and not have to download the file and view it externally. So, the easiest thing is to either comment-out or remove the associated calls. Thanks, Jason.

      Delete