blogs.conchango.com

welcome to the conchango blogging site
Welcome to blogs.conchango.com Sign in | Join | Help
in Search

Anthony Steele's Blog

REST from WCF 3.5

WFC is well known to be brilliant at SOAP, and fans of WCF may be aware that in version 3.5 may be aware of the cool new features. But the rest of us (the REST of us, haha, I'm so funny)  may not know that it addresses in a simple and flexible way other scenarios- that is, serving XML or JSON data off simple Urls in a REST style.

 

This note is be based information from talks by Aaron Skonnard (http://www.pluralsight.com/blogs/aaron/) and Richard Blewett (http://www.dotnetconsult.co.uk/weblog2/) given at Devweek. I went to these talks to get a basic understanding of WCF, and found a couple of interesting features as well.

 

Before the REST in introduced , I'll start with a simple service that when you give it your name, will greet you.

 

The contract is:

 

using System.ServiceModel;

 

namespace GreeterLib

{

    [ServiceContract]

    public interface IGreeterService

    {

        [OperationContract]

        string Greet(string name);

    }

}

 

The service implementation is

 

namespace GreeterLib

{ 

    public class GreeterService : IGreeterService

    {

        public string Greet(string name)

        {

            return string.Format("Hello, {0}", name);

        }

    }

}

 

This is hosted for debug purposes in a console as follows:

 

using System;

using System.ServiceModel;

 

using GreeterLib;

 

namespace GreeterConsole

{

    class Program

    {

        static void Main(string[] args)

        {

            using (ServiceHost serviceHost = new ServiceHost(typeof(GreeterService)))

            {

                serviceHost.Open();

 

                Console.WriteLine("WCF Service is running...");

                Console.ReadLine();

 

                serviceHost.Close();

            }

 

            Console.WriteLine("WCF Service has closed");

        }

    }

}

 

And as always with WFC, the config file does a lot of the heavy lifting of tying things together:

  

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <bindings>

     

    </bindings>

    <services>

      <service name ="GreeterLib.GreeterService" behaviorConfiguration="Default">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8080/greeter"/>

          </baseAddresses>

        </host>

        <endpoint

          address=""

          binding ="basicHttpBinding"

          contract="GreeterLib.IGreeterService" />

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="Default">

          <serviceMetadata httpGetEnabled="true"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

 

 

So far so usual and SOAPy. I can run the console, and verify that at http://localhost:8080/greeter there is a service, it has wsdl at http://localhost:8080/greeter?wsdl, which specifies the soap that I would need to craft if I wanted to talk to it. I'm not going to do that manually.

 

To do this in a REST style, we change as follows:

The contract needs a WebGet attribute, specifying the URL to match:

 

using System.ServiceModel;

using System.ServiceModel.Web;

 

namespace GreeterLib

{

    [ServiceContract]

    public interface IGreeterService

    {

        [OperationContract]

        [WebGet(UriTemplate = "greet/{name}")]

        string Greet(string name);

    }

}

 

 

The program needs to use WebServiceHost:

 

using System;

using System.ServiceModel;

using System.ServiceModel.Web;

 

using GreeterLib;

 

namespace GreeterConsole

{

    class Program

    {

        static void Main(string[] args)

        {

            using (WebServiceHost serviceHost = new WebServiceHost(typeof(GreeterService)))

            {

                serviceHost.Open();

 

                Console.WriteLine("WCF Service is running...");

                Console.ReadLine();

 

                serviceHost.Close();

            }

 

            Console.WriteLine("WCF Service has closed");

        }

    }

}

 

The config needs to use the webHttpBinding binding

 

      <service name ="GreeterLib.GreeterService" behaviorConfiguration="Default">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8080/greeter"/>

          </baseAddresses>

        </host>

        <endpoint

          address=""

          binding ="webHttpBinding"

          contract="GreeterLib.IGreeterService" />

      </service>

 

And there you go. You can now run this, and hit the URL http://localhost:8080/greeter/greet/Anthony

 

and get the response

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">Hello, anthony</string>

 

You can also return data in JSON format by setting attributes.

 

But if you hack around a bit, you can also take full control of the XML returned, and serve some Plain Old XML if you want, as follows:

 

The contract must return a Message:

 

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Channels;

using System.ServiceModel.Web;

 

namespace GreeterLib

{

    [ServiceContract]

    public interface IGreeterService

    {

        [OperationContract]

        [WebGet(UriTemplate = "greet/{name}")]

        Message Greet(string name);

    }

}

 

The service:

 

using System.ServiceModel.Channels;

using System.Xml;

using System.Text;

using System.IO;

 

namespace GreeterLib

{

 

    public class GreeterService : IGreeterService

    {

        public Message Greet(string name)

        {

            XmlReader xmlReader = MakeXml(name);

            return Message.CreateMessage(MessageVersion.None, "", xmlReader);

        }

 

        private XmlReader MakeXml(string name)

        {

            StringBuilder buffer = new StringBuilder();

            using (XmlWriter xmlWriter = XmlWriter.Create(buffer))

            {

                xmlWriter.WriteStartDocument();

                xmlWriter.WriteStartElement("greeting");

                xmlWriter.WriteAttributeString("type", "hello");

                xmlWriter.WriteString(string.Format("Hello, {0}", name));

                xmlWriter.WriteEndElement();

                xmlWriter.WriteEndDocument();

            }

 

            TextReader reader = new StringReader(buffer.ToString());

            return XmlReader.Create(reader);

        }

    }

}

 

And you'll ret the returned data:

 

<greeting type="hello">Hello, anthony</greeting>

 

So there it is: POX over REST served by WCF. And it wasn't very difficult.

Published 15 March 2008 16:18 by Anthony.Steele
Filed under: , , , , , ,

Comments

 

Minority blog said:

Zn&#225;te REST? S b&#225;ječnou podporou webov&#253;ch služeb založen&#253;ch na protokolu SOAP ve Visual

June 11, 2008 12:27
Anonymous comments are disabled

About Anthony.Steele

Programmer in c# for Conchango
Powered by Community Server (Personal Edition), by Telligent Systems