Categories: Finance Posted by mheydt on 7/24/2010 6:54 PM | Comments (0)

Just making a note about this blog entry I looked up once upon a time.  Being a linear algebra head, I thought it was really explanatory of the concept of market risk using linear algebra.

http://phorgyphynance.wordpress.com/2008/02/10/visualizing-market-risk-a-physicists-perspective/

Categories: .Net, C#, AppFabric Cache Posted by mheydt on 5/10/2010 5:20 PM | Comments (0)

In this post I will describe how to install AppFabric Cache (AFC) and begin talking to it with a C# application.  There are many useful things that can be done with AFC, but through I series of post I will discuss a scenario that I am using it for now which is to provide a scalable middle tier data service for routing events from back end systems to Silverlight clients.

But lets start with just getting this to work, which initially seems easy, but like everything else has its issues.  First, we need to get a few installation packages.

Download the proper install for AFC from:

http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=8197ad8d-673f-4efb-b165-82710f2648c3

I'm installing this on a fresh Windows 2008 R2 box, so I also need to install .NET 4.0, which you can get here:

http://www.microsoft.com/downloads/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en

Once you have those and .NET 4 installed, start the AppFabric Cache setup, sign your life away, and press next.

You then get the customer experience improvement dialog:

Right now I don’t want to participate in the improvement program so I just press ‘Next’, which takes us to the select services dialog:

I only need caching for this demonstration, so I select them and press next, and it takes you to the confirmation screen:

Press install.  When done, you get the ‘installed ok’ screen:

At this point we need to configure the cache service, so leave the check box selected and press ‘Finish’.  A few moments later you’ll be presented with the send feedback page for the configuration wizard:

I select ‘no’ and press next to get to the main configuration screen:

Now with this screen I’m not sure why it is possible to not check the Set Caching Service configuration box.  I tried that, and could not get things to work (in retrospect, I think it was because of the yet to be described security issue, but it’s just best to do this with a cluster [even a one node cluster] anyway).  So, check it and fill out the information as needed.

For my configuration I created an account named ‘velocity’ on the local machine and use that as the login account for the cache service; the setup program does not let you use a built in account. 

I am also going to use the XML configuration technique as I want to keep this lightweight without using SQL Server.  To do this you must have a network share accessible, so I created a folder on this system (VELOCITYA) and shared it as ‘VelocityConfig’.

Since this is the first system installed, I select ‘New cluster’, and I’m going to use a small cluster (1-5 machines).

Select ‘Next’ and you will be taken to the page to configure the ports that the cache will use.

Leave these as the defaults.  Note, I have the windows firewall disabled so those options are also disabled.

Now press ‘Finish’, and accept the confirmation dialog.  After a few seconds your configuration will be completed.

But, you are not done, yet.

There are a few powershell commands that first need to be executed.  The install will have installed several menu items:

Select “Caching Administrator Windows PowerShell’.  This will open a powershell console where you need to run several commands.  First run this command: ‘Use-CacheCluster’.

The output is pretty basic – nothing.  Now run ‘Start-CacheCluster’.  A teal box will show some status of starting the cluster:

And then you’ll get some status of the nodes in the cluster.

Now that we have a one node cluster running, lets try to verify we can talk to it with some C# code.

First, you’ll need the caching client assemblies.  I believe you can install these on your development system with the AppFabric Cache installer, but I grabbed mine from the cache server itself in the \windows\system32\appfabric folder:

The code I have here is the simplest code you can use to simply connect to the local system’s cache and retrieve the default cache (with the caveat of some security code needed to solve a security problem that is described soon).

When running this on the VELOCITYA server, the following is the result:

What’s the deal with this?  Well, that was a lot of googling on my part to figure out, so I’ll save you the trouble.

