SingingEels : Development Community & Resource

Login

Articles

  • ADO.NET (2)
  • ASP.NET (31)
  • LINQ (4)
  • Security (2)
  • Silverlight (2)
  • SQL (7)
  • Standards (5)
  • WCF (1)

Syndication

  • Articles RSS
  • Blogs RSS

Contribute

  • Our Authors List
  • Member Sign-Up
  • Suggestions Box

Images as a Service with ADO.NET Data Services

(May 17 2008 - 08:00:06 PM by Timothy Khouri) - [print article]

For those of you who have already put your feet into the waters of .NET 3.5 SP1, you have probably seen some amazing things with ADO.NET Data Services coupled to the Entity Framework. But that coupling may lead to blindness. Allow me to explain.

First of all, I want to clearly state up front that I love the Entity Framework and I love how easily ADO.NET Data Services snaps into it to provide a RESTful representation of your Entity Data Model (EDM). But there is a lot more to Data Services than is shown by this usage.

For instance, many people may not realize that you don't need EF behind your data service. What's more, is that you don't need a SQL database behind your data service. ADO.NET Data Services can be fully customized to expose any queryable "data" that you come up with in a REST-styled, web accessible data store.

Our Scenario - Serving Images

To demonstrate customization with ADO.NET Data Services, our example "data" will simply be a folder with some pictures in it. Our "data model" is nothing more than an image name, size, a thumbnail and the image data itself.

Data Services will give us out-of-the-box 'queryable' functionality such as paging and sorting. It also provides a delivery medium (HTTP) as well as multiple ways to receive the serialized data (Atom, JSON). Let's take a look at our data service and how to consume it in a few creative ways.

As a quick side note, this article will not get into how to do sorting or paging. Rather, it is intended to broaden the understanding of data as a RESTful service using ADO.NET Data Services.

Custom Data Service and IQueryable Properties

Creating an ADO.NET Data Service is easy to do, and the initial setup takes only a few moments. I simply right-click on my project, and go to 'Add New Item', select ADO.NET Data Service and press 'OK'. This is no different than adding a web service to your project. Here is what we have when we add our new data service:

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;

namespace MyNameSpace
{
   public class WebDataService1 : DataService</* your class here */>
   {
       public static void InitializeService(IDataServiceConfiguration config)
       {
           // TODO: set rules to indicate which entity sets

           // and service operations are visible, updatable, etc.

       }
   }
}

Other than removing some of the comments (for display reasons), I intentionally haven't touched the generated code to show you how simple it is. In fact, most of the content above are comments that describe what to do. So, I'll configure my data service now to use a custom C# class that I built called "ImagesStore". We'll take a look at that class in a moment, but for now it's good that you know that it has a single property on there called "Images" which is of type "IQueryable". So here's my configured data service code:

using System.Data.Services;

namespace MyNameSpace
{
   public class WebDataService1 : DataService<ImagesStore>
   {
       public static void InitializeService(IDataServiceConfiguration config)
       {
           config.SetEntitySetAccessRule("Images", EntitySetRights.AllRead);
       }
   }
}

That's it! ADO.NET Data Services now knows exactly what to do. Now my custom C# provider of data is exposed via a RESTful URL and can be queried and transmitted across the network (or Internet). Now that our data service is configured, let's take a look at the "ImagesStore" class to see what kind of data is being provided.

Data Services will reflect your class and look for any IQueryable properties, so here's my simple "ImagesStore" code:

// First I need to make a class that will hold the image data.
// Also, ADO.NET Data Services needs to know which property is

// the main identifier for each individual image. I'll use the

// Name property for that.

[DataServiceKey("Name")]
public class Image
{
   public string Name { get; set; }

   public byte[] ImageData { get; set; }

   public int Height { get; set; }

   public byte[] ThumbnailData { get; set; }

   public int Width { get; set; }

   // There are some helper methods here that I'm leaving

   // out, but you can download the source later.

}

// Here is the ImagesStore class with the single property

// called Images. There's not a lot going on here.

public class ImagesStore
{
   private static List<Image> images;

   public IQueryable<Image> Images
   {
       get
       {
           if (ImagesStore.images == null)
           {
               ImagesStore.images = new List<Image>();

               // Loop through the files in the Images folder...

               foreach (string imagePath in Directory.GetFiles(
                   HttpContext.Current.Server.MapPath("~/Images")))
               {
                   // Add the image to the list...

                   ImagesStore.images.Add(new Image
                   {
                       Name = Image.GetImageName(imagePath),
                       ImageData = Image.GetImageData(imagePath),
                       ThumbnailData = Image.GetThumbnailData(imagePath),
                       Height = Image.GetImageHeight(imagePath),
                       Width = Image.GetImageWidth(imagePath)
                   });
               }
           }

           // Return the list as a queryable source.

           return ImagesStore.images.AsQueryable();
       }
   }
}

The above code doesn't show my methods for pulling out the data from each image, but that code isn't important to show in the article. If you want to see more detail on how this is done, you can download the entire source project, including a windows forms client that consumes the data too.

The Results

When you look at the above service directly (by browsing to the service URL), you will see the Atom serialized representation of our images. Below, I'll show two separate client representations of that data: one a web site, and one a Windows Forms application. Here's what it looks like:

Atom Pub Serialized Data for Images as a Data Service Web Client for Images as a Data Service Windows Forms Client for Images as a Data Service

Conclusion and Known Issues with ADO.NET Data Services

The above example is supposed to help you look at data in a different light, as well as to realize that we can achieve a lot of quick and flexible power by exposing your data in a RESTful manner. There are many more benefits to this approach that will be understood more as time goes on, but there are a few issues that are worth noting:

  1. Because our "Image" object contains a large amount of binary data (the ImageData and ThumbnailData), the payload of hitting this resource is huge. This is especially concerning when not all of the data is required for the client (such as with our web client that only needs to know the image name).
  2. To deserialize to a client class, all of the properties that are being sent over the wire need to be on your class - otherwise you will receive a runtime error saying 'could not find a settable property named "Blah" on the client class'. This "semi-tight coupling" is problematic, especially if you wanted to add-on to your server code without breaking your clients.

There are other issues as well that are worth their own design conversations. But all in all, this is a great (and still very young) product that will really change the way we do data!

As was promised, here is a source project (compiled with the .NET 3.5 SP1 Beta - so if you are downloading this in the future, it might not work!): SingingEels_Images_As_A_DataService.zip

  • Aug 04 2008 - 11:42:07 PM martintrev

    Hi Timothy

    I loved your article, it was the only one I could find that made sense.

    I was wondering if you may have more information on the subject as I am trying to get an

    example running that allows filtering on the custom objects.

    At the moment nothing seems to effect what comes back, I always get the full list and can not filter at the uri.

    Any help would be apprieciated.

    Thanks Martin

    mtrevena@reeds.net.au

You must be logged in to add comments. If you have not already done so, you can create an account here. If you already are a member, you first need to login before you can comment.

Developer / Architect / Author

People to Follow

Experts in the categories related to this article.

  • Jonathan Carter
  • Elisa Flasko
  • Astoria Team

Related Blogs

These are the most recent blog posts related to this article.

  • How to Handle "Side Content" in ASP.NET MVC
  • LINQ to SQL - Am I Hitting The Database?
  • ASP.NET MVC - Issue with CSS Class Name on ActionLinks
  • The Most Amazing Interview I've Seen - Pete Lacey on REST
  • Site Updates, Bug Fixes and Syndication in .NET 3.5

Related Ads

SingingEels.com as of Aug 20 2008 - 08:58:50 PM - (0.203125)