How to create REST/POX web services with WCF

Posted by adamjh on Nov 6th, 2007

After a horribly unfulfilling day of hacking at .Net, Perl, and Ruby SOAP implementations... trying to get them to talk nicely to each other... I went to sleep last night with the realization that attempting to achieve interoperability through SOAP would be a never-ending war.

So, I woke up this morning with the desire to make some of our .Net web services RESTful.  One of the great things about Windows Communication Foundation (WCF), the subset of the .Net Framework that provides web service capabilities, is the ability to switch between SOAP/REST and POX/JSON configurations without changing most of your underlying code.

Unfortunately, with .Net 3.5 and Visual Studio 2008 still in beta (for at least a few more weeks anyway), I couldn't find any good documentation/tutorials/howtos on how to do this.  So, after a lot of trial and error, here are the steps to successfully create a RESTful web service with Plain Old XML endpoints, starting with the sample WCF Service Application template that ships with Visual Studio:

1. Create a new WCF Service Application

In Visual Studio, create a new Visual C# project using the "WCF Service Application" template.

2. Add a RESTful service endpoint

In your application's configuration file (Web.config or App.config), add the following endpointBehaviors section right above the existing serviceBehaviors section.  It should now look something like this:

    <behaviors>
      <
endpointBehaviors>
        <
behavior name="webBehavior">
          <
webHttp />
        </
behavior>
      </
endpointBehaviors>
      <
serviceBehaviors>

Now add the following "rest" endpoint to your existing service section so that it looks like:

      <service name="RESTService.Service1" behaviorConfiguration="RESTService.Service1Behavior">
        <!--
 Service Endpoints -->
        <
endpoint address="" binding="wsHttpBinding" contract="RESTService.IService1"/>
        <
endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <
endpoint address="rest" behaviorConfiguration="webBehavior" binding="webHttpBinding"
         bindingConfiguration="" contract="RESTService.IService1" />
      </
service>

3. Reference System.ServiceModel.Web 

Add a reference to the .Net System.ServiceModel.Web assembly.  You can do this by going to Project->Add Reference, and selecting "System.ServiceModel.Web" from the .NET tab.

At the top of your service interface file (i.e. IService1.cs), add:

using System.ServiceModel.Web;

4. Add a WebGet attribute

The default sample GetData() method in your service interface file should look like:

        [OperationContract]
        string GetData(int intParam);

We'll make this RESTful and accessible through HTTP GET by adding a WebGet attribute:

        [OperationContractWebGet]
        string GetData(int intParam);

Testing it out

At this point, you should be able to build and run your program, and access your new RESTful web service at the following URL:

http://localhost:[port]/Service1.svc/rest/GetData?intParam=1337 

You should get the following output:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">You entered: 1337</string>

Note: [port] will be chosen at random when you build and run your program from within Visual Studio.  When you run for the first time, you will see a notification with the port in the system tray.  You can also hover over the ASP.NET Development Server icon in the system tray at any time to find the port number.

Using HTTP POST and URI Templates

If you want to submit information to your service using HTTP POST or another HTTP method, simply replace the WebGet attribute with the WebInvoke attribute, whichdefaults to POST and has an optional Method parameter (for PUT, DELETE, and other less common methods).

If you want to use a different URI scheme, WCF makes it really easy to do so.  For example, try:

        [OperationContractWebGet(UriTemplate = "data/{intParam}")]
        string GetData(string intParam);

And now try accessing your service at:

http://localhost:[port]/Service1.svc/rest/data/5 

Notes: We had to change the intParam from type int to type string, because URI Templates expect string parameters.  Inside of the GetData() method, we could convert the parameter back to an int with a simple call to int.Parse(intParam).  It's also possible to clean up the "Service1.svc" and "rest" URI sections by changing the service host and endpoint addresses.

Hope this helps anyone out there trying to get started creating a simple REST/POX web service with WCF.  This should be significantly better documented in the near future as Visual Studio 2008 RTMs.  At that point, some of the snippets above may need to change slightly depending on any changes that have been made to the framework or the sample applications since Beta 2 -- if you notice any issues or find this useful, please post a comment!

Also, for a lot more background on web services in .Net, check out Steve Maine's blog.  I saw him speak earlier this year at MIX, and he and his team are doing some really great work at Microsoft in this area.