The short of it is because the AppFabric cache is not running in a domain it is not authenticating the request, even from the local box.  To fix this, we must modify our cache clusters configuration file.  There are a few ways to do this, but I found it simplest to just open the XML file in the network share (\\VELOCITYA\VelocityConfig\ClusterConfig.XML").  This is the default content after the configuration that we previously performed:

We need to add the following lines (26-28):

Ideally not the best for security but it is good enough for our purposes of demonstration.  Also, I needed to reboot the cache server after making this change.  I tried to restart the service, but that didn’t seem to get the settings.  Once successful, the program output will be the following:

Success!

Note that those lines added to the configuration file also required the addition of lines 32-34 in the source code.  I’ll describe other security models in later posts, but this suffices at this point in time.

Also, please note that the install be default does not set the cache service to start automatically, so you’ll need to go and change that in the services dialog (either start it manually or configure it to auto start).

 

Next post...  Adding items to the cache and getting notifications of new items in the cache.

Categories: Azure, oData Posted by mheydt on 4/4/2010 4:29 PM | Comments (0)

Today I went through the process of oData enabling one of my SQLAzure databases.  One of the advantages of using SQLAzure is that it is easy (almost) to enable oData access.  The following was the process I went through for your use, as I didn't see a similar tutorial.

First, I recommend starting at this page on the oData site (it is where I started):

From this page you can go to the oData Service Portal, which is at this URL: https://www.sqlazurelabs.com/ which looks like the following:

Click on the OData Service for SQL Azure tab.  Upon your first time in, you'll see a registration screen as follows.  Accept the terms and continue.

When you get in, you'll be presented with a form to enter your SQL Azure database credentials:

Press connect, and upon successful connection, you will be presented with a list of specific databases fromt that server for you to oData enable.  Select your database, and the 'Enable OData' checkbox, and you will be presented with a request to specify access to the database.  The default is no anonymous access:

You can select any user in your database if you want anonymous access.  For now I'm using 'dbo':

At this point, you have actually completed oData enabling of your database.  You can access the data at the URL provided in the portal on the screen.  As an example, if I click the link above, I get the following result:

I only have one table in this database, named HistoricalErcotPrices.  If I was to append /HistoricalErcotPrices to the URL, I would get the following:

Not incredibly useful, but if you view source, you can see the data:

Very nice indeed!

If you want an app to visualize your oData feed, there is the Silverlight OData Explorer, which looks like the following once you enter your feed url:

Categories: .Net, GPGPU Posted by mheydt on 4/4/2010 12:16 PM | Comments (0)

I've been looking into some GPU work lately as I have a potential opportunity to potentially do a project like this for a client.  I've looked at the stuff a while ago, but today a quick search seems to show the following as the libraries to use for .NET:

I'll probably give both of these over the next few weeks.

Some resources:

Categories: RIA, Silverlight, WCF Posted by mheydt on 1/26/2010 11:10 AM | Comments (0)

A few weeks back I wrote about getting RIA services to work with POCO.  It was a long post, so long that it was 5 posts.  In the weeks since, I spent some time trying to use POCO/RIA in some work that I was doing for a client, and I started to develop some strong feelings about why bother with all of this extra work to just get things to work with RIA instead of just using WCF/Data Contracts/DTOs.  I'm still trying to be able to articulate these feelings, but figure I'll give it a shot right now.

First, it was a lot of work to get the POCO to work with RIA, at least compared to just creating a class that is annotated with DataContact/DataMember attributes.  The former took me 5 posts just to describe how it works.  The latter takes maybe a minute to build an end to end solution.

But that's not all.

Second, a lot of what RIA (excuse me WCF RIA) does is autogenerate code to do different things, such as generating client side objects that know how to track changes and do automatic validation.  I'm left to wonder about the former, but do by that the automatic validation code is useful, but I'm not sure its worth the effort getting POCO to work over using validation libraries such as EL. 

The issue with tracking changes I think is the sticking point, as I don't see what value there is in POCO, as it is inherently tied to using entities on the server side (read Entity Framework).  Without the mapping back to entities in the client side, is it adding any value?  I don't see that it is.

This also leads to the generation of service methods for which I can see as nothing but CRUD operations.  Again in a POCO world, is CRUD really necessary?  If I'm not using a database, and not modelling my objects off of entities generated from the database, do I really need CRUD methods auto generated by convention? And to be honest, it was really hard to just get a single POCO object returned with RIA.

So what I think this boils down to is without a database, and then additionally without EF, I don't see the advantage.

And now one more kicker.  The system I was building wanted to try and use RIA, but we were not connecting to a database, so hence the POCO route.  Instead of a database, we are connecting with a backend system via EMS messages bridged over JMS into services in Oracle.  This throws this whole thing into the world of asyncronous messaging.  WCF RIA services are inherently tied to syncronous operations, since they pretty much are generated to do syncronous communications to the database and return the result.  The EMS method we looked at had to be asyncronous (it's the nature of the environment I'm working in, not that EMS can't be syncronous - the back end Oracle app could not do this syncronously). 

So, the method to get objects would need to either block waiting to a response message on EMS, or return directly without any data.  In the latter case, there is really no use for RIA; why do all this magic if I can't get the data to be managed during the RIA services call?  Well, none that I can see.  In the case of blocking waiting for a response, sure I can program that, but it is going to inherently reduce scalability of the solution.  And it kind of defeats one of the things I really like about Silverlight - the asyncronous nature of calls to the client.  The Silverlight client will still do the call asyncronously which is great, but with my having to program syncronous blocks on the server it just seems to defeat the purpose.  I would rather go totally asyncronous and gain all the scalability possible, even at the expense of having to use callbacks from the server to the silverlight client for when response messages arrive back on EMS.

So, I guess this would lead to some rules about when to use / not use WCF RIA.  I'll take a try at them...

When not to use:

  • You are not using a database.
  • You need asyncronous communications with a third tier
  • You are using something other than Silvelright for a client

When to use:

  • You don't have a database, or are doing async communications with a third tier, but feel the automatic generation and use of validation rules is worth the effort
  • You are building forms-like CRUD apps against your database model

I also have concerns about how portable this is to non-Silverlight clients.  For example, I can't use the RIA objects in WPF, and I wonder how this would integrate to web or AJAX clients; sure the classes can't be used, but can you use the web services that are exposed?  My guess (as I haven't tried it yet) is that you can't, at least easily.

I'd really like to hear your comments on this.  Every time I look at RIA services I really want to like it, and I'd like to be able to feel like it has broader value, so please let me know your experiences.

 

Categories: WPF Posted by mheydt on 1/22/2010 11:44 AM | Comments (0)

Last night I posted about a way to do glass effects in your WPF application.  The technique I showed was very basic, just showing how to extend glass into the client area.  In a lot of cases, you will want to do a lot more.  An example is that it is desireous to put a background image behind the entire window.  This would seem to be very straightforward with some XAML as such:


<Window x:Class="SocialBus.Navigator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Hello there" Height="350" Width="525" Icon="Assets/Icons/transparent.png" Background="Transparent">
    <Grid>
        <Border BorderBrush="Transparent" BorderThickness="0">
            <Border.OpacityMask>
                <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
                    <GradientStop Offset="1.0" Color="Black" />
                    <GradientStop Offset="1.0" Color="Transparent" />
                </LinearGradientBrush>
            </Border.OpacityMask>
            <Image Source="Assets/images/pdc09black.png" Stretch="UniformToFill" />
        </Border>
    </Grid>
</Window>

What this xaml is trying to do is use the pdc09 image as a background, with a linear fade of the opacity from 100% at the bottom to 0% at the top.  Unfortuantely, the result is not what I desired, as there is still non-client area on the window that the image is not behind (although I have made the opacity 100% for this image to show the issue better):

The solution to this seems to be involved in intercepting the WM_NCCALCSIZE message to the window, and munging the data to tell the window to have the client area cover the whole window.  After many hours of trying to get that to work I just gave up on it and went for another solution.

Another great article on glass effects (chrome) is at this link:

http://blogs.msdn.com/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx

The article itself is quite informative, and states that dealing with the WM_NCCALCSIZE method is not trivial.  Fortunately, that writer also has a library that helps out greatly, and you can get it here:

http://code.msdn.microsoft.com/chrome/Release/ProjectReleases.aspx?ReleaseId=1505

I examined this code and it appears very robust, as it handles all kinds of issues with WDM.  Nice thing is that it is very easy to use.  Just link the DLL into your project, and for the desired effects I just change the XAML to the following:


<Window x:Class="SocialBus.Navigator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ext="clr-namespace:System.Windows.Extensions;assembly=Chrome"
        Title="Hello there" Height="350" Width="525" Icon="Assets/Icons/transparent.png" Background="Transparent">
    <ext:WindowChrome.WindowChrome>
        <ext:WindowChrome
          ClientBorderThickness="-1" />
    </ext:WindowChrome.WindowChrome>
    <Grid>
        <Border BorderBrush="Transparent" BorderThickness="0">
            <Border.OpacityMask>
                <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
                    <GradientStop Offset="1.0" Color="Black" />
                    <GradientStop Offset="1.0" Color="Transparent" />
                </LinearGradientBrush>
            </Border.OpacityMask>
            <Image Source="Assets/images/pdc09black.png" Stretch="UniformToFill" />
        </Border>
    </Grid>
</Window>

Note that all I did was add the reference to the DLL and add the one tag, which does a lot of magic in the background configuring the window for custom chrome.  The result now is the following:

Perhaps still not quite what I want, but what is going on is that all non-client areas are removed and the image takes up the whole window.  With a simple tweak, I can make this much better, by putting the gradient fade back in as well asrounding the corners of the image a little (note, I also changed this a little so that instead of using a border I used a rectangle - border wouldn't clip the image corners round):


<Window x:Class="SocialBus.Navigator.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ext="clr-namespace:System.Windows.Extensions;assembly=Chrome"
        Title="Hello there" Height="350" Width="525" Icon="Assets/Icons/transparent.png" Background="Transparent">
    <ext:WindowChrome.WindowChrome>
        <ext:WindowChrome
          ClientBorderThickness="-1" />
    </ext:WindowChrome.WindowChrome>
    <Grid>
        <Rectangle RadiusX="10" RadiusY="10">
            <Rectangle.Fill>
                <ImageBrush ImageSource="Assets/images/pdc09black.png" Stretch="UniformToFill" />
            </Rectangle.Fill>
            <Rectangle.OpacityMask>
                <LinearGradientBrush StartPoint="0,1" EndPoint="0,0">
                    <GradientStop Offset="0.0" Color="Black" />
                    <GradientStop Offset="1.0" Color="Transparent" />
                </LinearGradientBrush>
            </Rectangle.OpacityMask>
        </Rectangle>
    </Grid>
</Window>

And the result: just beautiful!

Glass, transparancy of the whole window, and with a custom background.  Kewl!  And by the way, drag at the top, min, max, close resize on all edges still works perfectly.

There's alot more that can be done with this library, but this is exactly what I ndeeded.

Categories: WPF Posted by mheydt on 1/21/2010 10:18 PM | Comments (0)

Today I downloaded the freshly released Seesmic Look application. This is a twitter client that I think makes really great use of WPF. Here's a screen shot:



There are a number of great things going on here, one of which is the use of Aero glass in the WPF application. Notice how the desktop wallpaper blends through the upper part of the window. This is a pretty simple thing to do, but not well documented. There are a few links to information on how to do this that I'll enumerate here, as well as show how to do this in a sample application.

There are a number of great things going on here, one of which is the use of Aero glass in the WPF application. This is a pretty simple thing to do, but not well documented. There are a few links to information on how to do this that I'll enumerate here, as well as show how to do this in a sample application.

The two links that I found useful are:
http://blogs.msdn.com/adam_nathan/archive/2006/05/04/589686.aspx
http://blogs.msdn.com/wpfsdk/archive/2008/09/08/custom-window-chrome-in-wpf.aspx

Adam gives some code for doing this trick in WPF. I'll reproduce the entire code of the class and an implementation for completeness.

The class for forcing glass into your window is this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Interop;

namespace SocialBus.Navigator.Glass
{
    public class GlassHelper
    {
        [DllImport("dwmapi.dll", PreserveSig = false)]
        static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);

        [DllImport("dwmapi.dll", PreserveSig = false)]
        static extern bool DwmIsCompositionEnabled();

        [DllImport("user32.dll")]
        static extern uint GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);

        private const int GWL_STYLE = -16;
        private const uint WS_SYSMENU = 0x80000;

        struct MARGINS
        {
            public MARGINS(Thickness t)
            {
                Left = (int)t.Left;
                Right = (int)t.Right;
                Top = (int)t.Top;
                Bottom = (int)t.Bottom;
            }
            public int Left;
            public int Right;
            public int Top;
            public int Bottom;
        }
       
        public static bool ExtendGlassFrame(Window window, Thickness margin)
        {
            if (!DwmIsCompositionEnabled())
                return false;

            IntPtr hwnd = new WindowInteropHelper(window).Handle;
            if (hwnd == IntPtr.Zero)
                throw new InvalidOperationException("The Window must be shown before extending glass.");

            /* Set the background to transparent from both the WPF and Win32 perspectives */
            window.Background = Brushes.Transparent;
            HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;

            MARGINS margins = new MARGINS(margin);
            DwmExtendFrameIntoClientArea(hwnd, ref margins);

            return true;
        }
    }
}

Now to get the window to use this, we just need to hook up the OnSourceInitialized event/override in the main window control of the application as such:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

using SocialBus.Navigator.Glass;

namespace SocialBus.Navigator
{

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            GlassHelper.ExtendGlassFrame(this, new Thickness(-1));
        }
    }
}

