Saturday, 25 December 2010

Carving Rings

45614449[Abstract/ Sharing]  To close off 2010, I’m posting an article on how to carve a pair of linked rings from a single block of wood. It’s very simple so if you have a chance, why not have a go yourself.

 

 

This post is dedicated to the memory of Julian Guy Tulloch, who died peacefully on the 12th December 2010, aged 78.

Julian first introduced me to carving.

newrule

We start with a small block of wood, 5cm by 5cm by 10cm. The exact dimensions are not too important, you just want a block of wood that is rectangular in nature with a square end:

IMG_0715

I’m using Tilia or Basswood which is good for carving – not too dense and very little grain. You can find this type of wood at craft shops, often described as ‘Carving Blocks’.

Extruded Cross

The first step is to mark out an extruded cross using a pencil:

IMG_0716

I made the cross 1cm wide. The cross is drawn on the two square ends of the block of wood and joined up over the length of the block. Note, the extruded cross is the shaded area on the diagram.

Now, using a small Tenon Saw, you should remove the four corner pieces. These are the un-shaded areas in the diagram above. This should leave the extruded cross:

IMG_0711IMG_0712

Notice that I don’t cut right up to the line. I leave a little margin for error when using the saw. To finish off the extruded cross, I use a carving/milling tip on my Dremel hand tool:

IMG_0714IMG_0713

So far, so good. Now for a little vacuuming!

Overlapping Discs

Next we need to transform our extruded cross into two overlapping discs. The discs are inside the cross, you can see them on the diagram below:

IMG_0720

Because my cross was 5cm across the face, the discs are 5cm in diameter:

IMG_0719

The important bit is the overlap. One disc needs to overlap the other. There needs to be sufficient overlap to carve out the rings, one from each disc. I have decided to have each disc overlap half way through the other disc.

Again, I will use my Tenon Saw to cut away the excess wood. First step is to remove two end pieces – ‘A’ and ‘B’ on the diagram below:

IMG_0721

On the carving, the areas to remove are shown marked A and B:

IMG_0722IMG_0723IMG_0724

After cutting away the wood with the saw we have the following:

IMG_0725IMG_0727IMG_0728

Now we have to remove the rest of the excess wood. In the diagram below, this is marked ‘C’, ‘D’ and ‘E’:

IMG_0729

IMG_0730

‘C’ is a complete bit of the extruded cross and we remove this using the saw:

IMG_0731IMG_0733

Can  you see the two overlapping discs yet?

IMG_0732

Ok, now remove the little pieces ‘D’ and ‘E’. This is the same as ‘A’ and ‘B’. Look, two overlapped blocks:

IMG_0734IMG_0735

It is worth marking out the discs and removing the excess wood to reveal the discs. First, mark out the discs with a pencil. I’m draw these by hand:

IMG_0736IMG_0737

Then remove the excess wood. I’ve used my Dremel for this but carving chisels or even sanding will work. And now we have two interlinked discs:

IMG_0741

Again, let’s tidy up.

Finding the Rings

My discs are 1cm wide. Because of this, my rings are going to be roughly 1cm in diameter before any sanding.

At this point the rings are embedded in the edge of the discs. We need to define the rings by removing the centre of the discs. We are going to do this in two steps. The first step is to clear the majority of the centre of each disc. We will still be left with ring connected together. The second step is to finally free the rings.

For each disc we want to remove the shaded area ‘A’ from as shown in the diagram below:

IMG_0743

You must be very careful not to remove any of the ring or any of the second ring. The result should look like this:

 

IMG_0747

OUCH!!! I cut my hand – be careful.

Ok, tricky  bit coming up so time to tidy up and have a rest.

Tricky Bit – Free the Rings

This bit is a little tricky and can go badly wrong. If you remove too much wood, you may break the rings. The two rings are joined, but only by a small wall of wood. Take a close look at the rings and you can make this out.

The process for removing this wall and separating the rings is a little hard to describe but I will give it a go:

IMG_0756

In the diagram above I’m looking down on one of the rings. There are four points on the top surface that need to be chiselled – ‘A’, ‘B’, ‘C’ and ‘D’ Similarly, from the bottom side of this ring, there are four more points – ‘E’, ‘F’, ‘G’ and ‘H’.

Notice that these 8 points are the 8 corners of a cube. Not a normal cube with straight sides, rather one with concave sides:

IMG_0762

