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.

Silverlight’s niche, and its missing piece

Posted by jeff on Sep 30th, 2007

As it stands, I don't see Silverlight as a Flash-killer.  Flash is mature and still actively developed; Adobe recently opened up Flex (Flash development framework) as an open source project - perhaps intended to keep an edge over Silverlight in developers' minds.

That said, I want to make the claim that Silverlight 1.1 has the capability to outshine Flash/Flex for a certain class of CPU-intensive web applications, of which Fluxify is an example.  For starters, you need to check out Alexey Gavrilov's BubbleMark.  The site compares Flash, Silverlight, and a bunch of different web platforms in terms of their performance at displaying some bouncing bubbles.

Sure, bouncing bubbles are probably not the most representative of web applications in general, but Alexey did an incredible job of touching seemingly every platform.  On my machine, the optimized Flex version of BubbleMark achieves 64 fps, the Silverlight+Javascript version slogs through at similar speeds, whereas the Silverlight+CLR equivalent chimes in around 270 fps, or 4.2 times faster!  This faster CLR version requires Silverlight 1.1, and is written in C# instead of Javascript.  Thus, I assume that Silverlight's CLR engine is a lot faster (4.2X) than the Flex runtime, and this is the basis for the claim. 

To dig deeper, let's compare three numbers: 371, 3827, and 907 (kilobits per second).

371: This is a recent measure of the median internet upload speed in the USA.

3827: This is the effective speed at which Fluxify (w/Silverlight CLR) can upload a JPEG, including all client-side processing. Of course we're not uploading the full-size files, but for many applications (such as emailing photos), doing so is unnecessary.

907: This is the effective speed at which a Flash/Flex application could do the same thing, assuming the BubbleMark speed comparison holds, and that you can avoid uploading the image first for this example as well. 

To make this more visceral, let's assume a 12 megapixel JPEG, and convert these speeds into time:

79 seconds @ 371 kbps - Full upload - no client-side processing
32 seconds @ 907 kbps - Flash process + upload
7.7 seconds @ 3827 kbps - Silverlight process + upload

At this point, Flash developers will quickly point out a flaw in my analysis.  As it turns out, Flash Player currently does not allow access to file streams before upload, so the best Flash image editors out there, such as rsizr, are still at the mercy of upload speeds (that is, 79 seconds for our example).  This brings us back to the claim: Silverlight has an advantage in this type of application.  Is it significant enough to prompt developers to adopt it for applications in this niche?  Maybe... but let's look at one more number:

8343: This is the speed at which Fluxify can process and display a JPEG.  For our 12 megapixel example, that's 3.5 seconds.  This figure also applies if we want to save the file locally (for example, if you wanted to attach photos to an email manually, or to upload them manually to another site). Wait, except, you can't do this yet, which brings me to Silverlight's missing piece: the SaveFileDialog.

The SaveFileDialog?

SaveFileDialog sfd = new SaveFileDialog() { 
    Title = "Select a location to save your photo"; }

if( sfd.ShowDialog() == DialogResult.OK )
{
    using (Stream jpgFileStream = sfd.OpenFile())
    {
        /* you wish. */
    }
}

With Silverlight today, there's an OpenFileDialog, which lets us open and process files within the context of our application. We can do whatever we want with the bytes inside this file, and then we have a few options:

1. Display the data

  • We can display arbitrary text data onscreen. We can even display images, but in a very non-ideal way by rendering them manually  (Skip to the bottom for notes regarding this limitation.)

2. Upload the data

  • No problem. We just use the BrowserHttpWebRequest and call your server.

3. Store the data locally

  • We can?! Well, sorta...but only in the IsolatedStore (1MB cap). This means the file is shoved deep within the user's profile:

i.e. %userprofile%/AppData/Local/IsolatedStorage/***
In my case, those stars equate to:

ynckhjp5.2bb/lw1djvut.lfx/Url.wj54i ... /AppFiles
 

Got that? :) Since we can't refer the user to this folder directly, it can't really supplement the missing SaveFileDialog. 

Problem:  A SaveFileDialog doesn't exist, so we can't store the data anywhere useful for the user.  That's why Fluxify doesn't support saving your JPEGs after resize.  In other words, you're stuck at 3827 kbps.  So, where do we go from here?

Solution: Wait for version 2.0?

If this functionality doesn't pop up in Silverlight 1.1, it will give Flash/Flex a chance to bring their runtime up to par with Silverlight's CoreCLR.  Flash developers have requested pre-upload file stream access, and other FileReference enhancements are popping up in Flash 9 Update 3, which will be released tomorrow.  While Flash Player doesn't allow it, there's currently an Adobe AIR trick in use which lets you simulate a "Save File" dialog by faking a download().  Improvements are on the way, and Flash developers can migrate existing applications to do more intensive work client-side.  New developers will decide on Flash/Flex because of its maturity, and timeframe uncertainty on a Go-live license for Silverlight.  Client-side data processing is of course only one of many real-world considerations.  I'm overestimating the cascade influence of this single feature, but I do think developers really care. 

Solution: ActiveX control?

Of course we could make a little browser plugin to allow this, and prompt our users to install some EXE.  Unfortunately, this negates the advantage of using a web platform.

Solution: Google Gears?

Google Gears, a cross-platform tool giving web applications an offline store, can help us get around this problem with its LocalServer functionality -- a browser plugin which intercepts all web requests and potentially redirects them to the local application's data store.  SilverGears is proof of concept showing integration between Silverlight and Gears.  Of course, if you haven't installed Gears yet (I hadn't until today), this is another EXE download.  Gears also has a relational database client-side, which is a big plus for query-bound applications (say, an email client).

If anyone has insight into this problem, or this niche in general, we're very curious to hear.

Notes on image display: Silverlight actually has another missing piece, which is the ability to manipulate images and sounds at a raw level, so that we can perceive results without round-tripping them to the server.  At the very least, we should be able to instantiate these objects from byte arrays.  You can do this in Flash with the BitmapData class.  For Silverlight, one potential trick is to use the browser to display images: Firefox supports the data:uri spec for images.  If you're running Firefox, try Shift-clicking on a resized photo in Fluxify for a demonstration.

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!

Searching for close matches in C#

Posted by jeff on Aug 14th, 2007

Ever have trouble finding things?

This is just a quick code snippet to quickly find the nearest item from a generic list.  It leverages the .NET BinarySearch function, and it also uses the new Extension methods functionality of .NET 3.5.

Here's the extension in its entirety:

public static class BinarySearchExtension
{
    // Computes a distance between the query and a given object.
    public delegate double DistanceFunction<T>(T item);

    // Finds the nearest item to the query item in a sorted list.
    public static int BinarySearchNearest<T>
        this List<T> list, T query, 
        DistanceFunction<T> distFunc) {

        int n = list.Count,
            i = ~list.BinarySearch(query); /* O(log(n)) */

        return 
            (i < 0) ? ~i : /* query (q) was in the list */
            (i < 1) ?  0 : /* q < [0] */
            (i == n) ? n - 1 : /* q > [n-1] */ 
            Math.Abs(distFunc(list[i])) < /* [i] < q < [i-1] */
            Math.Abs(distFunc(list[i - 1])) ?
                i : i - 1; /* return the closest  */
    }
}

Here's an example of using it to search a list of dates:

List<DateTime> times = new List<DateTime>();
times.Add(DateTime.Parse("8/16/2007"));
times.Add(DateTime.Parse("7/7/2007"));

times.Sort(); /* Must be sorted before BinarySearch */

int i = times.BinarySearchNearest(DateTime.Now,
        /* distance: hours between now and t */
        t => t.Subtract(DateTime.Now).TotalHours);

DateTime nearest = times[i]; /* nearest is 8/16/2007 */

I have mixed feelings about extensions. They are clean and messy at the same time -- clean because you can, with very little code, add new functionality to old classes (even those that you didn't write). Unfortunately, because the extensions are separated from the classes they concern, it could easily set up a messy dependency situation. For many projects, I think a good practice is to keep all of your extensions localized together in one assembly.

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 »