When running this, the window looks like this:

Very nice! Notice also that I have removed the system icon and title from the window. The title is easy to remove by just setting the Title in the xaml to "". The icon is a little more difficult. You just cant set the Icon property on the window control to null, as WPF takes that as meaning that you want to use the default icon. What you need to do is prvoide a transparent icon. At first I was wondering how you make an .ico file with a transparent background (I dont think you can actually). But fortunately the flexibility of WPF allows for using a .png file for an icon, so I just made a 16x16 png file that was all transparent.

To follow up this post, I actually have some nice twitter control in the works and will add those to this window to show how nice things can look with this technique.

Categories: Silverlight, WCF Posted by mheydt on 1/5/2010 6:55 PM | Comments (2)

Over the last several weeks I've been investigating for a client a means of providing callbacks to Silverlight clients to push trade updates to all the users.  This has typcially been done using a PollingDuplexHttpBinding in Silverlight 3 and 2, but this is problematic as it is first a polling model (yuk!), and second the only data format is XML it could be slower then using a binary format.

The experience has been quite an adventure, as usual with beta Microsoft stuff.  There's not much documentation available, and everything that can be found is kind of all over the place in quality.  The best two sources I have found are the following two great blog posts by Tomasz Janczuk and Radenco Zec:

While these were valuable posts, I did still find the effort to have a lot of troubles, so I thought I'd also throw out my $0.02 on the process.