Try to see this in the rings before you start to carve. You want to chisel into these eight points as evenly as possible and when chiselling, you need to chisel diagonally towards the centre of the cube. Bit, by bit you have to remove the cube from the corners, outside to the centre. When the cube has been chiselled away, the rings will magically free:

IMG_0758

Remember, don’t rush it and it should work.

Another tidy up.

Last step – Sanding and Varnish

To complete the rings, you need to sand away excess wood to reveal the rings. You can sand away until you are happy with the results. Again, be careful as you don’t want to spoil the rings at this stage. Once you have sanded to reveal the rings, you need to varnish the rings.

The trick with varnishing is to apply a coat, then sand away the coat. Then repeat. The more times you repeat this, the harder the finish.

Here are my rings, not yet varnished but fully revealed:

IMG_0764IMG_0768IMG_0770

And after Varnishing

After more than 15 repeated varnish and sanding cycles, here is the finished article. Very hard finish with the wood grain showing through like Tiger Stone:

IMG_0791

I’m very pleased with the resultsSmile

Have fun and Happy New Year.

Friday, 24 September 2010

WCF Self Hosted Duplex Service for Chubby Client

barcodescanner[Concrete/Interesting] I received an email from a friend of mine. He was trying to build a Chubby Client, following some of the ideas I put down in my previous article. What was needed in this case was a Duplex Service that send data back from a thread outside of the main thread. My friend sent me his code and declared it couldn’t be done.

That sounded like a ‘dare’ to me, so I thought I’d have a go.

In this article I will take you through some of the major steps and discuss the overall architecture and solution. If you want the code, I've published this to Google Code so feel free to download and take a look: http://deviceservices.googlecode.com

The Goal

The main goal was to develop a device service that can be called from a Silverlight in or out of browser client. The device service would have initialization and action methods similar to those supported by an Windows OPOS device such as a scanner, printer, cash draw, customer display or MSR. For more details about Microsoft OPOS and POS device support, see Microsoft POS for .NET Overview 

The full implementation is a chubby client with a Silverlight browser client capable of running in or out of browser. This client would be launched from a console or service based service host. The host provides all application and devices services for the client through WCF Duplex Services. Within the host, the device services are responsible for abstracting and supporting the OPOS devices, application services provide APIs to application functions and databases:

apparchitecture

Duplex Services

The key problem we need to address is handling asynchronous events at the service. Why? Well we want to build a Silverlight client. We want this because we may want to run in a thin client configuration with the client hosted in a browser calling network or web services. For the application services, a normal one way web service or REST service would be fine. The client would simply call the service and the service would return data. But there are some application services where asynchronous events are a better way forward. Take notifications in workflow as an example. Here you don’t want to hold up the client and wait for the service to notify you of a state change. This state change could come at any time. Another example is large list data. You don’t want to call and have returned back all the data to the client and bound to some UI element. The data transfers could be huge and the client would be required to hold all this data.

Now considering the support of devices in our service, we again need to think about an asynchronous notification architecture as we request an action at the device such as ‘Scan when a barcode is available’ and a some time in the future, when a barcode is presented to the scanner, the device wants to tell us ‘here is a barcode I just scanned’. A further complication here is that the event notifications are typically not raised in the same thread as that used to handle the client request. 

In ASP.Net we would look towards AJAX to solve these problems. In the world of services, we need to implement Duplex or dual channel services. The diagram below illustrates this for a service supporting a POS scanner:opos

WCF Duplex Services allow us to define a client callback contract again the service contract. What this means is the client exchanges a service contract with the service; this allows the service to notify the client of service events.

Duplex Service Options

WCF provides a number of ways to implement duplex services against Silverlight 4 clients:

HTTP Polling Duplex Service

This is the one I’ll be looking at in more detail. It is suitable for Chubby Clients, however it doesn’t scale out client connections well and has trouble working across network boundaries. However, out of the box, this is the simplest duplex service to code and support in in a client.

Duplex Service using Sockets

You can also use private sockets to set up a duplex channel between Silverlight and the service. Very fast, scales well but only works on a limited range of ports (Silverlight sandbox restriction) and a lot of code needs to be hand forged both service and client side.

Duplex Service with Net.TCP Bindings

Ultimately, this is the best balance between non-functional like scalability, performance and network awareness. However, the code is more involved so I won’t be illustrating it here.

Proof of Concept

In the proof of concept, focus is given to the Device abstraction layer and support for events raised back to the client. These events would normally be raised outside of the main thread and the purpose of the proof of concept is to illustrate this can be done in a chubby Silverlight-WCF architecture. For this, I’m going to use a System.Threading.Timer to raise the client notifications.

