Sunday, December 28, 2008

Consuming RESTful Web Services in Silverlight

Overview

This post is an extension of Rob Bagby's series on RESTful services. His 11th post details setting up a RESTful WCF service that can be consumed in Silverlight.

The key points are:
  • Creating a new Service Host Factory and Interceptor to support HTTP Verb tunneling, since Silverlight supports only GET and POST verbs.
  • Issuing calls from a client application to the RESTful service (including Silverlight and Fiddler)
This provides a great starting point for creating RESTful services and consuming them with Silverlight, so I decided to create a RESTful service layer around Zleek that utilizes LINQ to Entities.

Here are my take-aways from the experience:
  • The WCF Rest Starter Kit makes generating RESTful services extremely easy!
  • The ADO.NET generated entity classes are declared as partial so that you can easily extend them with your business logic.
  • You should create a separate Data Contract version of your entities in order to facilitate serialization
I updated my Agnition.Silverlight.Utils library (see my Previous Post on Silverlight Extensions) with some utility classes for dealing with RESTful services, including request creation and serialization.

Step-By-Step

  1. Download the WCF Rest Starter Kit
  2. Create a blank solution and add the Microsoft.ServiceModel.Web project from the starter kit as well as the Agnition.Silverlight.Utils project into it.
  3. Create a class library for your ADO.NET Entities
  4. Create an Entity Data Model from your database
    Creating a Data Model
  5. Create partial classes for each of your entities that you wish to write business logic or create data contracts for. Ideally this will be in a separate class library project.
  6. Create a class library for your data contracts.
  7. Create a Silverlight class library for data contracts. You will add all data contracts here as existing links to your other data contracts library to facilitate code sharing between your .NET 3.5 and Silverlight 2.0 libraries.
    Add Existing Item
    Add as Link
  8. Optionally create Silverlight business entity classes (possibly in another library) for your Silverlight application.
  9. Create a Silverlight application that you will use as your client. Ideally you should create a separate ASP.NET web application linked to the Silverlight application for ease-of-testing.
At this point, your solution structure should look similar to the following:
Sample Solution
Now we can start fleshing out the service and client. Let's start out by creating the service. Follow Rob's Post to walk-through creating your Service Host Factory and Interceptor. After that is complete, get started making the sevice more accessible to Silverlight.
  1. Remember those data contract libraries? Now it's time to flesh them out. For each entity, create a class with public properties for each piece of data you wish to expose. You can include relational properties this way as well. Here is an example:
    Example Data Contract
  2. Provide a way to project your entity class into your data contract. The easiest way (syntactically) to do this is to create an operator that will allow you to project the entity class into your data contract type while using casting syntax. The following screenshot illustrates both creating the operator and using the cast syntax to perform conversions:
    Projecting Into a Data Contract
  3. Create a web service method using OperationContract and WebInvoke (or WebGet) attributes. Remember that to be truly RESTful, retrieval operations should use GET, inserts/updates should use PUT, deletes should use DELETE and appends should use POST. Response codes should be used effectively as well. Here is a GET example:
    Example Web Method
