Home > .net, wcf > Flickr WCF Part I - Basic Manual WCF Component

Flickr WCF Part I - Basic Manual WCF Component

February 10th, 2009

This is the first part in a series of blog posts where I see how many different aspects of WCF I can exercise with the same basic component definition. In this article we’re going to define our contracts, create a service, create a IIS host, hand-code a proxy and have a Console app spit out URLs to the 100 most recent photos uploaded to Flickr.

This and subsequent articles assume some basic working knowledge of WCF. If you’ve worked your way through a couple of tutorials, you’ll be fine.

The basic logic of the calling out to Flickr and the extension method I use are described in the previous blog post which is a prelude to this series. Please take a look at that article if you have trouble following along.

For simple cases like the one we’re working on here, I find that hand coding all of the WCF logic is the easiest and most straightforward way to make my code work. Using the svcutil.exe or the Add Service Reference feature in VS 2008 works, but both methods add unnecessary cruft that add to the complexity and understanding of the code. So, here we go!

Our objective is to call the Flickr API getting information about the 100 photos flickr deems interesting for the day, extract out of the XML the necessary information to create URLs to the medium sized jpg and then spit the URLs out to the console window. The first thing we’ll do is create a Class Library project called BasicFlickrWCFContracts in a solution named BasicFlickrWCFApp. Add references for System.ServiceModel and System.Runtime.Serializations.

In this solution, add a new class file named FlickrPhoto.cs. The code for FlickrPhoto will look like this:

   <br />using System;    <br />using System.Runtime.Serialization;</p>  <p>namespace Donaghe.FlickrInfoComponent   <br />{    <br />[DataContract]    <br />public class FlickrPhoto    <br />{    <br />string farm = string.Empty;    <br />string server = string.Empty;    <br />string id = string.Empty;    <br />string secret = string.Empty;    <br />string owner = string.Empty;    <br />string title = string.Empty;    <br />string url = string.Empty;    <br />string flickrUrl = string.Empty;</p>  <p>[DataMember]   <br />public string Farm    <br />{    <br />get { return farm; }    <br />set { farm = value; }    <br />}</p>  <p>[DataMember]   <br />public string Server    <br />{    <br />get { return server; }    <br />set { server = value; }    <br />}</p>  <p>[DataMember]   <br />public string Id    <br />{    <br />get { return id; }    <br />set { id = value; }    <br />}</p>  <p>[DataMember]   <br />public string Secret    <br />{    <br />get { return secret; }    <br />set { secret = value; }    <br />}</p>  <p>[DataMember]   <br />public string Owner    <br />{    <br />get { return owner; }    <br />set { owner = value; }    <br />}</p>  <p>[DataMember]   <br />public string Title    <br />{    <br />get { return title; }    <br />set { title = value; }    <br />}</p>  <p>[DataMember]   <br />public string Url    <br />{    <br />get { return url; }    <br />set { url = value; }    <br />}</p>  <p>[DataMember]   <br />public string FlickrUrl    <br />{    <br />get { return flickrUrl; }    <br />set { flickrUrl = value; }    <br />}    <br />}    <br />}</p>  <p>

This class definition is basically just a plain vanilla WCF data contract. We will use this class to help us build our photo URLs.

Now add an interface file to your project. Name is IFlickrInfo.cs. This will define a single operation to return recent Flickr photos. The code is simple and looks like this:

   <br />using System;    <br />using System.Collections.Generic;    <br />using System.Linq;    <br />using System.Text;    <br />using System.ServiceModel;</p>  <p>namespace Donaghe.FlickrInfoComponent   <br />{    <br />[ServiceContract]    <br />public interface IFlickrInfo    <br />{    <br />[OperationContract]    <br />List<flickrphoto> GetRecentPhotos();    <br />}    <br />}</p>  <p>

The next step is to create the service which will give life to our new ServiceContract. Create a new Class Library project and name it FlickrInfoService. Add a reference to System.ServiceModel as well as a Project Reference to the BasicFlickrWCFContracts project.

I use an extension method that I created for System.Net.WebClient as described in the previous blog post. You can either create this yourself or download a copy of my extensions dll here. If you use my dll, add a reference to it and you’ll need to add a using statement in your code like this:

   <br />using TadsExtensions;    <br />