To keep things simple, the implementation will also restrict itself to one client pre-service. Finally, no work will be done to provide application services or actual integration with Microsoft OPOS. I will leave that as an exercise for the reader.

DeviceService

Self Hosted Service

I’ll be honest, I like to see how things work, at least I do the first few times I do something.

Self Hosted WCF services let you get into the details as you have to write the service, not press a few buttons on a wizard.

Also, a self hosted service, all the bindings and endpoint behaviours are down to you. You have to code it rather than define it is a CONFIG file.

Lastly, we are building a console application so there is full control over the running, debugging and management of the application.

Of course, for a production system you may consider IIS hosted. This will provide the best performance and scalability and ease of deployment.

For chubby clients, self-hosted, either as console or service probably remains the choice solution as you need to package and deploy service and client together and for each service, there is likely to be only one client.

The Host

As ever, the host is simplicity itself:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Starting WCF Host for DuplexDeviceEvent...");
        string baseAddress = "http://localhost:8000";
        DeviceEventRunner runner = new DeviceEventRunner();

        using (ServiceHost host = new ServiceHost(typeof(DeviceEventService), new Uri(baseAddress)))
        {
            host.AddServiceEndpoint(typeof(IPolicyRetriever), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
            host.AddServiceEndpoint(typeof(IDeviceEventService), new PollingDuplexHttpBinding(), "DeviceEventService");

            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            host.Description.Behaviors.Add(smb);
            host.Open();

            Console.WriteLine("WCF Host Running...");
            Console.WriteLine("Press  to shutdown");
            Console.ReadLine();

            host.Close();
        }
    }
}

All that’s going on here is a service host is being initialized and run. Since we are calling this host from Silverlight we need to ensure there is a default Policy available. Beyond that, we are creating an endpoint for the service that follows the PollingDuplexHTTPBinding protocol.

ServiceMetadataBehaviour

As a side note, this little bit of code enables the service to publish itself. This is very useful as it will allow us to create a service reference in our client.

Device Runner

You will see a static object defined in the programs main method. This is the device runner that will simulate the device events. The code behind this class simply starts a System.Threading.Timer. In the timer’s callback, if a client is connected, the callback event for the service is executed:

private static void updateClient(Object stateinfo)
{
    try
    {
        if (theClient != null)
        {
            Console.WriteLine("Updating Client {0}", clientId);
            DeviceEventData eventData = new DeviceEventData();
            eventData.message = "Test Data";
            eventData.timestamp = DateTime.Now;
            theClient.SendDeviceEventData(eventData);
        }
    }
    catch (CommunicationException ex)
    {
        //client error so dispose of client
        Console.WriteLine("Client Error: {0}", ex.Message);
        Console.WriteLine("Closing connection to client {0}", clientId);
        theClient = null;
        clientId = String.Empty;
    }
}

public static void Register(IDeviceEventServiceClient client, string id)
{
    theClient = client;
    clientId = id;
    Console.WriteLine("Client {0} registered.", id);
}

The service runner is also responsible for accepting the client registration through the Connect interface.

Notice that exceptions can be raised during the callback processing. The main exception is a failure to reach the client during callback, typically because the client has gone. This is picked up as a CommunicationException. In this implementation the service runner simply removed its reference to the client.

Service Contracts and Implementation

When we define the service contract we also name the callback contract. This is defined in the interface for the service:

[ServiceContract(Namespace = "Silverlight", CallbackContract = typeof(IDeviceEventServiceClient))]
public interface IDeviceEventService
{
    [OperationContract(IsOneWay = true)]
    void Connect(string id);
}

[ServiceContract]
public interface IDeviceEventServiceClient
{
    [OperationContract(IsOneWay = true)]
    void SendDeviceEventData(DeviceEventData data);
}

Two things happen when the client connects. First, a callback interface is created against the callback channel. This callback interface is then passed to the service runner where is is remembered and used during the service callback processing.

Callback data

In this example, the callback to the client is responsible for sending data back to the client for display. In this case, the data is a timestamp identifying when the event was fired and some test data. This is packed into a data structure called DeviceEventData

public class DeviceEventData
{
    public DateTime timestamp { get; set; }
    public string message{ get; set; }
}

...

DeviceEventData eventData = new DeviceEventData();
eventData.message = "Test Data";
eventData.timestamp = DateTime.Now;
theClient.SendDeviceEventData(eventData);

To get this data to the client, all that we need to do is create a data object, initialize it and pass the data as a parameter in the service callback interface.