To get this Net.TCP to Silverlight 4 to work, you are going to need to do a bunch of things even to get up and running:

  • You need to run the web solution under IIS as the VS.NET web server does not support NET.TCP
  • You must configure Non-HTTP activation for IIS so it can respond to Net.TCP request
  • You must configure both the web site and web application to respond to Net.TCP
  • You must provide a policy server to verify the client as being able to communicate to the server with TCP

I had some problems with each of these, and I'll walk through configuration of these items.

Once you have that complete, there is also a bunch of configuration and programming that you need to get right in order for everything to work:

  • Your server web.config needs to be configured properly to support Net.TCP
  • Your client must also bind properly to the service

Yes, all WCF things need this, but I found documentation to be vexing, so I'll show exactly how I did it.

To get IIS configured to use Net.TCP, you need to go to control panel / install windows components, and make sure the following is selected:

This allows .NET to integrate with the Windows Process Activation Service to kick-start IIS on receipt of Net.TCP requests.  After installing this you will notice in the service management console the following service:

Make sure this service is running or you will get the an error when attempting to contact the service (I'll show the error later, once I get to some code).

Ok, A little of the prerequisites are out of the way so lets do a little coding!  Create a new visual studio solution which consists of a Silverlight 4 application and web site to serve the application.   My example looks like this:

At this point, because we cant use the VS.NET web server, we need to modify the web site configuration to run under IIS.  To do this, right click the web solution and bring up properties / web, and select "Use Local IIS Web server".  It will auto fill a project url, and then press 'Create Virtual Directory' to set up the application in IIS:

You should get a dialog stating that the virtual directory was created successfully.  Now add a WCF service to the web project that we will use to send messages back to the client.  I've called mine "PushDataService", and it creates an interface file (IPushDataService.cs) and PushDataService.svc file in the web project.  It is also needed to create an interface that represents the API that the server uses to talk back the the client, so I add an interface to the web solution named IPushDataCallback.

Now that we have the service and interfaces created, we need to add some method definitions to them and annotate them with attributes properly.  My IPushDataService interface is as follows:

namespace DuplexSilverlightExamples.Web
{
    [ServiceContract(CallbackContract = typeof(IPushDataCallback))]
    public interface IPushDataService
    {
        [OperationContract(IsOneWay = true)]
        void RegisterForUpdates();
        [OperationContract(IsOneWay = true)]
        void UnregisterForUpdates();
    }
}

The interface contains two methods, one that the client will call to notify the server that it wants to receive push updates, and another to tell the server would like to stop receiving updates.  Both of these methods are annotated with [OperationContract(IsOneWay = true)] which tells WCF that the client can call these methods and that there is no return value and it doesn't need to worry about a back channel.

The [ServiceContract(CallbackContract = typeof(IPushDataCallback))] on the interface tells WCF that the service implementing this interface is a WCF service and that it will support a communications channel back to the client and that it will follow the interface specified by IPushDataCallback.  And speaking of IPushDataCallback, here it is:

namespace DuplexSilverlightExamples.Web
{
    public interface IPushDataCallback
    {
        [OperationContract(IsOneWay = true)]
        void Update(string theUpdateMessage);
    }
}

This tells WCF that the communication channel back to the client will support a one way communications channel for passing a string message back to the client through the Update message.

Now we need to implement the service.  My service is implemented as such:

namespace DuplexSilverlightExamples.Web
{
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class PushDataService : IPushDataService
    {
        public static Dictionary<IPushDataCallback, IPushDataCallback> _clients =
            new Dictionary<IPushDataCallback, IPushDataCallback>();

        public PushDataService()
        {
            new Thread(new ThreadStart(pumpUpdates))
            {
                IsBackground = true
            }
            .Start();

        }

        public void RegisterForUpdates()
        {
            IPushDataCallback c = OperationContext.Current.GetCallbackChannel<IPushDataCallback>();
            if (!_clients.ContainsKey(c))
            {
                lock (_clients)
                {
                    _clients.Add(c, c);
                }
            }
        }

        public void UnregisterForUpdates()
        {
            IPushDataCallback c = OperationContext.Current.GetCallbackChannel<IPushDataCallback>();
            if (_clients.ContainsKey(c))
            {
                lock (_clients)
                {
                    _clients.Remove(c);
                }
            }
        }

        public void pumpUpdates()
        {
            Random w = new Random();

            List<IPushDataCallback> bad = new List<IPushDataCallback>();
            int count = 0;

            while (true)
            {
                Thread.Sleep(w.Next(10000));

                lock (_clients)
                {
                    if (_clients.Count > 0)
                    {
                        bad.Clear();
                        foreach (IPushDataCallback client in _clients.Keys)
                        {
                            try
                            {
                                client.Update(string.Format("{0}", count++));
                            }
                            catch (Exception)
                            {
                                bad.Add(client);
                            }
                        }

                        bad.ForEach(bc => _clients.Remove(bc));
                    }
                }
            }
        }
    }
}

The attributes on the class setup some Asp.NET compatibility, and also specify that I want a single instance of the service and that multiple clients can access it simultaneously.  The constructor starts a thread that runs the pumpUpdates method, and this will always run for the lifetime of the service, and since it is a singleton there will only be one of this tread running.  I also declare a dictionary object that will keep references to all connected clients that will be used to send the updates to the client.

The RegisterForUpdate method used the following statement:

IPushDataCallback c = OperationContext.Current.GetCallbackChannel<IPushDataCallback>();

What this does is it looks at the "context" of the current call - which contains information about various things, including any callback channels.  The GetCallbackChannel will look to see if there is an implementation of IPushDataCallback (which is specified on the IPushDataService definition, so it better be there).  If this client is not already in the dictionary, then the reference will be stored there for use by the pumpUpdates method.  The UnregisterForUpdates method basically does the opposite.

The pumpUpdates method will loop endlessly, sleeping for a random period up to 10 seconds, and then will send a message to all clients that are subscribed (the message is the count value).  Also on each pass through I keep track if there is an exception calling a specific client in the 'bad' list variable.  If an exception is caught, I'll remember that client and assume that it has "died" and that we don't want to call back to it anymore, and after all clients are updated I'll remove those "bad" clients from the update dictionary.

Ok, we've got the code in place.  Now we need to configure WCF (via the web.config) to support Net.TCP communication.  The configuration file as currently put together by vs.net is the following:


<?xml version="1.0"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true"/>
    </system.webServer>

    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

We need to extend this to the following:


<?xml version="1.0"?>
<configuration>

    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
 
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true"/>
    </system.webServer>

    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
             
              <behavior name="PushDataServiceBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceThrottling maxConcurrentCalls="2147483647" />
              </behavior>
             
            </serviceBehaviors>
        </behaviors>

      <bindings>
        <netTcpBinding>
          <binding name="InsecureTcp">
            <security mode="None"/>
          </binding>
        </netTcpBinding>
      </bindings>
     
      <services>
        <service behaviorConfiguration="PushDataServiceBehavior"
                 name="DuplexSilverlightExamples.Web.PushDataService">
          <endpoint address="" binding="netTcpBinding" bindingConfiguration="InsecureTcp"
                    contract="DuplexSilverlightExamples.Web.IPmtPocPushService"/>
          <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
          <host>
            <baseAddresses>
              <add baseAddress="net.tcp://localhost:4502/DuplexSilverlightExamples.Web/PushDataService.svc" />
            </baseAddresses>
          </host>
        </service>
      </services>
     
    </system.serviceModel>
</configuration>

What I've done here is added three sections:

  1. A service definition
  2. A netTcpBinding declaration
  3. and a new behavior section

The service definition:


<service behaviorConfiguration="PushDataServiceBehavior"
         name="DuplexSilverlightExamples.Web.PushDataService">
  <endpoint address="" binding="netTcpBinding" bindingConfiguration="InsecureTcp"
            contract="DuplexSilverlightExamples.Web.IPmtPocPushService"/>
  <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
  <host>
    <baseAddresses>
      <add baseAddress="net.tcp://localhost:4502/DuplexSilverlightExamples.Web/PushDataService.svc" />
    </baseAddresses>
  </host>
</service>

What this is specifying is that we want WCF to create a service implementing the IPushDataService interface, that we want to use the behavior we added in another section, the binding in the binding section, and that we want to expose two endpoints, one for metadata (using the mexTcpBinding), and one using NetTcpBinding (what this is all about) with the new behavior as well as the specified binding we are adding. 

Note that it is needed to add a base address entry to the service specifying the full address of the service.  Net.TCP doesn't seem to like that and you'll get and error if you dont use it.  Note also that I specify that the port used is 4502.  Silverlight is limited to ports 4502 - 4534, so you better specify one in that range.

The netTcpBinding is needed as we need to specify that there is no security to be used on the channel.  Net.TCP does not currently support a secure channel (they say this will likely be added in a future version) and we are forced to explicitly specify the insecurity.  The behavior section is also useful, mostly to specify that we want to have the maximum amount of simultaneous clients accessing the service.

Ok, we now have the server side complete, and we need to modify the client to use the service.  Add a service reference to the client application.  Or, well, try to, because you will likely get the following error:

Contract Requires Duplex, ...  WTF?  Well, this is a problem that I always get and expect you will too, and needs to be addressed.  Unfortunately, I spent a lot of time googling this to no avail.  How did I solve it?  I rebooted the computer and that problem went away.  Go figure!

However, like many things like this, that one problem begat another:

But this one is well known, and mentioned earlier.  We need to configure both the web site and the web application to accept net tcp connections.  First, configure the binding on the web site by right clicking the site and selecting edit bindings:

So, add the binding for net.tcp on port 4502:*  Then, it is also necessary to add net.tcp to the application, so right click on the application, select manage application -> advanced settings, and make sure that net.tcp is also specified instead of just http:

You should now be able to add the service reference to the client application.

The client application I put together shows the messages in a listbox; I won't go into that code.  But to utilize the service, I modify the MainPage.xaml.cs file as such:

public partial class MainPage : UserControl
{
    private ObservableCollection<string> _updates = new ObservableCollection<string>();

    public MainPage()
    {
        InitializeComponent();

        messagesListbox.ItemsSource = _updates;

        pds.PushDataServiceClient c =
            new pds.PushDataServiceClient("NetTcpBinding_IPushDataService");
        c.UpdateReceived += c_UpdateReceived;
        c.RegisterForUpdatesAsync();
    }

    void c_UpdateReceived(object sender, pds.UpdateReceivedEventArgs e)
    {
        if (e.Error == null)
        {
            _updates.Add(e.theUpdateMessage);
        }
    }
}

This is pretty straight forward code.  I keep an overvable collection of strings that hold the update messages and it is bound to the items source of the listbox.  I create an instane of PushDataServiceClient and pass the name of the binding in the ServiceReferences.ClientConfig file for the service (automatically created by the add service reference process).  The UpdateReceived event is bound to a method which will be called when the Update method on the client is called by the server (which triggers the UpdateReceived event - the name is the method name + "Received").  The event handler check to see if there was no error, and if so adds the parameter to the callback to the list, which then triggers an update of the UI.

But wait.  There is still a problem.  If you run this as is, it just looks like nothing is happening.  So, run the application in the debugger and you get the following error:

This is caused by us not having a socket policy server running.  When Silverlight attempts socket communications, it will contact the origin server on port 943 and ask for a policy file to see if the client is allowed to do communications.  This was actually a big issue for me at first as I thought I could just post the policy file in IIS and map port 943 to serve it with TCP.  That did not work.  You need to write your own server to do this, but thankfully there is one available as an online template project that you can add to your solution.  So, add a new project to the solution, but select "Online Templetes" for "silverlight tcp":

Once you have that project added, you can start it manually (it's a console app), or do like I do and setup multiple project starts with it going first.  Once you have it running you should see something like this in the application:

That is the listbox showing the messages sent from the server.  The console window just behind is the socket policy server.

But wait - there is perhaps one more problem!  If for some reason the Net.Tcp Listener service is not running, you would get an error similar to the following.  If that is the case, make sure the service is running.

Phew!  That's about it!  Must be a record for me for a blog post, but I hope it saves you a lot of hassle!

BTW, I will have a follow up post where I extend this service to have a binding for Http Duplex Polling in addition to the Net.TCP binding.  This will allow Silverlight 3 clients to still use the service, albeit a bit less efficiently, but it does keep them from being excluded from all the fun.  I'll write about how to do that soon.

Categories: Mix10 Posted by mheydt on 1/5/2010 6:32 PM | Comments (0)

I've got a session proposed for Mix'10.  Please vote for me! Click this image to be to cast your vote!

Title: Cloud Mashups: Creating integrated cross-cloud and on-premis systems using semantic data, mashup technologies, with desktop and mobile clients

Speaker: Michael Heydt, Sungard Consulting Services

Abstract:

Cloud mashups are a new type of application that combines cloud computing services from multiple clouds with your on-premis data and services rapidly into a single service or application. This session will demonstrate practical means of building these new types of applications, focusing on the key issues, specific best practices, and lessons learned for their creation and deployment. This session will share techniques for fusing Azure, EC2, and on-premis data and services using semantic data services, cloud based orchestration, mashup servers (including JackBe presto), rich Internet client (Silverlight) and mobile technologies (MonoTouch and iPhone) to rapidly create applications previously not possible with existing enterprise systems.

Posted by mheydt on 1/2/2010 1:50 PM | Comments (0)

I used to use this before DasBlog, but at the time (many years ago) it seemed that DasBlog was moving faster and had more features.  Well, seems DasBlog is pretty much dead, and I want more features.  I considered moving over to Wordpress, but gave BlogEngine.NET another look and I like what I see.  Hence, the move!