Month 3: Road trip!

Posted by adamjh on Oct 11th, 2007

Well, it's certainly been a busy two months!  So much so that we got distracted from writing a second monthly update earlier in September.

Recently, we've had some pretty interesting developments:

First, we're incredibly happy to share that our little startup has grown by 50% in size.  Or, in other words, a third person has recently decided to join Jeff and me on our adventure!  I'd better skimp on the details for now and let him post his own introduction and story as soon as he's had the opportunity to wrap things up at his current gig and settle down here.  But suffice it to say, we're all incredibly excited.

Beaver Island MapSecond, we're moving!  The initial plan was to work out of space in my parents' home in Los Angeles for the first six months, but Jeff and I felt that having three of us living and working full-time would be a bit overkill (despite their awesome level of support in offering to make it work).  Luckily, Jeff's family graciously offered us an empty apartment to live and work out of on their property on Beaver Island, Michigan.

So, in a move that has left some of our friends and family scratching their heads, we're taking the show on the road for roughly another three months while we burrow away and continue to develop technology together from the island.

Here are some pictures of Beaver Island in the winter (courtesy of the Beaver Beacon):

Beaver Island Ice

If you would like to come visit us, there are daily and charter flights available through Fresh Air Aviation and Island Airways (Jeff developed the flight reservation system), or ferry rides through Beaver Island Boat Co (until the lake freezes over).

Is this startup suicide?  Paul Graham and The New York Times both might have you believe so!  But the argument that all startups must begin in Silicon Valley seems to hinge on "all other things being equal", which they rarely if ever are.  We're hoping that our divergent path will enable us to invest more time early in developing differentiating technology, bootstrapping all-the-while for as long as possible.  And then, eventually, we'll return to a metropolis, rejoin the tech world, and start going to trendy "Lunch 2.0" style events again (if they still exist).

So, with that, we'll be departing LA over the last weekend in October.  Jeff will be driving his car another 2,000 miles back to Michigan.  I'll be sticking around for my Dad's birthday on the 28th, and rendezvousing with Jeff and secret agent #3 at the airport in Flint, Michigan.

Before we go, we'll be hitting up this month's October g33k d1nner, and we're planning a quick visit to the bay area.  If you're up there and know us or wanna meet us, drop us a line!

Fluxify: A simpler way to resize and email your photos

Posted by adamjh on Sep 21st, 2007

We've been incognito for awhile, but that doesn't mean we've been lazy. We spent the last seven days or so building a free service, to which the rest of this post is dedicated.

If you have a digital camera and have ever tried to email photos to friends or family, you've probably been faced with an inconvenient set of tasks that goes something like this:

  1. Make a copy somewhere on your computer of all the large photos you want to send so that you can resize them first in order to keep the size of the email down.
  2. Use a graphic design or imaging program to resize the newly created photo copies (insert many extra steps here if your program cannot do batch resizes or if you end up surfing the web to find and install shareware that can).
  3. If you use a web-based email service such as Gmail, compose a new message, then individually browse to and attach each resized photo to your message. Send.
  4. Switch contexts again out of your email and clean up those photo copies you made in step one.

If you're like me, you just find this cumbersome and annoying. If you're like my Mom and Dad (who do own a digital camera that produces 12 megapixel photos), the barrier is so high that you simply don't bother to try.

To make this easier and more accessible to everyone, we've published a web-based tool we're calling Fluxify that lets you automatically resize, upload, and email photos... without the effort.

Fluxify ScreenshotIt's free, and it doesn't require you to create an account. It should work in at least Firefox and IE, and on both a Mac and a PC. We built fluxify in Silverlight, and so you'll be prompted to install the Silverlight browser plugin if you've never visited a Silverlight-enabled site before (just like the first time you run Flash).

Fluxify is interesting in that it resizes your photos before it uploads them, saving you time and bandwidth. For web developers, we think this is a pretty revolutionary cross-platform capability: You can drop the "Max file size: 500KB" fine print (just resize it on the client-side), and avoid using cumbersome ActiveX/Java alternatives to achieve the same result.