Building a test client

Silverlight 4 really does make life easy, even when talking to duplex services. The key to this is to create a service reference.

The service reference takes care of all the low level stuff, including handling all asynchronous aspects of the relationship between the client and service.

Once we have a service reference, we can hook up to the service and service callback:

public partial class MainPage : UserControl
{
    ObservableCollection eventData;

    public MainPage()
    {
        InitializeComponent();

        eventData = new ObservableCollection();

        EndpointAddress address = new EndpointAddress("http://localhost:8000/DeviceEventService");

        CustomBinding binding = new CustomBinding(
            new PollingDuplexBindingElement(),
            new BinaryMessageEncodingBindingElement(),
            new HttpTransportBindingElement());

        DeviceEventService.DeviceEventServiceClient client = new DeviceEventService.DeviceEventServiceClient(binding, address);
        client.SendDeviceEventDataReceived += new EventHandler(client_SendDeviceEventReceived);
        client.ConnectAsync(Guid.NewGuid().ToString());
        EventListBox.ItemsSource = eventData;
    }

    void client_SendDeviceEventReceived(object sender, DeviceEventService.SendDeviceEventDataReceivedEventArgs e)
    {
        if (!eventData.Contains(e.data))
        {
            eventData.Add(e.data);
        }
    }
}

As you can see, the client is creating an ObservableCollection to hold the event data returned by the service callback. Next, the client connects up to the service endpoint, creates an implementation object for the service and initializes this object. Initialization means:

  • Associating the object with the endpoint binding,
  • Setting up a delegate to process the callback event and
  • Call the Connect service method. Note this call has an asynchronous implementation.

Note that the event data ObservableCollection is then bound to the clients visual component, in this case a ListBox.

Now when the callback delegate is fired, all that we need to do is add the event data to the ObservableCollection, and because this collection is observable, the ListBox is told about it.

In the XAML, the listbox binds the data to the list items:

<ListBox Grid.Row="1" x:Name="EventListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Width="770">
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="1" Text="{Binding timestamp}"></TextBlock>
                <TextBlock Grid.Column="1" Text="{Binding message}" FontWeight="Bold" Foreground="Red" HorizontalAlignment="Right"></TextBlock>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

and hey presto…

Wow, that was easy, Silverlight 4 seems to be doing all the work!

Conclusion

As you can see, its easy to build duplex service under WCF. What’s more, Silverlight 4 is well matched to this technology, providing simple binding against the callback event.

Saturday, 21 August 2010

Chubby RESTful Clients using Silverlight and WCF

wcfsilverlight  [Concrete/Interesting] Many years ago I was working on a project. We needed a application that worked in a browser but everything came from the local machine. Later I started to notice devices like Routers that had a web interface…just connect using HTTP to the device IP address and there you are.