At this point you can either test the service using Fiddler (see Rob's post), or go ahead and create the client application.
  1. Create a way to get the service URL into the Silverlight application. I like to use startup parameters. Here is how they are declared:
    Init Params
    They can only be extracted in the Application.Startup event, so I like to create a Configuration class that gives strongly-typed access to my parameters later.
    Reading Init Params
    Sample Configuration Class
  2. Now we are ready to call the service and deserialize the result:
    Call Service from Silverlight
That's it! Easier that you thought it would be, right? Please post any comments/questions you have about this. Here is the updated Agnition.Silverlight.Utils library.

Sunday, December 21, 2008

Silverlight Extenders

Source updated 12/24 with cross-browser support
Source updated 12/30 with RotateScaleExtender repaint fix
Work on the final version of Zleek is progressing nicely. The new UI is coming along, as well as the backend. The new features, including integration with other photo services and video support, are just about complete as well.

Over the coming months before our release, I will be posting code snippets and libraries that I put together for Zleek that may be helpful for other Silverlight developers.

This first post is a combination of a few extenders that I put together:
  • DragExtender: Adds mouse drag functionality to any FrameworkElement
  • RotateScaleXtender: Adds mouse rotate/scale functionality to any FrameworkElement
  • KeyExtender: Adds extra keyboard support, including handling of DOM events and extra keys
  • FillContainerExtender: Automatically resizes the Silverlight application to fill its container.

Here is the running example.

The source code in the test harness is pretty simple. You declare an instance of the extender and give it a reference to the FrameworkElement you want to add functionality to, and the extender does the rest. There are extensibility points inside of the extenders that should make them useful for any application.

Here is the source code, and here's a snippet from the test harness showing example usage:

   1:  using System;
   2:  using System.Windows.Controls;
   3:  using Agnition.Silverlight.Input;
   4:  using Agnition.Silverlight.Controls;
   5:   
   6:  namespace ExtenderTestHarness
   7:  {
   8:    public partial class Page : UserControl
   9:    {
  10:      public Page() {
  11:        InitializeComponent();
  12:   
  13:        // Initialize extenders
  14:   
  15:        _fillContainerExtender = new FillContainerExtender(this.LayoutRoot);
  16:   
  17:        _keyExtender = new KeyExtender(this, true, true, true);
  18:        _keyExtender.KeyDown += new EventHandler<KeyCodeEventArgs>(KeyExtender_KeyDown);
  19:        _keyExtender.KeyUp += new EventHandler<KeyCodeEventArgs>(KeyExtender_KeyUp);
  20:   
  21:        _dragExtender = new DragExtender(this.DragMe);
  22:        _dragExtender.StateChangeStart += new EventHandler<StateChangingEventArgs>(DragExtender_StateChangeStart);
  23:   
  24:        _rotateScaleExtender = new RotateScaleExtender(this.DragMe, 0.75, 6);
  25:        _rotateScaleExtender.StateChangeStart += new EventHandler<StateChangingEventArgs>(RotateScaleExtender_StateChangeStart);
  26:      }
  27:   
  28:      private void FullScreenButton_Click(object sender, System.Windows.RoutedEventArgs e) {
  29:        // Toggle full screen
  30:        _fillContainerExtender.IsFullScreen = !_fillContainerExtender.IsFullScreen;
  31:   
  32:        // Toggle display of warning
  33:        FullScreenWarning.Visibility =
  34:          FullScreenWarning.Visibility == System.Windows.Visibility.Collapsed ?
  35:          System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
  36:      }
  37:   
  38:      private void KeyExtender_KeyDown(object sender, KeyCodeEventArgs e) {
  39:        // Demonstrates KeyCode event arguments Key and TextValue
  40:   
  41:        // Show which key was pressed
  42:        if (e.Key == KeyCode.Shift) {
  43:          MouseMode.Text = "Mouse Mode: Rotate/Scale";
  44:        }
  45:        else {
  46:          // Don't show message on shift, to prevent spamming while holding
  47:          KeysPressed.Text += e.Key.ToString() + " ";
  48:        }
  49:   
  50:        // Render the text
  51:        if (e.TextValue != null) {
  52:          KeyText.Text += e.TextValue;
  53:        }
  54:        else if ((e.Key == KeyCode.Backspace) && (KeyText.Text.Length > 0)) {
  55:          // Check for backspace
  56:          KeyText.Text = KeyText.Text.Substring(0, KeyText.Text.Length - 1);
  57:        }
  58:      }
  59:   
  60:      private void KeyExtender_KeyUp(object sender, KeyCodeEventArgs e) {
  61:        // Demonstrates KeyCode event arguments Key and TextValue
  62:   
  63:        // Show which key was pressed
  64:        if (e.Key == KeyCode.Shift) {
  65:          MouseMode.Text = "Mouse Mode: Drag";
  66:        }
  67:      }
  68:   
  69:      private void DragExtender_StateChangeStart(object sender, StateChangingEventArgs e) {
  70:        // Demonstrates how to cancel an event in order to combine two MouseMovementExtenders
  71:   
  72:        // If not holding shift, allow dragging
  73:        e.CancelEvent = _keyExtender.IsShiftDown;
  74:      }
  75:   
  76:      private void RotateScaleExtender_StateChangeStart(object sender, StateChangingEventArgs e) {
  77:        // Demonstrates how to cancel an event in order to combine two MouseMovementExtenders
  78:   
  79:        // If holding shift, allow rotate/scale
  80:        e.CancelEvent = !_keyExtender.IsShiftDown;
  81:      }
  82:   
  83:      private readonly FillContainerExtender _fillContainerExtender;
  84:      private readonly KeyExtender _keyExtender;
  85:      private readonly DragExtender _dragExtender;
  86:      private readonly RotateScaleExtender _rotateScaleExtender;
  87:   
  88:    }
  89:  }

Sunday, July 13, 2008

New Job Opportunity

I recently received a package in the mail containing the following letter:
Mr. Stephen A. Commisso: We at Thompson Checkwriter Co., Inc. are in the process of upgrading our computer system. We have been looking into many different options, and think we have found the most useful, top of the line system. We elclosed[sic] a diskette with the program we plan on upgrading to, and a booklet that outlines its use. We have never been in the computer business, and we do not know anything about how to use them. We are in need of training. We have heard your name around the industry, and we would be honored to have you come to our company and train our employees how to use this top of the line system. We will pay top dollar for your services. We will need you to set up the system, and train our employees on its use and how it can improve our company. Thank you very much for your consideration, and we will be earnestly awaiting your response.
Wow, sounds promising! Here are the contents of the package: I don't know, I think I should take it... I'll keep these on my desk at work from now on and see if anyone notices. I only wish I could use these disks. If only I had a copy in 9 1/2"... My brother has a great sense of humor.

Zleek

The Bragosphere is now Zleek! Same great product, new name. Zleek There have been a few minor changes as well, including a new header that shows the latest public Zleek Pages.

Saturday, June 21, 2008

Firefox 2/3 and The Bragosphere

I was able to fix most of the issues affecting Firefox users. All Brag Page functionality now works in Firefox, except Full Screen Mode intermittently. this is a documented bug in Silverlight 2 Beta 2, and will hopefully be fixed by the time the final version rolls out. That said, yesterday I couldn't use full screen in Firefox, and today I can. I'm not sure what triggers the failure, but if I find out, I'll post it here. The updates to The Bragosphere will be slower and slower now that the majority of the functionality is complete. Watch this blog for details of new enhancements!

Thursday, June 19, 2008

New Look and Feel

Swami has put together a great new UI for The Bragosphere. Check it out! Now on to the cross-browser fixes... Firefox/Safari users -- we haven't forgotten about you!

Monday, June 16, 2008

It's Here!

I can finally announce that The Bragosphere is live! One more feature I never mentioned before: full screen mode. That's right, you can view your page layout in full-screen to get a better look at all your photos and videos! Go. Check. It. Out. Now. The Bragosphere

Saturday, June 14, 2008

Customizing a Silverlight Install Experience

A while back when I first started the Bragosphere project, I came across this excellent post by Tim Heuer. I put this off until now, but I think I've put together a decent installation experience with the help of some browser and platform detection javascript Here are the results:
Standard Install Experience Standard Install Experience
*Nix Install Experience *Nix Install Experience
Unsupported Experience Unsupported Experience
I still have to skin the popup a bit, but the detection is working great!

Wednesday, June 11, 2008

The Bragosphere Is Coming!

Well, it's about time I posted some screenshots here to show exactly what I've been up to. I won't make any promises about a release date, but I can tell you that The Bragosphere will be here very soon. I just finished the integration with Silverlight 2 Beta 2, and have some minor tweaking to do on the site itself, but here is an early view of what it looks like: Bragosphere Screenshot 1 In the above picture you see a simple "Brag Page" that I've created with some standard Windows Vista Sample Pictures. The site allows users to upload pictures in bulk, complete with a progress bar with thumbnail images showing what file is currently being uploaded. Once uploaded, pictures can be arranged any way the page creator wants by resizing, positioning, and rotating the pictures. A few different page backgrounds can then be chosen, the default of which is designed to look like a photo album page. Once the design is complete, security settings can be configured. The page can be public, private, or assigned to groups created by the user. Bragosphere Screenshot 2 Once saved, the page is visible to other (allowed) users. These users can manipulate the page in any way they like to create their own layout, and can even print it off if they like. They cannot save the layout and at any time they can reset the layout back to its original state. The controls available to users include double clicking on an image to zoom in/out; right clicking on an image to zoom in/out, reset state, or download the image; right clicking on the page background to reset the entire page state, or download all the images in a zip file. Bragosphere Screenshot 3 Multiple "Brag Pages" can be combined to create a "Brag Book", which can then be flipped through with the mouse just like you were turning the pages of an actual photo album! If the mouse is hovered over the top-left corner of the page, and a previous page is available, the corner will turn gold. Clicking and dragging will turn the page. Similarly, the bottom-right corner of the page allows you to go to the next page. Bragosphere Screenshot 4 Did you think I was done going over all of the features? Well, not quite. As you can see in the above screenshot, there is also full-motion-video support! Keep watching this space for more updates, and get ready to join The Bragosphere!

Friday, May 30, 2008

Silverlight Project Updates

Wow, it's already been a month since my last post... and it's been busy one. I've been working non-stop in my spare time on a Silverlight 2.0 project. I should be going live with it in the next week or two, so watch this space! I'm pretty excited about it. If you've read my earlier posts you can probably guess what it's going to be about. Anyway, check out this post on Tim Heuer's blog. It would be pretty cool if this is where the web is headed: http://timheuer.com/blog/archive/2008/05/29/new-deep-zoom-samples.aspx

Tuesday, April 29, 2008

Linkedin Networking

I'm really enjoying Linkedin. I've been able to reconnect with some old classmates at ASU and it will help me stay in touch with my colleagues from previous positions I've held. If you haven't seen it yet (which you probably have -- I'm just always the last to find out about new things on the web), check it out -- it's basically a professional networking application.

Monday, April 28, 2008

Connecting Families with Silverlight

One of the biggest hassles my family has concerns pictures. We take pictures on our digital camera, stick them on our PC, and let them sit there for months on end. Occasionally we may print a few or e-mail them to family. True, we could use a site like Flickr to provide an online listing of your photos that family can share. This still leaves a lot to be desired. When we're with family, we can show them printed pictures. They can handle the pictures, rotate them, look closely at fine details. If wehave the time we might create a photo album to show them, containing page layouts, possibly grouped around a specific theme, with the photos positioned however we like. Why can't we do this on the web? I would like to be able to take pictures on my camera, stick them on my PC, upload them to a web site, and create a virtual photo album just how I want. I also want my family to be able to virtually "handle" these pictures by rotating, zooming, repositioning however they want. Stay tuned as you'll be hearing more about this in the near future...

Instrument Preferences

Over the past few years I've mostly been playing bass guitar, with keyboard thrown in occasionally. Daniel Brymer, on his last Sunday at Living Streams, moved me over to the piano. Since then, I have been scheduled for piano maybe 1/3 of the time. I just received the May schedule and it looks like I'm back on the piano full time. I'm really looking forward to it as I've felt like I've let my piano skills degrade over the last few years while I played bass more, and hopefully I can improve my skills while not hitting too many bad notes in the process.

Sunday, April 27, 2008

Mat Weddle

Today was my second time on the Living Streams worship team with Mat Weddle (who you may recognize from YouTube) leading. He's a really great guy and I hope he gets scheduled for more Sundays. It seemed like he felt a lot more comfortable leading our church's worship service this past Sunday than he has in the past, and as a result the worship set was amazing. He has a sincere heart of worship, and a great ability to lead others into a genuine worship experience, and that was on display this past Sunday. Unfortunately, the next time he is playing is on Mothers' Day, which I requested off (finally - I had played it 3 years in a row, which included my wife's first Mothers' Day - big oops!), so I'm not sure when we'll be playing together next, but I am looking forward to it.

Friday, April 25, 2008

Silverlight Development

I am working on a Silverlight 2.0 project right now and got pointed to Tim Heuer's blog on one of my queries and found out that Tim is now working on the Silverlight team along with Jesse Liberty. Tim is a great guy who lives in the Phoenix area and helped me when I was a consultant with Sogeti, as our local Microsoft developer evangelist. If you're working with Silverlight and have any questions, check out his blog: ~ Method Of Failed ~. Aside from that, I'm pleasantly surprised at how easy it is to learn XAML and the Silverlight model. I previously had no WPF experience (my .NET 3.0 experience was limited to WCF), so I had no prior knowledge of XAML, but was able to pick it up pretty quickly. Granted, I made (and keep making) plenty of newbie mistakes, but overall the learning curve has been pretty gentle. Of course, coming from the perspective of working with Microsoft CAB and the Smart Client Software Factory, just about anything else will have a gently learning curve... but that's a topic for another post altogether. By the way, if you're working with that stuff, Ward Bell rocks.

Wednesday, April 23, 2008

Rebooting the Web

If you're not a geek like myself, you probably haven't heard about Silverlight, Microsoft's new web technology. As both a web developer and a client developer using the .NET platform, I see the strengths and weaknesses on both sides of the thick/thin client coin. Silverlight, especially Silverlight 2.0, blurs these lines. It allows developers to write what are essentially client applications on the web. A few years ago, AJAX (using a technology created by Microsoft, and made popular by sites such as Google Maps), greatly enhanced web applications by doing away with the page refreshes between mouse clicks. This allowed developers to create a new generation of web applications that behaved more like client applications. This revolution was called Web 2.0. It was a great improvement, however web applications were still handicapped by the visual confines of HTML and the browser. Of course, a compelling user experience could still be created with Flash, but that meant that the Flash content would not be indexed by a search engine. Silverlight is the next evolution of the web. As Jeff Prosise put it last year, Microsoft "rebooted the web" by giving developers a declarative programming model using XML (XAML), that allows for the creation of Flash-like user interfaces that can also be indexed be search engines (not to mention it has killer performance). In the past year since the announcement of Silverlight (formerly WPF/E), there have been some great ideas developed around it. Most early adopters used Silverlight simply for streaming HD-video, but that is just the tip of the iceberg. Check out the Silverlight Showcase to see what is possible with Silverlight 1.0. Silverlight 2.0, currently in Beta 1, expands on the Silverlight model by including a version of the .NET platform to write code against. This opens the door for .NET developers who have never touched Flash to write applications on the web that provide experiences that users never thought possible on the web. It will be interesting to see how quickly this technology (or alternatively, Flex, but I'm rooting for Silverlight) is adopted and how the web will be transformed. It is an exciting time to be a web developer.

Monday, April 21, 2008

Introduction

Well, I finally bit the bullet (thanks Kelly!) and decided to create a blog. It will primarily focus on Microsoft technologies and my experience with them, and hopefully provide some insight into the world of software development to the uninitiated. I may also write about music, life, and other bits and pieces. Occasionally there will be code walkthroughs, so to you non-geek types, you have been warned!