Silverlight

Recreating the MobileMe Gallery in Silverlight – Part 1 *Updated*

Originally, in Part 1 of my soon-to-be multi-part series on recreating the MobileMe Gallery in Silverlight I used a separate WCF project (under .NET 3.5) to create my Gallery Service to serve as a proxy between my Silverlight client and the Apple MobileMe service that provides MobileMe Gallery data in JSON format.

Since then, I have upgraded the project to Silverlight 4 and .NET 4 and have decided to move the service code into the Web project that hosts the Silverlight application. More importantly, I have changed the service to use the new config-free RESTful model available in WCF 4.

You can download the latest source from CodePlex here: http://silverlightmobileme.codeplex.com/SourceControl/list/changesets

Now, our web project looks like this:

Now, our service code is as simple as one file – GalleryService.cs which is as follows:
(Notice no .svc file needed anymore thanks to the WebServiceHostFactory in WCF 4)

using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

namespace Gallery.Web.Services
{
	[ServiceContract(Namespace = "urn:silverlightmobileme.codeplex.com")]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
	public class GalleryService
	{
		string galleryUrlFormat = ConfigurationManager.AppSettings["GalleryUrlFormat"];
		string albumUrlFormat = ConfigurationManager.AppSettings["AlbumUrlFormat"];

		[WebGet(UriTemplate = "/{username}",
				ResponseFormat = WebMessageFormat.Json,
				BodyStyle = WebMessageBodyStyle.Bare)]
		[OperationContract]
		public Stream GetGallery(string username)
		{
			// TODO: add exception-handling using WebFaultExceptions and HttpStatusCode enumeration
			var webClient = new WebClient();
			string photocastUrl = string.Format(galleryUrlFormat, username);
			return webClient.OpenRead(photocastUrl);
		}

		[WebGet(UriTemplate = "/{username}/{id}",
				ResponseFormat = WebMessageFormat.Json,
				BodyStyle = WebMessageBodyStyle.Bare)]
		[OperationContract]
		public Stream GetAlbum(string username, string id)
		{
			var webClient = new WebClient();
			string albumUrl = string.Format(albumUrlFormat, username, id);
			return webClient.OpenRead(albumUrl);
		}

	}
}

The magic of WCF 4 config-free RESTful services is handled in Global.asax.cs

using System.Web;
using System.ServiceModel.Activation;
using System.Web.Routing;
using Gallery.Web.Services;

namespace Gallery.Web
{
	public class Global : HttpApplication
	{
		public static void RegisterRoutes(RouteCollection routes)
		{
			//routes.Add("GalleryService", new Route(
			//    "GalleryService",
			//    new CustomRouteHandler("~/Services/GalleryService.svc")
			//));
			routes.Add("Default", new Route(
				"{username}",
				new CustomRouteHandler("~/Default.aspx")
			));
			RouteTable.Routes.Add(new ServiceRoute("GalleryService", new WebServiceHostFactory(), typeof(GalleryService)));
			RouteTable.Routes.Add(new ServiceRoute("ConfigService", new WebServiceHostFactory(), typeof(ConfigService)));
		}

		protected void Application_Start()
		{
			RegisterRoutes(RouteTable.Routes);
		}
	}
}

Here, after registering our main route for the gallery, we simply add two more routes (of type ServiceRoute), passing it the path we want to map to our services, then the ServiceHostFactory (which handles the config-free RESTful WCF), followed by the type of the service.

That’s it!

Now our service has nice RESTful service endpoints and there is no special WCF configuration needed and it just works.

Try out the new config-free RESTful service here: http://gallery.restazured.com/GalleryService/emily_parker

With WCF 4 config-free RESTful services, we also get handy helper pages for our service consumers to help them understand how to call our services and what type of response to expect.

Try it out here:

http://gallery.restazured.com/GalleryService/help
http://gallery.restazured.com/ConfigService/help

As you’ll see, this displays what operations are available and even provides sample responses. Now that’s RESTful!

Stay tuned for Part 2 where we’ll cover the details of the Silverlight project (now Silverlight 4) where we’ll be using MEF, MVVM and our config-free RESTful WCF services.

Silverlight MobileMe Gallery now on CodePlex!