I used a similar technique in my Ghostfiles Service application (http://www.lowrieweb.com/ghostfiles.htm).

Chubby Client Architecture

Ghostfiles is a Windows Service Application that runs as a lightweight HTTP server on a private HTTP port. If you point your browser at it, the service returns back application pages. It’s just like having Apache or IIS running, only lightweight with only the pages of the application supported. This is what I called a Chubby Client, a thin client interface delivered to a browser by a local web and application server.

The basic architecture used in Ghostfiles is shown here:

image 

Page requests (GET/PUT) from the browser are handled by the light HTTP Web Server. This directs the calls to Page Service.

Page Services are responsible for mapping the request against a template page. The template defines the basic HTML resources associated with this request. The template can contain standard mark-up as well as JavaScript.

So far so good. The template may also contain meta-tags that are interpreted by the meta-tag handler. This sub-system is responsible for mapping the tags to calls down to the business services. So for example, a table on the page is defined by a meta-tag, <APP:DoSomething></APP:DoSomething>. This maps to a business function DoSomething();

Looks familiar – well it’s very similar to PHP or old style ASP in how it works. And it works well from an application and UI point of view. However, the code is hard to maintain, adding new user interfaces is an effort and the implementation is limited to HTML and JavaScript, so not an ideal platform going forward.

Chubby Client Grows Up

.Net provides us with a way to take the Chubby Client into the realm of Rich Internet Applications (RIA). To achieve this we need to look at two core technologies, Silverlight Out Of Browser Clients and Self Hosted WCF:

image

WCF Self Hosting

Windows Communication Foundation is a well balanced communication framework. One feature of WCF is the range of hosting options. A couple of these allow us to deploy a service implementation without the overhead of IIS. WCF Self Hosting enables us to deploy communication services fully encapsulated as a standalone executable or if preferred, Windows Service Application.

I’m going to focus on RESTful web services for HTTP JSON clients. For the purpose of this blog, I’m going to create a Console based REST service that exposes one simple interface called Colour:

URI: http://localhost:8000/Chubby/Colour
MIME: application/json
HTTP Method: GET

The response to this call is a random colour reference in the form of:

{ “Colour” : “#FFRRGGBB” }

The steps to create the service are very easy under Visual Studio 2010:

Step 1

Create a new project based on a C# Console Application:

image Next add references to System.ServiceModel, System.ServiceModel.Web and System.Runtime.Serialization to the console application and add the following statements to the top of your Program.cs file:

using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Description;
using System.Runtime.Serialization;
using System.IO;

Note: You should check the Target Framework for the project, in Project Properties. This should be set to .NET Framework 4 to ensure the Reference filters are correctly set:

image

Step 2

Define and implement the service contracts. This defines the JSON services that will be exposed by this console application and the implementation behind these services.

Note: As well as the Chubby Service, we also need to define and implement Cross Domain Policies for our service. This is important because we are calling the service from Silverlight and Silverlight will need to be reassured that it can use the service:

#region Service Contract

    [ServiceContract]
    public interface IChubbyServices
    {
        [OperationContract]
        [WebGet(UriTemplate = "Colour", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
        JSONColour GetColour();
    }
    #endregion

    #region Service Contract for Cross Domain Policies

    [ServiceContract]
    public interface IPolicyRetriever
    {
        [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
        Stream GetSilverlightPolicy();
        [OperationContract, WebGet(UriTemplate = "/crossdomain.xml")]
        Stream GetFlashPolicy();
    }
    #endregion
    
    #region Data Contracts
    
    [DataContract]
    public class JSONColour
    {
        [DataMember]
        public string colour = String.Empty;
    }
    #endregion

    #region Service Implementation

    public class ChubbyServices : IChubbyServices, IPolicyRetriever
    {
        public JSONColour GetColour()
        {
            //Return a random colour from the list below
            string[] colours = { "#FFFF0000", "#FF00FF00", "#FF0000FF", "#FFFFFF00", "#FFFF00FF", "#FF00FFFF", "#FF000000" };
            JSONColour colour = new JSONColour();
            Random rand = new Random();
            colour.colour = colours[rand.Next(7)];
            return colour;
        }
        Stream StringToStream(string result)
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }

        public Stream GetSilverlightPolicy()
        {
            string result = @"<?xml version=""1.0"" encoding=""utf-8""?>
            <access-policy>
               <cross-domain-access>
                  <policy>
                     <allow-from http-request-headers=""*"">
                        <domain uri=""*""/>
                     </allow-from>
                     <grant-to>
                        <resource path=""/"" include-subpaths=""true""/>
                     </grant-to>
                  </policy>
               </cross-domain-access>
            </access-policy>";
            return StringToStream(result);
        }

        public Stream GetFlashPolicy()
        {
            string result = @"<?xml version=""1.0""?>
            <!DOCTYPE cross-domain-policy SYSTEM ""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"">
            <cross-domain-policy>
               <allow-access-from domain=""*"" />
            </cross-domain-policy>";
            return StringToStream(result);
        }
    }
    #endregion

Quick note about the class JSONColour. The service is designed to respond with Mime type “application/json”. To do this we need to instruct WCF to serialize the data in JSON format. This is defined by the Operation Contract against the method, specifically:

ResponseFormat = WebMessageFormat.Json

Now to ensure there is something for WCF to serialize, we create a Data Contract for serialization and define a structure to be serialized. In our case we call the structure JSONColour. With WFC that is all that is required to ensure correct serialization for JSON.

Step 3

Now we need to implement the host responsible for running the service:

#region Host Implementation

    class Program
    {
        static void Main(string[] args)
        {
            string baseAddress = "http://localhost:8000";

            using (ServiceHost host = new ServiceHost(typeof(ChubbyServices), new Uri(baseAddress)))
            {
                host.AddServiceEndpoint(typeof(IPolicyRetriever), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
                host.AddServiceEndpoint(typeof(IChubbyServices), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior("Chubby"));
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                host.Description.Behaviors.Add(smb);

                host.Open();

                Console.WriteLine("WCF Host Running...");
                Console.WriteLine();

                foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
                    Console.WriteLine("Supported Endpoint for {0} at address {1}", endpoint.Binding.GetType().Name, endpoint.Address.Uri);

                Console.WriteLine();
                Console.WriteLine("Press  to shutdown");
                Console.ReadLine();

                host.Close();
            }
        }
    }
    #endregion

Here we are creating a host and setting up the appropriate WebHTTPBindings as required by REST.

Step 4 

Now all we need to do is compile, run and test. When run the service should open a console window similar to that shown below:

image The console should show the application started and the host running.

Since this is a REST host, we should be able to test the service from a browser. Open your browser and go to the URL shown below:

http://localhost:8000/Chubby/Colour

The browser should respond with the JSON response data. Typically the browser will not recognise the Mime type and will allow you to save the response in a file:

image If you save the response to a file then open the file it should look like this:

image

Excellent, just what we were looking for.

Silverlight Out of Browser

The service is half the story. To complete our Chubby Client we need a client that calls on our service. For this we are going to use Silverlight and implement and Out of Browser client.

Our client will be simple, with a single showing a TextBlock and a Button. The code behind will implement the call to the web service and handle the response. Let’s create the client:

Step 1

Create the Silverlight Client App. We are going to choose the Silverlight Application Template:

image

We need a web page to host our apps. Let’s choose an ASP.Net Web Site:

image 

Open MainPage.xaml and create our UI. All we need for this demo is a TextBlock to show the colour returned from our service call and a Button to kick things off:

image

<usercontrol xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:class="ChubbyClient.MainPage" mc:ignorable="d" d:designheight="300" d:designwidth="400">

   <grid x:name="LayoutRoot" background="White">
        <textblock height="68" horizontalalignment="Left" margin="65,74,0,0" name="textBlock1" text="TextBlock" verticalalignment="Top" width="264" fontfamily="Comic Sans MS" fontsize="32" fontweight="Bold" textalignment="Center"></textblock>
        <button name="button1" height="55" horizontalalignment="Left" margin="145,187,0,0" verticalalignment="Top" width="104" fontsize="18" content="Press Me">
    </grid>
</usercontrol>
Step 2

Now we can wire up the button. Double click on the button in the IDE to create an event handler in the code behind. In this event handler we are going to call the web service.

I’m going to use a WebClient() object to make an HTTP GET call to the web service. The data response will be given to us in an asynchronous handler:

private void button1_Click(object sender, RoutedEventArgs e)
{
   WebClient client = new WebClient();
   client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
   client.DownloadStringAsync(new Uri("http://localhost:8000/Chubby/Colour"));
}

void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
   if (e.Error != null)
      return;
}

The results are found in e.Results in JSON encoding. All we need to do now is lightly parse the results, pulling out the colour and apply that colour to our styles. First we have to add a reference for System.Json to the project and a using statement to the code. We will use the System.Json assembly to help us decode the results.

Now to parse the results and update the view:

private Color GetColorFromHexa(string hexaColor)
{
   return Color.FromArgb(
      Convert.ToByte(hexaColor.Substring(1, 2), 16),
      Convert.ToByte(hexaColor.Substring(3, 2), 16),
      Convert.ToByte(hexaColor.Substring(5, 2), 16),
      Convert.ToByte(hexaColor.Substring(7, 2), 16));
   }

   void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
   {
      if (e.Error != null)
         return;

      JsonObject jsonDoc = (JsonObject)JsonObject.Parse(e.Result);
      string colour = jsonDoc["colour"];

      //Update the view
      textBlock1.Foreground = new SolidColorBrush(GetColorFromHexa(colour));
}
Step 3

The last step is to make the Silverlight run Out of Browser. This is very simple. Open up the properties for the Silverlight client and select the Siverlight tab. All we need to do is check the ‘Enable running application out of browser’. You may also want to change the out of browser settings.

image

That’s it, job done.

Chubby Client Grows Up

As you can see, we can build Silverlight out of browser applications that are serviced locally by a WCF console application.

This concept can be taken further in a number of directions. We can package the WCF service as a windows service. We can make an installer that puts both client and services onto the local machine, registering the client to access the local services. We can take the same client and call a remote service – so chubby client for desktop and thin client for RIA.

From a code point of view, I’ve done a quick and dirty here. The client should be better architected to follow a MVC or MVVM patterns. The server should be more modular with the service contracts in separate assemblies. I’m sure there is a lot more that can be improved.

To help you get started, I’ve published the code above to Google Code.

http://code.google.com/p/chubbyclient/

Have fun.