Add a new class file to this project and name it FlickrInfoService.cs. Copy and paste this code into it:

   <br />using System;    <br />using System.Collections.Generic;    <br />using System.Linq;    <br />using System.Net;    <br />using System.ServiceModel;    <br />using System.Text;    <br />using System.Xml.Linq;    <br />using TadsExtensions;</p>  <p>namespace Donaghe.FlickrInfoComponent   <br />{    <br />public class FlickrInfoService : IFlickrInfo    <br />{    <br />#region IFlickrInfo Members</p>  <p>public List<flickrphoto> GetRecentPhotos()   <br />{    <br />List<flickrphoto> photos = new List<flickrphoto>();</p>  <p>XElement x = (new WebClient()).DownloadXElement("http://api.flickr.com/services/rest/?method=flickr.interestingness.getList&amp;amp;amp;amp;amp;api_key=YOURFLICKRAPIKEYHERE");</p>  <p>var query = from b in x.Elements("photos").Elements("photo")   <br />select new FlickrPhoto    <br />{    <br />Farm = b.Attribute("farm").Value,    <br />Id = b.Attribute("id").Value,    <br />Secret = b.Attribute("secret").Value,    <br />Server = b.Attribute("server").Value,    <br />Owner = b.Attribute("owner").Value,    <br />Title = b.Attribute("title").Value    <br />};</p>  <p>foreach (FlickrPhoto photo in query)   <br />{    <br />StringBuilder urlBuilder = new StringBuilder();</p>  <p>urlBuilder.Append("http://farm");   <br />urlBuilder.Append(photo.Farm);    <br />urlBuilder.Append(".static.flickr.com/");    <br />urlBuilder.Append(photo.Server);    <br />urlBuilder.Append("/");    <br />urlBuilder.Append(photo.Id);    <br />urlBuilder.Append("_");    <br />urlBuilder.Append(photo.Secret);    <br />urlBuilder.Append("_m.jpg");</p>  <p>photo.Url = urlBuilder.ToString();</p>  <p>StringBuilder urlBuilder2 = new StringBuilder();</p>  <p>urlBuilder2.Append("http://www.flickr.com/photos/");   <br />urlBuilder2.Append(photo.Owner);    <br />urlBuilder2.Append("/");    <br />urlBuilder2.Append(photo.Id);</p>  <p>photo.FlickrUrl = urlBuilder2.ToString();</p>  <p>photos.Add(photo);   <br />}</p>  <p>return photos;   <br />}</p>  <p>#endregion   <br />}    <br />}</p>  <p>

The bulk of this code is explained in the my previous blog entry. Please see it if you need a better understanding of what’s going on.

Of interest is the code that sets the photo.Url and photo.FlickrUrl. The Url is the link to the actual photograph and the FlickrUrl is a link to the page on Flickr where you can view the photo in the owner’s photostream. This code follows the simple recipe given by Flickr on this page. For this solution we’re only interested in photo.Url. In my Flickr Toy app, I use photo.FlickrUrl to allow users to click a photo and go to its Flickr page.

Now it’s time to create a host for our component. In this case we’ll create an IIS host. I find IIS hosts very simple to implement and use. So, go to File->New->Project->ASP.NET Web Application. Name it FlickrInfoIISHost.

Delete the Default.aspx page - we won’t need it. Add Project references to BasicFlickrWCFContracts and FlickrInfoService. Now add a plain text file to the project. Name it FlickrInfoIISHost.svc. Edit the file to look like this:

[sourcecode language="asp"]
<%@ ServiceHost Service=”Donaghe.FlickrInfoComponent.FlickrInfoService” %>
[/sourcecode]

Open the Web.config file and paste the following code down at the bottom just before the configuration end node:


Find the compilation tag and set its debug attribute to true like this:


I like to specify the port for my IIS hosting projects manually. To do this, right click on the FlickrInfoIISHost project and choose Properties. Click the Web tab and make sure the “Specific Port” radio button is selected. For this example I set the port to 51030. You’ll see why when we create our client.

Now let’s try our host and see if it’s working properly. In Solution Explorer, right click the FlickrInfoIISHost project and chose “Set as Startup Project” from the context menu. Now run the solution by pressing ctrl-F5. This will start the service and will probably show a web page in your default browser just showing a directory listing. This isn’t what we’re interested in. Append FlickrInfoIISHost.svc to the end of the URL shown in the page that opened up. Now you should see the default WCF page showing how to set up Metadata Exchange which we’re going to ignore in this tutorial. This is good enough to let you know that your service is being hosted.

Next we need to create a proxy which will be used by our client to communicate with our new host. Most WCF tutorials have you create a proxy by adding a Service Reference or by using svcutil.exe. Here we’ll do it manually. It’s awfully simple, actually.

So, add a new Class Library project to your solution and name it FlickrInfoProxy. Change the name of the class file that’s been added for you to FlickrInfoProxy.cs. Add a Project Reference to BasicFlickrWCFContracts and a reference to System.ServiceModel. Now replace the code in your class with this code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;

namespace Donaghe.FlickrInfoComponent
{
public class FlickrInfoProxy : ClientBase, IFlickrInfo
{
#region IFlickrInfo Members

public List GetRecentPhotos()
{
return Channel.GetRecentPhotos();
}

#endregion
}
}

Our proxy is a subclass of the ClientBase generic class based on our IFlickrInfo interface. Our proxy will also implement the IFlickrInfo interface. ClientBase gives us the proxy magic. It creates a WCF communications channel between our client (which specifies the host in its configuration) and our host. Implementing IFlickrInfo allows our proxy to call the proper method at the right time. We only have one method in our interface and our proxy just passes the call on to the host.

Building a proxy in this way allows us to reuse it with any number of other clients. It will be built as a dll and can be referenced whenever a client needs it without polluting the client project with irrelevant details. Proxies can become a lot more complex, as you can see if you ever create one by adding a ServiceReference, but in simple cases, why not use a simple proxy?

Now for the client. In this example we will create a super simple console application client. So, add a new Console Application to the solution and name it FlickrInfoClient. Add Project references to BasicFlickrWCFContracts and FlickrInfoProxy as well as a reference to System.ServiceModel.

Replace the code in Program.cs with this code:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Donaghe.FlickrInfoComponent
{
class Program
{
static void Main(string[] args)
{
FlickrInfoProxy proxy = new FlickrInfoProxy();

Console.WriteLine("Getting recent Flickr photos...");

using (proxy as IDisposable)
{
List photos = proxy.GetRecentPhotos();

foreach (FlickrPhoto photo in photos)
{
Console.WriteLine(photo.Url);
}
}

Console.WriteLine("Press the ENTER key to end this program...");

Console.ReadLine();
}
}
}

First we create a new instance of our proxy. The using line allows us to treat our Proxy as IDisposable. This lets us not need to worry about opening and closing the communications channel to the host. It’s done for us automatically. The rest of the code in the using block is straightfoward and shows just how easy it is to deal with a WCF component that’s hosted by IIS. Of course, we’d use the same exact code if the component was hosted on another machine in a Windows Service and accessed via NetTCP.

This isn’t everything we need though. Our client needs to contain information so that the proxy knows how to talk with the host. We’ll put this information into an App.config file. So, right click on the client project and chose Add New Item and in the dialog choose Application Configuration File. This will add a new file named App.config. Make your App.config file look like this:


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

binding="wsHttpBinding"
contract="Donaghe.FlickrInfoComponent.IFlickrInfo"
/>

In our client configuration we always need to specify the ABC’s of WCF. Address, Binding and Contract. The address is, unsurprisingly the address to the .svc file that we put in our IIS Host. Note that the port used is the same as the one we specified in the host. The binding is also the same as what we configured on the host side. The contract is the fully qualified name of our component’s interface.

Here’s how to run and test our WCF application. First, press ctrl-F5 to run the IIS host. Now, while the host is running, right click on the client project and chose Debug->Start new instance. This will open the Console window and run the client code. Your results should look something like this:

In subsequent articles we’ll use this same component and extend it and exercise many WCF features with it. Coming up we’ll create a simple Windows Form application and use our component in-process.

I am by no means an expert in this, so please feel free to leave a comment if you’ve spotted a bug, or a better way to do something or even any criticism you have. I appreciate it!

Here is a zip file containing all of the source code in the application talked about above: Basic Flickr WCF App

kick it on DotNetKicks.com

Tad .net, wcf

Viewing 2 Comments

 

Trackbacks

(Trackback URL)

close Reblog this comment
blog comments powered by Disqus
Clicky Web Analytics