I have published the initial source for my project “Recreating the MobileMe Gallery in Silverlight 3” on CodePlex.

You can now access the Alpha release of the code here: http://silverlightmobileme.codeplex.com/

I will be updating I have updated the working example (http://gallery.restazured.com/emily_parker) as well to reflect the latest version on CodePlex.

Please leave your comments and let me know if you have any questions…or if you would like to be a contributor to the project.

Enjoy!

Recreating the MobileMe Gallery in Silverlight 3 – Part 1

In my introductory post I detailed the features needed to successfully recreate the MobileMe Gallery in Silverlight 3. While a bit late, this is Part 1 of a multi-part series where I will detail out step-by-step the process of Recreating the MobileMe Gallery in Silverlight 3.

The Tools

I will assume you already know what tools are required to do Silverlight development. If not, go here: http://timheuer.com/blog/articles/silverlight-get-started-part-1-hello-world.aspx

For this post, you will also need a tool such as Fiddler or Web Development Helper in order to do some HTTP tracing.

Getting Started

For this post we are going to focus on the initial plumbing required to retrieve the data from the MobileMe Gallery. The first thing we’ll need is the underlying data (album definitions, etc.) stored on the MobileMe site so that we can populate our Silverlight Gallery. To do so, we’ll need to see what the Apple MobileMe Gallery does under the covers.

So, if you head over to the MobileMe Sample Gallery you should see the following:

Click Here for a Larger View

Click Here for a Larger View

In order to find out if the underlying album data is accessible, I’m going to use the Web Development Helper IE Add-In to do some HTTP Tracing on the Apple MobileMe Gallery. After firing up Web Development Helper and turning on HTTP logging (HTTP > Enable HTTP Logging), I can then refresh the browser and should see a long list of HTTP requests in the console like so:

Web Dev Helper

Click Here for a Larger View

If you scroll up in the list, you should find the entry highlighted above. This is the main request we are concerned with. Double-clicking on this request and then selecting the “Reponse Content” tab at the bottom provides more details.

Http Log Viewer

Click Here for a Larger View

There you have it! A good ‘ol fashion HTTP GET request returning JSON. A quick glance over this data shows you that this JSON response contains the gallery details we’re after. So far, so good.

Getting the Data

Now we know where to get the data, but how do we get it? You may say just use the WebClient class in Silverlight to do an HTTP GET request. However, Silverlight requires client access policy files for cross-domain HTTP requests in order to provide a security mechanism to service authors to specify who can and cannot access their services. There are some public web services that already have these files in place for Flash, but Silverlight requires its own flavor. Additionally, the Apple MobileMe Gallery doesn’t have one. Therefore, we need our own service (WCF service that-is) that will serve as a proxy between the Apple MobileMe Gallery service and our Silverlight MobileMe Gallery client. In short, we’ll call our WCF service (that we’ll author) and our service will call the Apple MobileMe Gallery service. This is a common workaround as the Silverlight client performs the check for the client access policy file while WCF doesn’t do any checks because it’s a server technology.

Writing our Service

We’ll start off by creating an empty Visual Studio Solution called Gallery. Then, we’ll add a new “WCF Service Application” project to the solution – giving it the name Gallery.Service. Here is the structure of the service project after being built out.

Service Project Structure

IGallery.cs is our service contract that will define the signatures for the methods we’ll need to call to retrieve gallery and album details. It looks like this:

IGallery

IPolicyProvider.cs is our policy provider contract that will define the signature for the method that will return the Silverlight client access policy file. It looks like this:

IPolicyProvider

As you’ll notice, both of these interfaces are using the WebGet attribute to map specific UriTemplates to these service methods. For instance, in IPolicyProvider, we are saying if an HTTP GET request comes in to our root service folder followed by “/clientaccesspolicy.xml,” then that means run this method. We do this because anytime a Silverlight client makes any cross-domain request, it first makes a request to “clientaccesspolicy.xml” to see if it has rights to access the service.

Finally, our implementation of Gallery.svc.cs looks like this:

Gallery.svc

Click Here for a Larger View

Here, you’ll notice that our GetGallery and GetAlbum methods are simply using WebClient to call the gallery service and album service using url formats defined in Web.config. These are:

WebConfigSettings

Click Here for a Larger View

You’ll notice that the first entry (PhotocastUrlFormat) is the same format as the HTTP request we observed using Web Development Helper. And we simply, leave a curly-brace placeholder for the MobileMe username which we’ll substitute at run-time.

Minus WCF configuration settings which are included in the source, we now have a working service which will forward calls to the Apple MobileMe service to retrieve gallery and album details. This service is currently available at http://igallery.restazured.com/GalleryService.svc

Feel free to wire up your WCF client of choice (Silverlight, WPF, etc.) add a service reference and try calling one of the methods passing your own MobileMe username or the sample “emily_parker”. You can even see the client policy provider in action here: http://igallery.restazured.com/clientaccesspolicy.xml

Wrapping Up

Now, we have a WCF service setup to forward our requests for MobileMe Gallery and Album details to the Apple MobileMe Service. In Part 2, we’ll start creating the Silverlight project to call our WCF service and start building the home page to look like: http://gallery.me.com/emily_parker

In the meantime, checkout the working example (using Silverlight 3) here: http://gallery.restazured.com/emily_parker

Silverlight Midpoint Rounding Solution

As a follow up to my previous Shakespearean-titled post on rounding, I decided to provide a quick follow up to provide a solution for midpoint rounding in Silverlight. Based on some traffic that I’ve been getting it looks like people are searching for a rounding solution in Silverlight since the Silverlight core framework lacks the traditional Math.Round() overloads we get with the full .NET framework that allow specifying the desired midpoint rounding behavior.

Remember, Silverlight contains a pared-down version of the .NET framework.

So, here is a simple solution to take what we learned in the previous post and develop our own MathExt helper class that provides static Round methods similar to the Math.Round() methods that allow us to specify the desired midpoint rounding behavior. Using this you can now control midpoint rounding behavior in Silverlight.

public enum MidpointRounding
{
	ToEven,
	AwayFromZero
}

public static class MathExt
{
	public static decimal Round(decimal d, MidpointRounding mode)
	{
		return MathExt.Round(d, 0, mode);
	}

	/// <summary>
	/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
	/// </summary>
	/// <param name="d">A Decimal number to be rounded.</param>
	/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
	/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
	public static decimal Round(decimal d, int decimals, MidpointRounding mode)
	{
		if (mode == MidpointRounding.ToEven)
		{
			return decimal.Round(d, decimals);
		}
		else
		{
			decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
			int sign = Math.Sign(d);
			return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
		}
	}
}

Or if you prefer an extension-method approach:

public enum MidpointRounding
{
	ToEven,
	AwayFromZero
}

public static class DecimalExtensions
{
	public static decimal Round(this decimal d, MidpointRounding mode)
	{
		return d.Round(0, mode);
	}

	/// <summary>
	/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
	/// </summary>
	/// <param name="d">A Decimal number to be rounded.</param>
	/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
	/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
	public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
	{
		if (mode == MidpointRounding.ToEven)
		{
			return decimal.Round(d, decimals);
		}
		else
		{
			decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
			int sign = Math.Sign(d);
			return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
		}
	}
}

Remember, the non-extension-method version could easily be used in any legacy .NET projects that still may be on 1.0 or 1.1 to give us the ability to control midpoint rounding behavior which didn’t arrive in the framework until .NET 2.0.

Once again, Happy Rounding!

public enum MidpointRounding
{
AwayFromZero,
ToEven
}
public static class MathExt
{
public static decimal Round(decimal d, MidpointRounding mode)
{
return MathExt.Round(d, 0, mode);
}
/// <summary>
/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
/// </summary>
/// <param name=”d”>A Decimal number to be rounded.</param>
/// <param name=”decimals”>The number of significant fractional digits (precision) in the return value.</param>
/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
public static decimal Round(decimal d, int decimals, MidpointRounding mode)
{
if (mode == MidpointRounding.ToEven)
{
return decimal.Round(d, decimals);
}
else
{
decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
int sign = Math.Sign(d);
return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
}
}
}

Recreating the MobileMe Gallery in Silverlight 3

Background:

Even though I am an avid fan of many Microsoft products (especially their developer tools), Apple has just done certain things “right” for the home user where it seems Microsoft has struggled or been late to the table. As you may have read on my About Me page, I use Macs at home. They have their own set of issues, but for most of the “home stuff” I need a computer for (photos, movies, music) they do the job and they do it well.

One of my favorite tools is iPhoto (Aperture too) and the one-click publishing to MobileMe Gallery – Apple’s web-based photo/movie gallery tool that creates good looking, easy-to-use, web-based galleries that I use to share photos and movies with friends and family. Take a look for yourself and visit the MobileMe sample gallery for the ficticious user “Emily Parker.”

Sample MobileMe Gallery

Problem:

So for the most part, the features here meet my needs with one exception – movies require the Apple QuickTime plug-in to view them. Well, you may say, ‘no big deal’ and you’re right…unless you’re one of my many family members who is still on Windows 2000 (or earlier) and can’t install the latest version of QuickTime because it requires Windows XP. So, needless to say, a fair amount of people are unable to view any of the movies that I publish to MobileMe Gallery. So, I end up having to also publish them to YouTube as well (which is a kind of a hassle). Not to mention that they don’t get the same focused user experience of my photos and movies in one nice and neat presentation and not a bunch of other junk detracting from the experience. I know, I know, my family members should upgrade, but the simple fact of the matter is that many of them are happy with their computers and they’re not going to upgrade just so they can view my measly ol’ MobileMe Gallery.

Solution:

So, now for the solution. I attended a Guerilla.NET event back in March (put on by DevelopMentor) and while at the class I got up to speed on Silverlight 2 as well what features were coming in Silverlight 3. Voila! Silverlight 3 was going to support additional media formats including MPEG-4, which is the format used by iTunes and MobileMe Gallery. So, you see where I’m going. My solution would be to use the features of Silverlight 3 to create a solution that would allow my family to view the MPEG-4 format movies stored on MobileMe Gallery using the Silverlight 3 plug-in (once it became available). I knew it would be sometime before it came out of beta and I knew it would take me awhile to develop, so I knew I had some time.

But remember, I didn’t want to sacrifice the clean, simple, focused UX of MobileMe Gallery by simply giving my family a silverlight media player as an alternate location to view movies. Plus, there are already Silverlight media players that would handle the job once Silverlight 3 was available. I wanted my family to have the full, beautiful MobileMe Gallery experience in all its glory. So, I decided I would recreate the MobileMe Gallery using Silverlight. I figured it would be a good learning experiment since I hadn’t played with Silverlight much before the class.

So, this is the introductory post of a multi-part series where I will detail out step-by-step the process of Recreating the MobileMe Gallery in Silverlight 3. I hope you’ll follow along as I go down to meticulous detail to ensure my Silverlight Gallery looks exactly like Apple’s MobileMe Gallery.

Key Features and Success Criteria:

1. Play MPEG-4 (.m4v) files using Silverlight without the need for QuickTime

2. Photo Album and Movie “Scrubbing” (if you view the sample above, you’ll see what I mean when you mouse over an album or movie)

3. Full featured photo album with all the features (and views) of the one built-in to MobileMe Gallery

4. Utilize the photos/movies already stored on MobileMe Gallery (no separate upload or storage required…we’ll do this by tapping into the existing APIs and RSS/JSON feeds that MobileMe uses itself by using a little Fiddler detective work)

5. 100% Silverlight implementation

The goal in one sentence is by the time we finish we should have an exact replica, feature-for-feature match of the MobileMe Gallery using Silverlight 3 (see below for a preview).

MobileMe Gallery (using Silverlight 3)

As for legal disclaimer, I should note that Apple, the Apple logo, MobileMe, the MobileMe logo, and MobileMe Gallery are registered trademarks of Apple.

Also, I am a multi-Mac owner, multi-iPhone owner, paying member of the iPhone developer program and MobileMe subscriber, so Apple don’t sweat this too much. I’m still a big fan, but needed a good project to develop my Silverlight skills and figured recreating the beautiful MobileMe Gallery would be an excellent challenge.

Here’s the breakdown:

  • Part 1: Getting Started – WCF and the initial plumbing required to retrieve the data from the MobileMe Gallery
  • Part 2: The Silverlight Project (Coming Soon) – creating the Silverlight project to call our WCF service and start building the home page

Please check back for updates as I’ll continue to update this post with the links to new segments as I complete them.