As promised here is part 3 of the three part series on Silverlight development. Silverlight is a technology which fits very well in the Web 2.0 environment. One of the neat things about Web 2.0 is the concept of mashups. My focus in this blog is to create a mashup application in Silverlight which retrieves thumbnails from a website, presents the thumbnails and when a thumbnail is clicked the large photo is displayed.
The challenge for this implementation is that Silverlight Alpha 1.1 doesn’t allow cross-domain calling of web services. Microsoft has indicated they are working on providing this functionality; however, they have also indicated it is a hard thing to do and still keep it secured. In the mean time, or maybe forever, I will be showing one way to have Silverlight access a web service on a different domain. The technique I will be using is commonly known as proxy web services. I will be writing a web service in my local web server which in turn calls the web service on another domain and returns the same data types as the original domain’s web service.
In part 2, I left off by creating a web service in the local web server which returned a string to the Silverlight application.
Since part 2 I have gone ahead and modified the XAML from that application and have made it a bit more complex. I have added a few more elements which will support the gallery we’re trying to create.
As you can see from the screen shot above there are a few more elements. I have 4 canvas, and three text blocks. One text block contains the title of the application; the other two text blocks will be turned into buttons. As I mentioned in Part 1, I will not be using any additional controls and because of that, I have to build my own buttons. The text block element has mouse events which we can capture in our code behind. So I have wired the MouseLeftButtonUp event of both the Refresh and Close text blocks in the Page_Loaded event (see below.)
To create my mashup, I chose PhotoPoints.com web services since I’m very familiar with them (I wrote them.) You can find the implementation of these web services at http://www.photopoints.com/ws/ppws.asmx (by the way these are beta so you will not fine a whole lot of documentation besides the WSDL.)
I chose to only implement 2 of the methods for my sample proxy. I will be implementing the HelloWorld and the GetNewestFamilyThumbnails methods. The HelloWorld method I implemented only for testing purposes as I was building the application.
OK, let’s get started. First we need to add a web reference in our web application which points to the PhotoPoints web service. You do that by right clicking on the web application project and choosing the Add Web Reference… option. Enter the URL provided above on the address line and click Go. Once the web service is resolved, click Add Reference. I changed the Web reference name to PhotoPoints so if you are building along you might want to do the same so the screen shots make sense.
Next we want to do is add a web service to our web application. This is done the same way it was done before. I called mine PPProxy.asmx. The two methods I implemented are pictured below.
As you can see I return the same data types that I receive back from PhotoPoints; by doing that, I have eliminated the need to reformat the data when I receive the results from PhotoPoints. You will also notice the methods take in the same input parameters as PhotoPoints.
Now comes the “tricky” part. Silverlight doesn’t let us call cross-domain web services, but it does let us create a web reference to the cross-domain web service. Why is this important? If you look at the local web service above, you will notice that I’m returning PhotoPoints.Thumbs in the GetNewestFamilyThumbnails method. But the “Thumbs” class is not defined anywhere. So, by creating the reference in the Silverlight application to the original web service we will have all the classes and methods from that web service defined (reference.cs) and we will be able to use them in our application. To add the reference, right click on your Silverlight project and add a web reference. But, unlike in part 2 where we pointed to a local web service, this time we’re going to be pointing to http://www.photopoints.com/ws/ppws.asmx. I gave the web reference the name of photopoints (lower case) to make it different than the web reference in the web application. This is not a requirement though.
Now, let’s call our web service. And here we continue with the “tricky” part. As you can see from the code below, I’m instantiating a copy of the web service which points to PhotoPoints, but before I call any methods, I change its Url to point to my local web service. Doing this is what allows me to create the proxy on my web application and not have to redefine all the classes the original web service has implemented.
Below is the actual use of the data.
The first thing I do is make a call to the GetNewestFamilyThumbnails web method. I place the returned value in a module level private variable. I do that so I can have access to that data in other parts of the application. Once I make sure I have no errors returned I proceed to build a grid with the up to 9 thumbnails that are returned to me. Below is the rest of the GetData method which should be pretty self explanatory.
If you notice when I’m building the grid I wire an event (MouseLeftButtonUp) for each thumbnail I display on the page. I want to process that even so I can display the full size photo. See the code for that event below.
In the code you can see that I’m going through all the records I have in my Thumbs module level variable. Once I find the record that I want by comparing the thumbnail which fired the event URL with the one in the record, I retrieve the PhotoURL from the record and create an image which I add to the canvas and display it.
There are two more events that I handle. The first is when the person clicks the Close button to close the full image to go back to the thumbnails. The code for that event is displayed below.
The final even is the one that handles when the person clicks on the Refresh button on the top of the page. Code below.
So what happens when we run our application?
That’s the end of my demonstration. Of course, there is a lot more that can be done to the interface to make it better. As you can see at the time I wrote the blog there were over 271K photos on the website. I only display the top most recent 9 photos. We could add a paging mechanism to the thumbnail canvas. We could also create a slide show to display the full size images. And we could… You get my point of course. However, the very first thing I would add is a “wait cursor” from when I’m calling the web service. Hey, maybe that will be my next blog (calling web services asynch)?
You can see the Silverlight application in action at http://www.photopoints.com/main/Silverlight_Alpha/