Idea for a Helper Utility Class Generator for a WCF Rest Service

This morning I followed an Adobe Flex tutorial, well 3, about consuming Twitters restful API inside Flex.  After this it got me thinking about WCF and their Rest Starter Kit.  I looked and they are now up to Preview 2, so I downloaded it and in my spare time focused on this recently release white paper:

A Guide to Designing and Building RESTful Web Services with WCF 3.5

Installing the starter kit, which also installs some project templates, gives you a good starting point.  It also introduced me to some new concepts.  The starter kit actually generates a help page for your service which is an xml feed and XSLT Style Sheet e.g.

image

So It provides all the relevant information required i.e. the method, the uri template, the request and response schema.  I tested out a quick code up for the simplest form for consumption by C# and it worked out pretty well.  I focused on the fact that the info can be returned currently in two formats being XML and also JSON.  I wanted an abstract class to hold the URI’s for each method and also abstract methods which each derived object needs to override.

The idea is ultimately to have strongly typed helper methods for consuming restful apis.  So the tool, similar to the WSDL or SVCUTIL could be supplied with the following information:

  • namespace
  • language
  • url of help feed
  • asynchronous

What I would want to build on is the language part, as the interoperability of a rest api is huge.  If you make an implementation of the help generator in C# for example and use a Strategy pattern for the generation then this gives rise to the following:

  • C# Generation Strategy
  • VB.NET Generation Strategy
  • ActionScript Generation Strategy
  • C++ Generation Strategy
  • Pure JavaScript Generation Strategy
  • Jquery Generation Strategy (Yes I differentiated from the JavaScript option)
  • PHP Generation Strategy
  • Java Strategy
  • Python Strategy
  • Ruby on rails strategy

So you get the idea, it could be built then extended over time.  Am I getting ahead of myself here?  Is there one in production? WHO KNOWS? but it is fun never the less to jump in and have a go. 

So the quick Code Up I did is as follows:

Duplicate the type used in the REST Service and decorate with the namespace for XML Serialization needs

    [XmlRoot(Namespace="http://schemas.datacontract.org/2004/07/Swissmod.Service.Model")]
    public class Project
    {
        public string ID { get; set; }
        public string UserID { get; set; }
        public string ClientID { get; set; }
        public string ProjectTitle { get; set; }
        public string ProjectDescription { get; set; }
        public DateTime Created { get; set; }
        public DateTime LastModified { get; set; }
        public string Version { get; set; }

        public override string ToString()
        {
            StringBuilder sb1 = new StringBuilder();

            foreach (PropertyInfo pi in this.GetType().GetProperties())
            {
                sb1.AppendLine(pi.Name + " : " + pi.GetValue(this, null));
            }

            return sb1.ToString();
        }
    }

Define the abstract class for the Project Service

    public abstract class ProjectRestClient
    {
        protected string baseUrl = "http://test.@yoursite.com/ProjectService.svc/";

        public abstract Project GetProject(string id);
    }

Implement an XML Version of the Project Rest Client

    public class ProjectXmlRestClient : ProjectRestClient
    {
        public override Project GetProject(string id)
        {
            WebRequest wr = WebRequest.Create(baseUrl + id);
            wr.Method = "GET";
            wr.ContentType = "text/xml";
            WebResponse wresp = wr.GetResponse();
            XmlSerializer serializer = new XmlSerializer(typeof(Project));
            XmlReaderSettings settings = new XmlReaderSettings();
            settings.ValidationFlags = XmlSchemaValidationFlags.None;
            settings.ValidationType = ValidationType.None;
            settings.ConformanceLevel = ConformanceLevel.Auto;
            settings.IgnoreProcessingInstructions = true;
            settings.NameTable = new NameTable();
            settings.NameTable.Add("http://schemas.datacontract.org/2004/07/Swissmod.Service.Model");
            XmlReader reader = XmlReader.Create(wresp.GetResponseStream(),settings);
            Project p = (Project)serializer.Deserialize(reader);
            return p;
        }
    }

Implement a JSON Version of the Project Rest Client

    public class ProjectJsonRestClient : ProjectRestClient
    {
        public override Project GetProject(string id)
        {
            WebRequest wr = WebRequest.Create(baseUrl + id + "?format=json");
            wr.Method = "GET";
            WebResponse wresp = wr.GetResponse();
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Project));
            Project p = (Project)serializer.ReadObject(wresp.GetResponseStream());
            return p;
        }
    }

Give it a whirl

At this point I know what is going to happen, but I am just protyping to give myself ideas for when I come to make a generation tool for the actual complete feed.  IF I CAN OFCOURSE! lol :-)

    public static class Program
    {
        const string XML = "XML";
        const string JSON = "JSON";

        [STAThread]
        public static void Main(string[] args)
        {
            IUnityContainer container = new UnityContainer();
            container.RegisterType<ProjectRestClient, ProjectXmlRestClient>(XML, new ContainerControlledLifetimeManager());
            container.RegisterType<ProjectRestClient, ProjectJsonRestClient>(JSON, new ContainerControlledLifetimeManager());

            ProjectRestClient xmlCient = container.Resolve<ProjectRestClient>(XML);
            ProjectRestClient jsonCient = container.Resolve<ProjectRestClient>(JSON);

            Console.WriteLine(xmlCient.GetProject("1"));
            Console.WriteLine(jsonCient.GetProject("1"));

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }

P.S. I have used unity here for a few reasons but mainly because I love the idea of Inversion of Control and Dependency Injections.  The above simply allows me to obtain a singleton instance of either class whenever I want to execute a service method.

image

So to summarise, the only reason I am doing this is so that the consumption of the Rest service is strongly typed, I am not doing this because I think it is a necessity, simply because I think it would be extremely helpful for me.  The ability to strongly type things gives me much more happiness when working across language barriers.

Anyways,

Cheers for now,

Andrew

Published Tuesday, March 17, 2009 5:49 PM by REA_ANDREW
Filed under: , ,

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)