We'll be posting another entry with more technical details on how we built Fluxify, what's going on behind the scenes, and how developers can incorporate similar client-resize features into their own services on the web. For now, we've assembled some details on the about page.

Check it out and let us know what you think!

Month 1: Breaking in the garage

Posted by adamjh on Aug 5th, 2007

A wise man once said:

Keep on going and the chances are you will stumble on something, perhaps when you are least expecting it. I have never heard of anyone stumbling on something sitting down.

And so has been the theme of month one. After roughly 9 months of sporadic brainstorming sessions about what our company might do should Jeff someday decide to stop pursuing his Ph.D. and I to leave my job, we chose on day 1 to table any further planning discussions and start hacking.

This continued for roughly 25 days (or 32,000 lines of code), at which point we were able to take a step back with a greater understanding than ever before of the beast we're attempting to tame -- what's easy? what's hard? what's been done before and what never has? how long should it take? what kind of people should we attempt to hire first and how soon? and so on...

We then decided to invest some time over roughly 3 days to revisit some of the "businessy" stuff. We jotted down all the company/product names that had been thrown out over time on our beat up whiteboard and evaluated them according to the nine dimensions suggested in the Igor Naming Guide, then discarded them all in favor of something else we came up with on a whim and decided we liked better.

We threw together 3 slides of the 10/10/15 that Guy, David, and Brad recommend, as a sanity check as to whether we could clearly and concisely articulate our vision/value. We explained what we were were building to a handful of friends in no more than 2-3 sentences, and listened to whether the response was a "What?" or a "Wow!", refining our vision down to a simple 5 words until the "What"s were no more.

As the weekend progresses and month 1 comes to an end, we're continuing to wrap up our first stretch of coding -- getting various disjointed pieces to fit together, grepping for BUGBUGs/TODOs, and ensuring we have something that works end-to-end however small in scope. Then it's on to another month of code, with a new set of goals.

In closing, I'll pose a question that's been on my mind lately to anyone out there who follows our journey:

Ambient OrbHow would you convey the value proposition of one of our favorite products, the Ambient Orb?

What kind of ROI can its customer expect by buying it?

What kind of pain does it eliminate?

Is it a vitamin, aspirin, or antibiotic (i.e. a luxury, nice-to-have, or need-to-have)?

How to consume a WCF service from Perl with SOAP::Lite

Posted by adamjh on Jul 23rd, 2007

Due to the outdated state of Perl's only SOAP library and less-than-stellar documentation on Windows Communication Foundation web service interoperability, getting a Perl script to consume a WCF service sent me on a debugging adventure accompanied by a scavenger hunt for information scattered across the web.

Below are the tweaks that must be made to a new WCF service created using the "WCF Service Library" project template in Visual Studio 2008 Beta 1 ("Orcas") and an example of a how to call the service from a SOAP::Lite client script:

Step 1. Change the service endpoint binding from the default wsHttpBinding to basicHttpBinding:

    <endpoint address ="" binding="basicHttpBinding" contract="Service1.IService1" />

Step 2. Change the data contract format to RPC:

    [ServiceContract]
    [DataContractFormat(Style=OperationFormatStyle.Rpc)]
    public interface IService1
    {

Step 3. Specify an on_action() method in the SOAP::Lite client to override the default Namespace#Action with the format WCF expects:

$data = SOAP::Lite
  -> uri('http://tempuri.org/')
  -> proxy('http://localhost:8080/IService1')
  -> on_action(sub{sprintf '%sIService1/%s', @_})
  -> GetData(SOAP::Data->name('intParam' => 5))->result;

Note: If you decide to do this, you should understand the implications of changing the service endpoint binding and the data contract format.  Supporting information is available somewhere in the bowels of MSDN.

Update [Nov 5 2007]: I ran into new problems when moving from SOAP::Lite 0.55 (the highest supported in ActivePerl on Windows) to SOAP::Lite 0.69 (the latest version as of now, and running on Linux).  It seems SOAP::Lite evolved from the SOAP 1999 (1.1) to 2001 (1.2) schema, and somewhere in the mix, new conflicts arose with WCF interoperability.  After a few hours of horrid tracing and hacking, I've decided to ditch Perl and SOAP altogether for Ruby and REST.  Welcome, Adam, to the year 2007.

Next »