18 November 2009

A light-weight .NET framework for publishing Layar layers using WCF and Unity (C#)

Thus speaks Wikipedia:

Augmented reality (AR) is a term for a live direct or indirect view of a physical real-world environment whose elements are merged with (or augmented by) virtual computer-generated imagery - creating a mixed reality.

Amen. Fact is that AR is currently as hot a nuclear reactor core making its way to China, and that everyone and his aunt are scrambling to get a piece of the action. So why not me ;-)

On November 9th this year, my colleague Jeroen Prins, who did some prototyping with Layar, pushed a HTC Hero in my hands with the words “see if you can do something nice with it”. So in a few evenings I created a little framework for making Layar layers in an easier and consistent way. It is based upon some of Jeroen’s prototype, but since he insisted on not having credits for this I won’t give him any ;-). The framework uses the Enterprise Library, most notably Unity, and I assume you are familiar with it.

Since WCF can be bent in almost every direction as far as generating content is concerned, I decided to use it for my solution. I started, as you always start, with the data contract. The object model is pretty simple: a Layer object has Point-Of-Interest (Poi) objects, a Poi has Action objects. If you study the Layar GetPointsOfInterest page for a few minutes you will see the implementation is WCF 101. Maybe 102 ;-). Contrary to my habits, I forego on the comments – those are all on the GetPointsOfInterest page. First, the Action object:

using System.Runtime.Serialization;

namespace LocalJoost.Layar
{
  [DataContract(Name = "Action")]
  public class Action
  {
    [DataMember(Name = "uri")]
    public string Uri { get; set; }

    [DataMember(Name = "label")]
    public string Label { get; set; }
  }
}

The member name is “Uri” (following the .NET coding guidelines) but with adding “Name=uri” in the DataMember attribute I tell WCF to serialize the member as “uri”, without the capital “U”, thus following exactly the Layer API description. This is standard WCF stuff. Then, the Poi class:

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace LocalJoost.Layar
{
  [DataContract (Name="POI")]
  public class Poi
  {
    public Poi()
    {
      Actions = new List();
    }
    [DataMember(Name = "actions")]
    public List Actions { get; set; }

    [DataMember(Name = "attribution")]
    public String Attribution { get; set; }

    [DataMember(Name = "distance")]
    public double Distance { get; set; }

    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "imageURL")]
    public string ImageUrl { get; set; }

    [DataMember(Name = "lat")]
    public int Latitude { get; set; }

    [DataMember(Name = "lon")]
    public int Longitude { get; set; }

    [DataMember(Name = "line2")]
    public string Line2 { get; set; }

    [DataMember(Name = "line3")]
    public string Line3 { get; set; }

    [DataMember(Name = "line4")]
    public string Line4 { get; set; }

    [DataMember(Name = "title")]
    public string Title { get; set; }

    [DataMember(Name = "type")]
    public int Type { get; set; }
  }
}

and finally, the Layer object itself:

using System.Collections.Generic;
using System.Runtime.Serialization;

namespace LocalJoost.Layar
{
  [DataContract]
  public class Layer
  {
    public Layer()
    {
      Hotspots = new List();
    }

    [DataMember(Name = "nextPageKey")]
    public string NextPageKey { get; set; }

    [DataMember(Name = "morePages")]
    public bool MorePages { get; set; }

    [DataMember(Name = "hotspots")]
    public List Hotspots { get; set; }

    [DataMember(Name = "layer")]
    public string LayerName { get; set; }

    [DataMember(Name = "errorCode")]
    public int ErrorCode { get; set; }

    [DataMember(Name = "errorString")]
    public string ErrorString { get; set; }
  }
}

I move on to the whopping complex service contract:

using System.ServiceModel;
using System.ServiceModel.Web;

namespace LocalJoost.Layar
{
  [ServiceContract(Namespace = "www.yournamespacehere.nl/layar")]
  public interface ILayarService
  {
    [OperationContract]
    [WebGet(UriTemplate = "Layar/{layerName}/*", 
      ResponseFormat=WebMessageFormat.Json)]
    Layer GetLayerData(string layerName);
  }
}

which defines the output for this as being JSON, and a custom URI matching pattern which allows us to put the actual layer name in the URL. The * at the end means "and the rest is also accepted". Now the title of this posting says I was doing something with Unity, and here it comes: I define an equally complex interface for a Layar "provider" which will be used by the service implementation:

using System.Collections.Generic;

namespace LocalJoost.Layar
{
  public interface ILayarProvider
  {
    Layer Get(double? lat, double? lon, 
      int? radius, int? accuracy, 
      IDictionary requestParameters);
  }
}

The final piece of real code is the implementation of the ILayarService service contract, with apologies for the crappy layout, but some WCF class names are a wee bit long:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.ServiceModel.Web;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using LocalJoost.Utilities.Unity;

namespace LocalJoost.Layar
{
  /// <summary>
  /// Layar service implementation
  /// </summary>
  public class LayarService : ILayarService
  {
    /// <summary>
    /// Request parameters
    /// </summary>
    private static NameValueCollection RequestParams
    {
      get
      {
        return WebOperationContext.Current != null ?          WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters
: null;
      }
    }

    private static readonly List<string> KeyWordsProcessed = 
      new List<string> { "lat", "lon", "radius", "accuracy" };

    /// <summary>
    /// Gets the layer data.
    /// </summary>
    /// <param name="layerName">Name of the layer.</param>
    /// <returns></returns>
    public Layer GetLayerData(string layerName)
    {
      try
      {
        if (WebOperationContext.Current != null )
        {
          Logger.Write("Layar call: " +             WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri);
        }
        // Note: layername is lowercase
        var provider =
          new UnityResolver(
             layerName.ToLowerInvariant()).Resolve<ILayarProvider>();

        // Collect the other parameters
        var reqParms = new Dictionary<string, string>();
        foreach( var key in RequestParams.Keys)
        {
          var keyS = key.ToString();
          if (!KeyWordsProcessed.Contains(keyS))
            reqParms.Add(keyS, RequestParams[keyS]);
        };
        
        return provider.Get(
          GetRequestDouble("lat"), GetRequestDouble("lon"),
          GetRequestInt("radius"), GetRequestInt("accuracy"),
          reqParms);
      }
      catch( Exception ex)
      {
        Logger.Write(ex,"Exceptions");
        return null;
      }
    }

    #region Utility methods
    private double GetRequestDouble(String keyname)
    {
      if (!(RequestParams == null || 
         string.IsNullOrEmpty(RequestParams[keyname])))
      {
        return Convert.ToDouble(RequestParams[keyname], 
         CultureInfo.InvariantCulture);
      }
      return -1;
    }

    private int GetRequestInt(String keyname)
    {
      if (!(RequestParams == null || 
         string.IsNullOrEmpty(RequestParams[keyname])))
      {
        return Convert.ToInt32(RequestParams[keyname],
          CultureInfo.InvariantCulture);
      }
      return -1;
    }
    #endregion
  }
}

Here comes my little UnityResolver into play, which was described earlier in this blog. What this LayarService basically does is accept a layer name, burp the call into a log file, get the lat, lon, radius, and accuracy from the query string, dump the rest of the query string parameters into a dictionary, use Unity to determine which ILayerProvider implementation is to be loaded, call it’s Get method with the collected data, and return the result.

Now there are only six steps to make this actually work. First, you define a web application project. You reference the LocalJoost.Layar project, System.ServiceModel.dll, System.Runtime.Serialization, every file in the Enterprise Library that starts with "Microsoft.Practices.Unity" (I have 5), and Microsoft.Practices.EnterpriseLibrary.Logging.dll.

The second step is: add a text file to the web application, for instance "LayarService.txt". You enter the following text in it:

<%@ ServiceHost Language="C#" 
    Debug="true" Service="LocalJoost.Layar.LayarService" %>

and rename this the file to "LayerService.svc". The third step is some WCF configuration in the web.config of your web application to host the service as a webHttpBinding, thus making it accept calls via http get:

<services>
  <service name="LocalJoost.Layar.LayarService">
    <endpoint address="" binding="webHttpBinding"
 behaviorConfiguration="WebHttpBehavior"
 contract="LocalJoost.Layar.ILayarService" 
 bindingNamespace="http://whatever/layar">
    </endpoint>
   </service>
</services>
<behaviors>
  <endpointBehaviors>
    <behavior name="WebHttpBehavior">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>

The fourth step is to map your implementations of ILayarProvider to your layers. The LayerService class works in such a way that a layer maps directly to a Unity container, so a configuration might look like this:

<unity>
  <typeAliases>
   <typeAlias alias="ILayarProvider" 
        type="LocalJoost.ILayarProvider,LocalJoost.Layar"/>
   <typeAlias alias="SampleProvider" 
        type="SomeAssembly.SampleProvider,SomeAssembly"/>
   <typeAlias alias="AnotherProvider"
         type="SomeotherAssembly.AnotherProvider, SomeotherAssembly"/>
  </typeAliases>
  <containers>
   <container name="mylayer">
    <types>
     <type type="ILayarProvider" 
     mapTo="SampleProvider"/>
    </types>
   </container>
   <container name="someotherlayer">
    <types>
     <type type="ILayarProvider"
        mapTo="AnotherProvider"/>
    </types>
   </container>
  </containers>
</unity>

Here I have defined two sample containers, thus layers. If, for instance, your service is hosted as “http://mydomain.com/LayarServer/LayerService.svc” you can register your Layer with the Layar developer portal (which is, incidentally, the fifth step) as “http://mydomain.com/LayarServer/LayerService.svc/Layar/mylayer/” (mind the trailing slash!) and the framework will do the rest.

Now the sixth and final step is the real hard part: writing actual implementations of the ILayarProvider. This depends or what you are actually wanting to show. And this it where my help ends ;-).

A simple Unity helper for making class decoupling easier

Unity, a part of the Enterprise Library, is a great way of decoupling interfaces and implementation, and for opening a road into unit testing with mock objects. Unfortunately, using it can be a bit cumbersome. You have to create a container, configure it from code or from configuration, and have to decide when to do what. I thought it could do with some help, so I created some helper classes. I must admit this inspired by The Common Service Locator and some code for that I got from Dennis van der Stelt, but it is a little simpler to use. And it works only with Unity ;-) The idea is to define a factory and a resolver, that know of each other only trough an interface:
namespace LocalJoost.Utilities.Unity
{
  public interface IUnityResolver
  {
    Resolve<T>();
  }
}
Then, I define a UnityResolver, which is basically a wrapping around a UnityContainer class:
using System;
using System.Configuration;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace LocalJoost.Utilities.Unity
{
  /// <summary>
  /// Base class for unity resolvers
  /// </summary>
  [Serializable]
  public class UnityResolver : IUnityResolver
  {
    protected static string _defaultContainer = "Default";
    protected IUnityContainer Container{get; set;}

    /// <summary>
    /// Initializes a new instance of the UnityResolver
    /// Override this constructor if you want to write your own default
/// behaviour. /// Register in code by adding lines like: /// Container.RegisterType(Type.GetType("NameSpace.IMyClass",true), /// Type.GetType("NameSpace.MyClass",true)); /// </summary> public UnityResolver() : this(_defaultContainer) { } /// <summary> /// Initializes a new instance of the UnityResolver class. /// </summary> /// <param name="containerName">Name of the container.</param> public UnityResolver(string containerName) { Container = new UnityContainer(); var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection; if (section != null) { var containerConfiguration = section.Containers[containerName]; if (containerConfiguration != null) { section.Containers[containerName].Configure(Container); } } } /// <summary> /// Resolves an instance of T /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public T Resolve<T>() { return Container.Resolve<T>(); } } }

You can use this class directly, by calling new UnityResolver(“MyContainer”).Resolve<IMyType>(). The UnityResolver looks for a Unity container named “Default” in your configuration file. If that is not present, it creates an empty container. Use of the latter feature is described below.

This is not very efficient when all your classes are sitting into one and the same container, and you may want to have some consistent behavior of your classes during unit testing with mockups. So I created the UnityFactory class that can accept a resolver and hold it:

using System;
using System.Configuration;
using System.Reflection;
using System.Web;

namespace LocalJoost.Utilities.Unity
{
  /// <summary>
  /// Static helper class for shortcutting Unity instantiated 
  /// classes
  /// </summary>
  public class UnityFactory
  {
    /// <summary>
    /// Method to set the resolver manually - use this for unit testing
    /// </summary>
    /// <param name="resolver">The resolver.</param>
    public static void SetResolver( IUnityResolver resolver)
    {
      Resolver = resolver;
    }

    /// <summary>
    /// Gets a resolver from configuration.
    /// </summary>
    /// <returns></returns>
    private static IUnityResolver GetResolverFromConfiguration()
    {
      var configuredDefaultResolver = 
	    ConfigurationManager.AppSettings["UnityResolver"];
      if (!string.IsNullOrEmpty(configuredDefaultResolver))
      {
        var specParts = configuredDefaultResolver.Split(',');
        var ass = Assembly.Load(specParts[1]);
        var objType = ass.GetType(specParts[0]);
        return Activator.CreateInstance(objType) as IUnityResolver;
      }
      return null;
    }

    /// <summary>
    /// Gets the instance of an object via an interface
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static T GetInstance<T>()
    {
      // First, make sure there is a resolver. 
      // If none is defined, try to load one from configuration
      // If that fails too, use the default resolver
      if (Resolver == null)
      {
        Resolver = GetResolverFromConfiguration() ?? new UnityResolver();
      }

      // Then, resolve the interface to an object instance
      return Resolver.Resolve<T>();
    }

    #region Properties
    /// <summary>
    /// Gets or sets the resolver. Uses Http context or static variable
    /// to store a created resolver
    /// </summary>
    /// <value>The resolver.</value>
    private static IUnityResolver Resolver
    {
      get
      {
        if (HttpContext.Current == null)
        {
          return _resolver;
        }
        return HttpContext.Current.Application["__UnityResolver"]
          as IUnityResolver;
      }

      set
      {
        if (HttpContext.Current == null)
        {
          _resolver = value;
        }
        else
        {
          HttpContext.Current.Application["__UnityResolver"] = value;
        }
      }
    }

    private static IUnityResolver _resolver;
    #endregion
  }
}

Usage of this class is UnityFactory.Resolve<IMyType>(). And presto, you have got a reference to your implementation class. That’s all there is. Except for some configuration, of course ;-).

Another feature of this class is that it looks for a config setting “UnityResolver”. If that is present, it tries to load that class for a resolver in stead of the default UnityResolver. For instance, you can subclass UnityResolver, override the default constructor and define your interface-to-implementation mapping in code. Now this may look strange, because what is the point of decoupling classes and then make the mappings in code again? Well, for a scenario in which you want to use Unity for unit testing with mockups, this makes sense – when you want to deliver your production application without the necessity for a (possible very large) unity mapping section in your configuration file. If you want to register objects from code, you can do it for instance like this in the constructor of your UnityResolver override:

Container.RegisterType(
 Type.GetType("SomeNamespace.IMyInterface,SomeNamespace", true),
 Type.GetType("SomeOtherNamespace.MyImplementation,SomeOtherNamespace", true));

where "SomeNamespace" and "SomeOtherNamespace" after the comma are assembly names. If you use this construct, because it looks nice in NDepend and you don't have to make references, make sure your set the second parameter of Type.GetType, throwOnError, to true or it will fail silently and you might spend an uncomfortable long time debugging (I am talking from experience here). Personally I would go for typeof in stead of using Type.GetType but that is a matter of taste.

As a last feature, in unit testing scenarios, you can make another subclass of UnityResolver, call UnityFactory.SetResolver(myResolver) and the UnityFactory will store your resolver in a static variable (or the application context). Subsequently, all your classes will use the mapping logic defined in your own resolver, which makes a great starting point for mockup testing.

I hope this little sample will make decoupling, unit testing and mockup objects using Unity a bit more accessible.

17 October 2009

Using the Microsoft Ajax library to keep the javascript "this" context intact

This is not strictly .NET but more of a Javascript trick, but nevertheless, one that you might need. It is a simple trick, and actually requires much more text to decribe the problem than the actual solution ;-) Javascript supports the notion of object oriented programming, to an extent. There's plenty to find about that on the web and I don't care to repeat that. One of the more annoying things of Javascript is that it does support callbacks, but is quite careless about object context. This happens for instance when you use callbacks to process data coming back from calling WCF services. Suppose, for instance, I take my project in which I explain how to get data from WCF services in Javascript and rewrite the Javascript code as an object:
function CallBackProcessor()
{
  this.CallSingle = function()
  {
      dotnetbyexample.JSONDemoService.IJSONService.GetSingleObject(
      document.getElementById("tbId").value,
      document.getElementById("tbName").value,
      this.CallBackSingle);
  }
  this.CallBackSingle = function(WebServiceResult)
  {
      resultDiv = document.getElementById("result1");
      resultDiv.innerHTML = this.CreateMessage(WebServiceResult);
  }
  this.CreateMessage = function(WebServiceResult)
  {
    return( "You entered: id = " +
      WebServiceResult.Id + " name = " +
      WebServiceResult.Name);
  }            
}
var processor = new CallBackProcessor();
and then change the code of the button calling the service to call the processor object
<asp:Button ID="btnSelect" runat="server" Text="SingleSelect" 
   UseSubmitBehavior="False"
   OnClientClick="processor.CallSingle(); return false;" />
I will get the notorious "Object doesn't support this property or method" error. Why? Because I try to call the method "CreateMessage" from the "CallBackSingle": the context of "this" is no longer that of "processor", but of whatever is calling the callback. You can find this out by placing a breakpoint before the call to CreateMessage and then view the properties of "this". The logic behind this behaviour defies my imagination, but the solution is actually pretty simple: use Function.createDelegate to set up the callback in stead of calling it directly
this.CallSingle = function()
{
    dotnetbyexample.JSONDemoService.IJSONService.GetSingleObject(
    document.getElementById("tbId").value,
    document.getElementById("tbName").value,
    Function.createDelegate(this, this.CallBackSingle));
}
And that's all there is to it. The "this" context stays intact, thanks to the Microsoft Ajax library, that you already included automatically by placing a ScriptManager on your page.

25 August 2009

Yet another way to determine root paths in ASP.NET

How many times I have tried to find the root path of an ASP.NET page or a handler (ASHX) in order to call another URL I can hardly count. When working with WMS and WFS services and connected documents - when you call all kind of weird 'services' - it's something that needs to be done often. I decided to put a few in what seems to become my trade mark - extension methods. I created the following extensions to HttpContext
using System;
using System.Web;

namespace LocalJoost.Utilities.Web
{
  public static class HttpContextExtensions
  {
    public static string FullRootPath( this HttpContext context )
    {
      return context.Request.Url.AbsoluteUri.Split(
        new[] { context.Request.Url.AbsolutePath },
        StringSplitOptions.RemoveEmptyEntries)[0];
    }

    public static string FullApplicationPath(this HttpContext context)
    {
      return string.Concat(context.FullRootPath(), 
        context.Request.ApplicationPath);
    }
  }
}
In the Page_Load of an aspx page you can, for instance, use the methods as described below:
var r = Context.FullRootPath();
var a = Context.FullApplicationPath();
r will contain something like "http://localhost:3974" and a "http://localhost:3974/YourTestSite". Maybe there are simpler ways, but these work very well for me.

21 August 2009

Azure Tables and DateTime: some limitations

A nice thing I ran into yesterday: if you have a TableStorageEntity child class containing a DateTime property, you have two thing to remember:
  • You cannot use DateTime.Now, just should use DateTime.UtcNow when defining "now"
  • Make sure your DateTime does default to TableStorageConstants.MinSupportedDateTime (and not the standard DateTime.MinValue)
I had a class like this
using System;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace LocalJoost.CloudMapper.Data.MapBuild
{
  public class Job : TableStorageEntity
  {
    #region Properties
    public string JobId { get; set; }
    public string MapName { get; set; }

    public DateTime QueuedAt { get; set; }
    public DateTime StartedAt { get; set; }
    public DateTime FinishedAt { get; set; }
    #endregion

    public Job()
    {
      QueuedAt = DateTime.Now;
    }

    public override string PartitionKey
    {
      get{return MapName;}
      set{}
    }

    public override string RowKey
    {
      get{return JobId;}
      set
      { }
    }
  }
}
and I simply could not store it. "There was an error processing the request". Yeah. I was able to find out the restrictions mentioned above, changed the class to
using System;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace LocalJoost.CloudMapper.Data.MapBuild
{
  public class Job : TableStorageEntity
  {
    #region Properties
    public string JobId { get; set; }
    public string MapName { get; set; }

    public DateTime QueuedAt { get; set; }
    public DateTime StartedAt { get; set; }
    public DateTime FinishedAt { get; set; }
    #endregion

    public Job()
    {
      QueuedAt = DateTime.UtcNow;
      StartedAt = TableStorageConstants.MinSupportedDateTime;
      FinishedAt = TableStorageConstants.MinSupportedDateTime;
    }

    public override string PartitionKey
    {
      get{return MapName;}
      set{}
    }

    public override string RowKey
    {
      get{return JobId;}
      set
      { }
    }
  }
}
and then it worked. Thanks to Steve Marx for pointing me to the TableStorageConstants on twitter live while I was debugging

15 August 2009

Using extension methods to serialize objects to XML and compress the result - and deserialize again

Elaborating upon the string extension methods I created for compressing and decompressing strings to and from a byte array, it turned out fairly easy to create another set of compress / decompress methods to serialize any type of object to and from a byte array containing compressed XML. I once again took the StringZipExtensions class and added the following methods to compress any old object to a byte array:
/// <summary>
/// XmlSerializes the object to a compressed byte array
/// using the specified encoding.
/// </summary>
/// <param name="objectToCompress">The object to compress.</param>
/// <param name="encoding">The encoding.</param>
/// <returns>bytes array with compressed serialized object</returns>
public static byte[] Compress(this object objectToCompress,
  Encoding encoding)
{
  var xmlSerializer = new XmlSerializer(objectToCompress.GetType());
  using (var stringWriter = new StringWriter())
  {
    xmlSerializer.Serialize(stringWriter, objectToCompress);
    return stringWriter.ToString().Compress(encoding);
  }
}

/// <summary>
/// XmlSerializes the object to a compressed byte array using default
/// UTF8 encoding.
/// </summary>
/// <param name="objectToCompress">The object to compress.</param>
/// <returns>bytes array with compressed serialized object</returns>
public static byte[] Compress(this object objectToCompress)
{
  return Compress(objectToCompress, new UTF8Encoding());
}
Here, once again, an overload using a default UTF8 encoding and a method which uses your own encoding to do the heavy lifting. Then, the methods for decompressing, which - in all modesty - are a rather neat usage of generics, I think:
/// <summary>
/// Decompress an array of bytes into an object via Xml Deserialization
/// using the specified encoding
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="compressedObject">The compressed string.</param>
/// <param name="encoding">The encoding.</param>
/// <returns>Decompressed object</returns>
public static T DecompressToObject<T>(this byte[] compressedObject,
  Encoding encoding)
{
  var xmlSer = new XmlSerializer(typeof(T));
  return (T)xmlSer.Deserialize(new StringReader(
    compressedObject.DecompressToString(encoding)));
}

/// <summary>
/// Decompress an array of bytes into an object via Xml Deserialization
/// using default UTF8 encoding
/// </summary>
/// <param name="compressedObject">The compressed string.</param>
/// <returns>Decompressed object</returns>
public static T DecompressToObject<T>(this byte[] compressedObject )
{
  return DecompressToObject<T>(compressedObject, new UTF8Encoding());
}
Then you can take something like this hugely complex ;-) object Person
public class Person
{
  public int Id { get; set; }
  public string Name { get; set; }
  public DateTime Birthday { get; set; }

  public override bool Equals(object obj)
  {
    var toCompare = obj as Person;
    if( toCompare != null )
    {
      return
        Name.Equals(toCompare.Name) &&
        Id.Equals(toCompare.Id) &&
        Birthday.Equals(toCompare.Birthday);

    }
    return base.Equals(obj);
  }
}
and serialize/compress and decompress/deserialize it like this:
[Test]
public void CompressObjectTest()
{
  var baseLineObject = new Person
  {
  Id = 99, 
  Name = "Tom", 
  Birthday = new DateTime(1969, 06, 03)
  };
  var compressed = baseLineObject.Compress();
  var testObject = compressed.DecompressToObject<Person>();
  Assert.AreEqual(testObject, baseLineObject);
}
Code downloadable here

12 August 2009

Using extension methods to compress and decompress strings

After some rightful comments by Jarno Peschier I decided to once again look into my blog post about putting compressed object on the Azure message queue and came up with the following set of extensions methods that allow you to compress a string via gzip into a byte array, and unzip a byte array containing a compressed string to a regular string again:
using System.IO;
using System.IO.Compression;
using System.Text;

namespace LocalJoost.Utilities.Compression
{
 public static class StringZipExtensions
 {
  /// <summary>
  /// Compresses the specified string a byte array using the specified
  /// encoding.
  /// </summary>
  /// <param name="stringToCompress">The string to compress.</param>
  /// <param name="encoding">The encoding.</param>
  /// <returns>bytes array with compressed string</returns>
  public static byte[] Compress(
   this string stringToCompress, 
    Encoding encoding )
   {
    var stringAsBytes = encoding.GetBytes(stringToCompress);
    using (var memoryStream = new MemoryStream())
    {
     using (var zipStream = new GZipStream(memoryStream,
      CompressionMode.Compress))
     {
      zipStream.Write(stringAsBytes, 0, stringAsBytes.Length);
      zipStream.Close();
      return (memoryStream.ToArray());
     }
    }
   }

   /// <summary>
   /// Compresses the specified string a byte array using default
   /// UTF8 encoding.
   /// </summary>
   /// <param name="stringToCompress">The string to compress.</param>
   /// <returns>bytes array with compressed string</returns>
  public static byte[] Compress( this string stringToCompress )
  {
   return Compress(stringToCompress, new UTF8Encoding());
  }

  /// <summary>
  /// Decompress an array of bytes to a string using the specified
  /// encoding
  /// </summary>
  /// <param name="compressedString">The compressed string.</param>
  /// <param name="encoding">The encoding.</param>
  /// <returns>Decompressed string</returns>
  public static string DecompressToString(
   this byte[] compressedString, 
   Encoding encoding)
  {
   const int bufferSize = 1024;
   using (var memoryStream = new MemoryStream(compressedString))
   {
    using (var zipStream = new GZipStream(memoryStream,
     CompressionMode.Decompress))
    {
     // Memory stream for storing the decompressed bytes
     using (var outStream = new MemoryStream())
     {
      var buffer = new byte[bufferSize];
      var totalBytes = 0;
      int readBytes;
      while ((readBytes = zipStream.Read(buffer,0, bufferSize)) > 0)
      {
       outStream.Write(buffer, 0, readBytes);
       totalBytes += readBytes;
      }
      return encoding.GetString(
       outStream.GetBuffer(),0, totalBytes);     
     }
    }
   }
  }

  /// <summary>
  /// Decompress an array of bytes to a string using default
  /// UTF8 encoding.
  /// </summary>
  /// <param name="compressedString">The compressed string.</param>
  /// <returns>Decompressed string</returns>
  public static string DecompressToString(this byte[] compressedString )
  {
   return DecompressToString(compressedString, new UTF8Encoding());
  }
 }
}
You can now quite simply do something like
using LocalJoost.Utilities.Compression;
using NUnit.Framework;

namespace LocalJoost.Utilities.Test
{
  [TestFixture]
  public class TestCompress
  {
    [Test]
    public void TestZipUnzip()
    {
      const string test = "The quick brown fox jumps over the lazy dog";
      var compressed = test.Compress();
      var uncompressed = compressed.DecompressToString();
      Assert.AreEqual(test, uncompressed);
    }
  }
}
and that will work, of course ;-) Both the Compress and the DecompressToString methods use UTF8 as default encoding as Jarno suggested by Live Messenger, but both methods also sport an overload which allow you to provide an encoding yourself. This will support almost any encoding - provided of course you use the same encoding to compress and decompress. So, this can even be used to compress strings containing Klingon messages - I hope this will earn me a fond majQa' from Jarno ;-) Code downloadable here

05 August 2009

Putting multiple elements in a Silverlight 3 DataForm DataField while retaining auto Label and Description generation

Summary: if you want to use a DataForm, want to put multiple controls in one DataField, and still want Silverlight 3 to generate Label and Description from the attributes applied to the properties you bind, you need to
  • Name your DataField
  • Add an ItemsControl as wrapping element inside the DataField
  • Bind the property to the ItemsControl
  • Bind the property of your controls inside the ItemsControl to the ItemsControls' DataContext
Bear with me: I started out with the Mike Taulty video and made a nice little business class like this:
using System;
using System.ComponentModel.DataAnnotations;

namespace DataFormDemo
{
  public class Coordinate
  {   
    private double _xmin;
    public double XMin { get { return _xmin; } }

    private double _ymin;
    public double YMin { get { return _ymin; } }

    private double _xmax;
    public double XMax { get { return _xmax; } }

    private double _ymax;
    public double YMax { get { return _ymax; } }

    public Coordinate(double x, double y,
                      double xLow, double yLow,
                      double xHigh, double yHigh)
    {
      _x = x;
      _y = y;
      _xmax =  xHigh;
      _ymax =  yHigh;
      _xmin =  xLow;
      _ymin =  yLow;
    }

    private double _x;
    [Display(Name = "X Coordinate:",
      Description = "The X coordinate of the point")]
    public double X
    {
      get
      {
        return _x;
      }
      set
      {
        ValidateValue(value, XMin, XMax);
        _x = value;
      }
    }

    private double _y;
    [Display(Name = "Y Coordinate:",
      Description = "The Y coordinate of the point")]
    public double Y
    {
      get
      {
        return _y;
      }
      set
      {
        ValidateValue(value, YMin, YMax);
        _y = value;
      }
    }
   
    private void ValidateValue(double value, 
     double minValue, double maxValue)
    {
      if (value < minValue || value > maxValue)
      {
        throw new ArgumentException(
            string.Format("Valid value {0} - {1}", minValue,maxValue));
      }
    }
  }
}
and just like Mike did, I added some labels and descriptions (in red) to get a nicer looking form. The purpose of this class is that a user can enter an X and Y value that fall in a range, which is validated. All parameters are set by the constructor. Then I made some minimal XAML
<UserControl x:Class="DataFormDemo.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:dataFormToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit"
  mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
 <Grid x:Name="LayoutRoot">
    <dataFormToolkit:DataForm x:Name="MyForm"
    HorizontalAlignment="Center" VerticalAlignment="Top">
    </dataFormToolkit:DataForm>
  </Grid>
</UserControl>
Then I bound a Coordinate in the constructor
public MainPage()
{
  InitializeComponent();
  MyForm.CurrentItem = new Coordinate(
      150000, 450000, 
      0, 300000, 
      300000, 600000);
}
and got the screen left, with a wee bit more than I bargained for. I was planning to customize the default dataform layout anyway, so I changed the DataForm to:

 

 

 

 

<dataFormToolkit:DataForm x:Name="MyForm" 
  HorizontalAlignment="Center" VerticalAlignment="Top">
  <dataFormToolkit:DataForm.EditTemplate>
    <DataTemplate>
      <StackPanel>
        <dataFormToolkit:DataField >
          <TextBox Text="{Binding X,Mode=TwoWay}"/>
        </dataFormToolkit:DataField>
        <dataFormToolkit:DataField >
          <TextBox Text="{Binding Y,Mode=TwoWay}"/>
        </dataFormToolkit:DataField>
      </StackPanel>
    </DataTemplate>
  </dataFormToolkit:DataForm.EditTemplate>
</dataFormToolkit:DataForm>

That worked out nicely, but wanting to make this a little more slickey and user friendly I introduced a slider connected to the text box with the new Silverlight 3 component-to-component binding:

 

<dataFormToolkit:DataForm x:Name="MyForm" 
  HorizontalAlignment="Center" VerticalAlignment="Top">
  <dataFormToolkit:DataForm.EditTemplate>
    <DataTemplate>
      <StackPanel>
        <dataFormToolkit:DataField >
          <StackPanel>
            <TextBox x:Name="tbX" Text="{Binding X, Mode=TwoWay}"/>
            <Slider Maximum="{Binding XMax}" Minimum="{Binding XMin}"
              Value="{Binding Text, ElementName=tbX, Mode=TwoWay}"/>
          </StackPanel>
        </dataFormToolkit:DataField>
        <dataFormToolkit:DataField >
          <StackPanel>
            <TextBox x:Name="tbY" Text="{Binding Y, Mode=TwoWay}"/>
            <Slider Maximum="{Binding YMax}" Minimum="{Binding YMin}"
              Value="{Binding Text, ElementName=tbY, Mode=TwoWay}"/>
          </StackPanel>
        </dataFormToolkit:DataField>
      </StackPanel>
    </DataTemplate>
  </dataFormToolkit:DataForm.EditTemplate>
</dataFormToolkit:DataForm>
That works swell, but where are my label and my description? Turns out that the Silverlight 3 DataForm shows label and description if and only if there is one element inside that DataField to which the property is bound. You use a StackPanel or something, and the DataForm seems to loose track of where to put which label and which description, so it does not show them at all. After some experimenting around, I found the following work around using the ItemsControl:
<dataFormToolkit:DataForm x:Name="MyForm" 
  HorizontalAlignment="Center" VerticalAlignment="Top">
  <dataFormToolkit:DataForm.EditTemplate>
    <DataTemplate>
      <StackPanel>
        <dataFormToolkit:DataField>
          <ItemsControl x:Name="icX" DataContext="{Binding X,Mode=TwoWay}">
            <StackPanel>
              <TextBox x:Name="tbX" 
               Text="{Binding DataContext, ElementName=icX, Mode=TwoWay}"/>
              <Slider Maximum="{Binding XMax}" Minimum="{Binding XMin}"
               Value="{Binding Text, ElementName=tbX, Mode=TwoWay}"/>
            </StackPanel>
          </ItemsControl>
        </dataFormToolkit:DataField>
        <dataFormToolkit:DataField >
          <ItemsControl x:Name="icY" DataContext="{Binding Y,Mode=TwoWay}">
            <StackPanel>
              <TextBox x:Name="tbY" 
               Text="{Binding DataContext, ElementName=icY, Mode=TwoWay}"/>
              <Slider Maximum="{Binding YMax}" Minimum="{Binding YMin}"
                Value="{Binding Text, ElementName=tbY, Mode=TwoWay}"/>
            </StackPanel>
          </ItemsControl>
        </dataFormToolkit:DataField>
      </StackPanel>
    </DataTemplate>
  </dataFormToolkit:DataForm.EditTemplate>
</dataFormToolkit:DataForm>
But now my sliders do not work anymore: they are locked in the right position. This is logical, because the DataContext of anything inside the ItemsControl is now no longer the Coordinate object, but its X or Y property. So XMin, XMax, YMin and YMax are now unknown (and thus zero). This, too, can be solved by naming your DataFields, using the Path binding syntax and then once again using control-to-control binding:
<dataFormToolkit:DataForm x:Name="MyForm" 
  HorizontalAlignment="Center" VerticalAlignment="Top">
  <dataFormToolkit:DataForm.EditTemplate>
    <DataTemplate>
      <StackPanel>
        <dataFormToolkit:DataField x:Name="dfX">
          <ItemsControl x:Name="icX" DataContext="{Binding X,Mode=TwoWay}">
            <StackPanel>
              <TextBox x:Name="tbX" 
               Text="{Binding DataContext, ElementName=icX, Mode=TwoWay}"/>
              <Slider 
               Maximum="{Binding Path=DataContext.XMax,ElementName=dfX}" 
               Minimum="{Binding Path=DataContext.XMin,ElementName=dfX}"
               Value="{Binding Text, ElementName=tbX, Mode=TwoWay}"/>
            </StackPanel>
          </ItemsControl>
        </dataFormToolkit:DataField>
        <dataFormToolkit:DataField x:Name="dfY">
          <ItemsControl x:Name="icY" DataContext="{Binding Y,Mode=TwoWay}">
            <StackPanel>
              <TextBox x:Name="tbY" 
               Text="{Binding DataContext, ElementName=icY, Mode=TwoWay}"/>
             <Slider 
               Maximum="{Binding Path=DataContext.YMax,ElementName=dfY}"
               Minimum="{Binding Path=DataContext.YMin,ElementName=dfY}"
               Value="{Binding Text, ElementName=tbY, Mode=TwoWay}"/>
             </StackPanel>
          </ItemsControl>
        </dataFormToolkit:DataField>
      </StackPanel>
    </DataTemplate>
  </dataFormToolkit:DataForm.EditTemplate>
</dataFormToolkit:DataForm>
Which gives the resulting - and fully functional - screen to the right. A prime example of something that started out so simple, and then became just a teeny bit more complex ;-) So, using the ItemsControl and control-to-control binding makes the DataForm retain its ability to generate Labels and Descriptions automatically. Which shows that Silverlight 3 databinding is about as flexible as a rubber band. One note of caution: when binding Maximum, Minimum and Value to a slider, this must be done in exactly the right order, as shown here. I blogged about this earlier this week.

01 August 2009

Bind Silverlight 3 Slider Value, Minimum and Maximum attributes in EXACTLY the right order!

Today I want to share a piece of very hard won knowlegde with you. That piece of knowlegde is: if you want to use a Silverlight Slider, and you want to get the Value, Minimum and Maximum attributes from binding, you need to bind them in exactly the right order. That order is:
  • Maximum
  • Minimum
  • Value
or else it simply won't work. It took me the better part of a sunny saturday afternoon to figure that out. To clarify things, I will show what I was doing when I ran into this. I have a simple business class that looks like this:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;

namespace LocalJoost.CloudMapper.Ui
{
  public class TileRequestParms 
  {
    private double _xmin;
    public double XMin { get { return _xmin; } }

    private double _ymin;
    public double YMin { get { return _ymin; } }

    private double _xmax;
    public double XMax { get { return _xmax; } }

    private double _ymax;
    public double YMax { get { return _ymax; } }

    private double _xLow;
    [Display(Name = "X lower left:")]
    public double XLow
    {
      get
      {
        return _xLow;
      }
      set
      {
        ValidateValue(value, XMin, XHigh);
        _xLow = value;
      }
    }

    private double _yLow;
    [Display(Name = "Y lower left:")]
    public double YLow
    {
      get
      {
        return _yLow;
      }
      set
      {
        ValidateValue(value, YMin, YHigh);
        _yLow = value;
      }
    }

    private double _xHigh;
    [Display(Name = "X upper right:")]
    public double XHigh
    {
      get
      {
        return _xHigh;
      }
      set
      {
        ValidateValue(value, XLow, XMax);
        _xHigh = value;

      }
    }

    private double _yHigh;
    [Display(Name = "Y upper right:")]
    public double YHigh
    {
      get
      {
        return _yHigh;
      }
      set
      {
        ValidateValue(value, YLow, YMax);
        _yHigh = value;
      }
    }

    public TileRequestParms(double xLow, double yLow, 
        double xHigh, double yHigh)
    {
      _xmax = _xHigh = xHigh;
      _ymax = _yHigh = yHigh;
      _xmin = _xLow = xLow;
      _ymin = _yLow = yLow;
    }

    private void ValidateValue(double value, 
      double minValue, double maxValue)
    {
      if (value < minValue || value > maxValue)
      {
        throw new ArgumentException(
           string.Format("Valid value {0} - {1}", minValue,
                             maxValue));
      }
    }
  }
}
Its purpose is very simple: the user can input two coordinates that are inside a rectangle defined by the max and min values in the constructor. In addition, XMax can never be smaller than XMin, and YMax never smaller than YMin. Now I wanted the user to be able to input the value both by a text box and a slider. And I decided to use the new Silverlight 3 DataForm and control to control binding:
<dataFormToolkit:DataField Grid.Row="0" Grid.Column="0" 
  Label="X lower left: ">
    <StackPanel>
        <TextBox x:Name ="tbXLow" Text="{Binding XLow,Mode=TwoWay}" />
        <Slider x:Name="slXLow" 
         Value="{Binding Text,ElementName=tbXLow, Mode=TwoWay}" 
         Minimum="{Binding XMin}" Maximum="{Binding XMax}"/>
    </StackPanel>
</dataFormToolkit:DataField>
<dataFormToolkit:DataField Grid.Row="0" Grid.Column="1" 
      Label="Y lower left: ">
    <StackPanel>
        <TextBox x:Name ="tbYLow" Text="{Binding YLow,Mode=TwoWay}" />
        <Slider x:Name="slYLow" 
         Value="{Binding Text,ElementName=tbYLow, Mode=TwoWay}" 
         Minimum="{Binding YMin}" Maximum="{Binding YMax}"/>
    </StackPanel>
</dataFormToolkit:DataField>
<dataFormToolkit:DataField Grid.Row="1" Grid.Column="0" 
    Label="X upper right: ">
    <StackPanel>
        <TextBox x:Name ="tbXHigh" Text="{Binding XHigh,Mode=TwoWay}" />
        <Slider x:Name="slXHigh" 
         Value="{Binding Text,ElementName=tbXHigh, Mode=TwoWay}" 
         Minimum="{Binding XMin}" Maximum="{Binding XMax}"/>
    </StackPanel>
</dataFormToolkit:DataField>
<dataFormToolkit:DataField Grid.Row="1" Grid.Column="1" 
  Label="Y upper right: ">
    <StackPanel>
        <TextBox x:Name ="tbYHigh" Text="{Binding YHigh,Mode=TwoWay}" />
        <Slider x:Name="slYHigh" 
         Value="{Binding Text,ElementName=tbYHigh, Mode=TwoWay}" 
         Minimum="{Binding YMin}" Maximum="{Binding YMax}"/>
    </StackPanel>
</dataFormToolkit:DataField>
Now the annoying thing is: is worked for X, but not for Y. The sliders stayed put and refused to work. After a considerable time of debugging and I noticed one thing: it worked when I put hard coded values for Minimum and Maximum, but not if I used binded values. For X, I was using a minimum 0 and a maximum of 300000. But I was using a minimum of 300000 for Y, and 600000 for a maximum (Yes, that's the RD coordinate system, for my Dutch readers). With a bit of debugging I was able to find out the both minimum and maximum value of the first slider where set to 300000, as was it's value. So I reasoned: maybe, by setting the value, the maximum value is set already (because the minimum is already 0) and it does 'not like' to get a max value twice. Or something among that lines. So what if I first set the maximum, then the minimum, and only then the value? So I changed the XAML for the first slider
<dataFormToolkit:DataField Grid.Row="1" Grid.Column="0" 
  Label="X upper right: ">
    <StackPanel>
        <TextBox x:Name ="tbXHigh" Text="{Binding XHigh,Mode=TwoWay}" />
        <Slider Maximum="{Binding XMax}" Minimum="{Binding XMin}"
         x:Name="slXHigh" 
         Value="{Binding Text,ElementName=tbXHigh, Mode=TwoWay}"/>
    </StackPanel>
</dataFormToolkit:DataField>
And it worked. It's these little things that make a developer's life interesting, isn't it? Although, in my case, it also gave this here developer a pretty potent headache.

24 July 2009

Storing objects as compressed messages in the Windows Azure Queue

For my current private R&D project I wanted to store 'task set' objects (in code samples below as shown type "Request") on the Windows Azure Queue. To prevent serialization issues I opted for XML serialization, like this:
private void Enqueue(Request tr)
{
  var queueStorage = QueueStorage.Create(
  StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration());
  var queue = queueStorage.GetQueue("MyQueue");
  if (!queue.DoesQueueExist())
  {
    queue.CreateQueue();
  }

  var xmlSerializer = new XmlSerializer(tr.GetType());
  using (var stringWriter = new StringWriter())
  {
    xmlSerializer.Serialize(stringWriter, tr);
    queue.PutMessage(new Message(stringWriter.ToString()));
  }
}
I would let the worker role deserialize the Request object and then execute it. It annoyed me to no end to learn that the Azure Queue limits message sizes to 8192 bytes. I could have redesigned my task sets to smaller units, but that would hurt the efficiency of the process I had in mind. Based upon the StringZipExtensions class I blogged about that can serialize and deserialize any old object to and from compressed XML (which you can download here) I created the following extension methods, which enable you to store objects as a GZip compressed set of bytes on the Azure queue and retrieve them again:
using LocalJoost.Utilities.Compression;
using Microsoft.Samples.ServiceHosting.StorageClient;

namespace LocalJoost.Utilities.Azure
{
  public static class MessageQueueExtensions
  {
    /// <summary>
    /// Decompresses the specified queue message.
    /// </summary>
    /// <param name="message">The message.</param>
    /// <returns></returns>
    public static string Decompress(this Message message)
    {
      return message != null ?
       message.ContentAsBytes().DecompressToString() : null;
    }

    /// <summary>
    /// Decompresses the specified queue message.
    /// to an object
    /// </summary>
    /// <param name="message">The message.</param>
    /// <returns></returns>
    public static T Decompress <T>(this Message message) where T:class
    {
      return message != null ?
       message.ContentAsBytes().DecompressToObject<T>() : null;
    }
  }
}
Adhering to my first code sample, you can now simply put an object to the queue like this
private void Enqueue(Request tr)
{
  var queueStorage = QueueStorage.Create(
    StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration());
  var queue = queueStorage.GetQueue("MyQueue");
  if (!queue.DoesQueueExist())
  {
    queue.CreateQueue();
  }

  queue.PutCompressedObject(tr);
}
and let the worker role use the Decompress extension method on the Message itself:
var queueStorage =
  QueueStorage.Create(
  StorageAccountInfo.GetDefaultQueueStorageAccountFromConfiguration());
var queue = queueStorage.GetQueue("MyQueue");
if (queue.DoesQueueExist())
{
  var message = queue.GetMessage(600);
  if (message != null)
  {
    var request = message.Decompress<Request>();
    request.Execute();
    queue.DeleteMessage(message);
  }
}
And there you go. It is as simple as that. Although the Window Azure Queue message queue size still is limited to 8192, the amount of data that fits in that space is increased dramatically.

18 July 2009

Calling a service relative to the Silverlight XAP (improved)

In my previous post I showed a way to call a service defined with a full path, as created by the designer, relative to that of the location of your XAP, by means of an extension to a user control. I developed that during a training and while blogging it I alreadly realized that there was room for improvement. And here it is:
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Windows;

namespace LocalJoost.Utilities.Silverlight
{
  public static class ServiceEndpointExtension
  {
    public static void MakeRelative(
      this ServiceEndpoint endpoint)
    {
      var clientbinLocation = 
        Application.Current.Host.Source.ToString().Substring(0,
        Application.Current.Host.Source.ToString().LastIndexOf("/"));
      var rootLocation = 
        clientbinLocation.Substring(0, 
        clientbinLocation.LastIndexOf("/"));
      endpoint.Address = new EndpointAddress(
        new Uri(string.Concat(rootLocation, 
          endpoint.Address.Uri.AbsolutePath)));
    }
  }
}
In stead of extending the user control I now extend the ServiceEndpoint. If you now want to call a service that is sitting in the root of your web application that is hosting you can call it like this:
var client = new CloudMapperDataServiceClient();
client.Endpoint.Address.MakeRelative();
Substitute "CloudMapperDataServiceClient" by your own client proxy class and you are go for launch (Sorry, currently listening to wechoosethemoon.org ;-)

15 July 2009

Calling a service relative to the Silverlight XAP

This post is deprecated and left here for link reference only. See this post or a better way to do this. A small tidbit that I developed when I was following a training by Dennis van der Stelt of Class-A. One of the assigments was to consume a service and display data. The lab contained a string with a hard coded path. I thought of the following, IMHO much cleaner solution. I also discovered that WCF services are defined in a ServiceReferences.ClientConfig that contains a full path to the service. That is not nice on deployment time. This may have been caused by the fact I hosted the Silverlight App in an Azure project, I am not sure yet. But anyhow, I made an extension method to the Silverlight System.Windows.Controls.Control like this
using System;
using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;

namespace LocalJoost.Utilities.Silverlight
{
  public static class UserControlExtensions
  {
    public static EndpointAddress GetRelativeEndpointAdress(
      this UserControl control, string path)
    {
      var clientbinLocation = 
          Application.Current.Host.Source.ToString().Substring(0,
          Application.Current.Host.Source.ToString().LastIndexOf("/"));
      return new EndpointAddress(new Uri(string.Format("{0}/{1}",
        clientbinLocation.Substring(0,
        clientbinLocation.LastIndexOf("/")), path)));
    }
  }
}
If you now want to call a service that is sitting in the root of your web application that is hosting you can call it like this:
var client = new CloudMapperDataServiceClient();
client.Endpoint.Address = 
 this.GetRelativeEndpointAdress("CloudMapperDataService.svc");
Substitute "CloudMapperDataServiceClient" by your own client proxy class and "CloudMapperDataService.svc" by your own svc and you are ready to roll. Seeing this again while I blog it I think it might be even better to get the name of the svc from the original Endpoint.Address setting. Well, that's something for later

13 July 2009

Adding a Silverlight (3) gui to an existing Azure webrole

This is extremely easy. Steve Marx points out in a comment on this blog post:
To add a Silverlight project to a Web Role project, simply right-click your project file in the solution explorer and select "Properties". In the Project properties view, the bottom-most tab on the left is "Silverlight Applications" - select this, and there is an "Add..." button that allows you to add (and configure) a new or existing Silverlight app to your web role.
And that is really all there is to it. I've tried this with a Silverlight 3 project but since the comment is from december 2008 I have every reason to believe this works for Silverlight 2.0 projects as well. Not that I can think of any reason to stick with 2.0... but that's another story ;-)

07 July 2009

Using the "global" prefix to prevent namespace clashes

I was running into a snag into the situation in which the compiler was accidentally took my local namespace when I wanted it to use the root namespace of CSLA. I had defined a dll "LocalJoost.Utilities.Csla" with the following code:
using Csla;
using Csla.Validation;

namespace LocalJoost.Utilities.Csla
{
  public static class LocalJoostCommonRules
  {
    public static bool NotNull(object target, RuleArgs args)
    {
      args.Description = string.Format("{0} is required", 
        args.PropertyName);
      var value = global::Csla.Utilities.CallByName(
       target, args.PropertyName, CallType.Get);
      return value != null;

    }
  }
}
and although I had referenced the Csla.dll nicely, it did not compile. The compiler errorred out telling me that "The type or namespace name 'Utilities' does not exist in the namespace 'LocalJoost.Utilities.Csla' (are you missing an assembly reference?)" Well of course does the namespace "LocalJoost.Utilities.Csla.Utilities" not exist: I wanted it to use "Csla.Utilities". I had created myself a nice namespace clash. Or kludge, whatever you want to call this. In stead of searching from the root of the namespace, the compiler started to search relatively from my namespace. Turns out this is very easy to fix: there is a .NET directive "global" that is the .NET equivalent of starting an URL with a "/". I changed my code to
using Csla;
using Csla.Validation;

namespace LocalJoost.Utilities.Csla
{
  public static class LocalJoostCommonRules
  {
    public static bool NotNull(object target, RuleArgs args)
    {
      args.Description = string.Format("{0} is required", 
        args.PropertyName);
      var value = global::Csla.Utilities.CallByName(
       target, args.PropertyName, CallType.Get);
      return value != null;
    }
  }
}
and the compiler was happy again. And so was I, incidently.

01 July 2009

Using PresentationCore in Azure requires full trust

Sometimes the answer is staring you in the face... I was trying to load an image from an URL in code. Imagine the code for that being something like this
var blobURL = "http://www.somewhere.com/image.jpg";
var multiTileImage = new BitmapImage(); 
multiTileImage.BeginInit(); 
multiTileImage.UriSource = new Uri(blobURL);
multiTileImage.CacheOption = BitmapCacheOption.None;
multiTileImage.EndInit();
This fails with an security expection, you get something like "Request for the permission of type 'System.Security.Permissions.MediaPermission failed in System.Windows.Media.Imaging.BitmapImage.EndInit" Dennis van der Stelt suggested that this may have to do something with full trust. And indeed it does. In your service definition file by default is defined
<WebRole name="WebRole" enableNativeCodeExecution="false">
I noticed that, I just failed to see the connection between "enableNativeCodeExecution" and "full trust". In fact, I still fail to see that connection ;-) but you just need to set the value for enableNativeCodeExecution in the appropriate tag to "true" and then PresentationCore classes - with apparently are not thrustworthy - can be used from Web- or Worker roles.

06 June 2009

Hosting a CGI program as a REST service on the Azure .NET Service Bus (allowing anonymous access)

The point of this posting is threefold: I want to show how you can make REST services on the .NET service bus, how you can allow anonymous access to these, and that anything that is accessible by an URL can be hosted on the .NET service bus. For my example I am going to host a WMS Service by UMN MapServer - which is in fact a CGI program - on the .NET Service bus, but you can host anything you want. I am going to assume that you have Visual Studio 2008, .NET 3.5 SP1, the Azure tools and toolkits CTP May 2009 installed, that you have access to the .NET Services portal and that you know how to create a solution for a .NET Service on that portal. Setting the stage Create a new solution with two projects: a console application and a WCF Service library. I have called my solution "CloudMapExample", the console app "CloudMapRunner" and the library "CloudMap.Contracts" Setup the console application Add references to "System.ServiceModel", "System.ServiceModel.Web" and the Service library you have just created. Add an app.config, and make sure it looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="WMSServices"
   type="System.Configuration.NameValueSectionHandler" />
  </configSections>
  <WMSServices>
    <add key="DemoSrv"
   value="http://localhost/MapServer/mapserv.exe?map=d:/MapServer/CONFIG/Demo.map"/>
  </WMSServices>
</configuration>
This of course requires you to have setup MapServer. Don't worry, you can also set a url to a HTML page or ASPX page running on your local machine mocking this behaviour. Setup the service library Right-click the CloudMap.Contracts project, select the "WCF Option" tab and unselect the checkbox before "Start WCF Service Host blah blah blah" to prevent the WCF host popping up every time you test your project. Then, delete App.config, IService1.cs and Service1.cs Finally, add references to "System.ServiceModel.Web" and "System.Configuration" Add the service contract Add to the service library an interface IWMSProxyService that looks like this:
using System.ServiceModel;
using System.ServiceModel.Web;
using System.IO;

namespace CloudMap.Contracts
{
  [ServiceContract]
  public interface IWMSProxyService
  {
    [OperationContract]
    [WebGet(UriTemplate = "WMS/{map}/*")]
    Stream WMSRequest(string map);
  }
}
Notice the WebGet attribute "UriTemplate". The asterisk is a wildcard that tells WCF that any url starting with this template is mapped to the WMSRequest method. A nifty trick, since the idea is that I can call the method like "http://host/baseurl/WMS/MyMap/?key1=value&key2=value. "MyMap" will automatically be populated into the "map" parameter of the method "WMSRequest". How the rest of the querystring will become available is shown in the service implementation. Add the service implementation class
using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.ServiceModel.Web;
using System.Configuration;
namespace CloudMap.Contracts
{
  public class WMSProxyService : IWMSProxyService
  {
    public Stream WMSRequest(string map)
    {
      Console.WriteLine("Proxy call!");
      var wms = GetWMSbyMap(map);
      return RelayUrl(string.Format("{0}{1}{2}",
                      wms,
                      (wms.Contains("?") ? "&" : "?"),
      WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters));     
    }

    private string GetWMSbyMap( string map )
    {
      var services = ConfigurationManager.GetSection("WMSServices")
               as NameValueCollection;
      return services != null ? services[map] : null;
    }

    private Stream RelayUrl(string urlToLoadFrom)
    {
      var webRequest = HttpWebRequest.Create(urlToLoadFrom) 
         as HttpWebRequest;
      // Important! Keeps the request from blocking after the first
      // time!
      webRequest.KeepAlive = false;
      webRequest.Credentials = CredentialCache.DefaultCredentials;
      using (var backendResponse = (HttpWebResponse)webRequest.GetResponse())
      {
        using (var receiveStream = backendResponse.GetResponseStream())
        {
          var ms = new MemoryStream();
          var response = WebOperationContext.Current.OutgoingResponse;
          // Copy headers      
          // Check if header contains a contenth-lenght since IE
          // goes bananas if this is missing
          bool contentLenghtFound = false;
          foreach (string header in backendResponse.Headers)
          {
            if (string.Compare(header, "CONTENT-LENGTH", true) == 0)
            {
              contentLenghtFound = true;
            }
            response.Headers.Add(header, backendResponse.Headers[header]);
          }
          // Copy contents      
          var buff = new byte[1024];
          var length = 0;
          int bytes;
          while ((bytes = receiveStream.Read(buff, 0, 1024)) > 0)
          {
            length += bytes;
            ms.Write(buff, 0, bytes);
          }
          // Add contentlength if it is missing
          if (!contentLenghtFound) response.ContentLength = length;
          // Set the stream to the start
          ms.Position = 0;
          return ms;
        }
      }
    }
  }
}
Now this may look a bit intimidating, but in fact it is just a little extension of my WCF proxy example described earlier in this blog. The 'extensions' are pretty simple: first of all the method "GetWMS" searches for a configuration section "WMSServices" in the App.config and then tries to retrieve the base url of the WMS defined by the value of "map". It then concatenates the rest of querystring, which is accessible by the not quite self-evident statement "WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters", to the url found in the config section and calls it, passing the parameters of the query string to it. Anyway, don't worry too much about it. This is the more or less generic proxy. The point is getting it to run and then hosting it on the .NET service bus. Add code code to host the service Open the "Program.cs" file in the Console application, and make it look like this:
using System;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Web;
using CloudMap.Contracts;

namespace CloudMapRunner
{
  class Program
  {
    static void Main(string[] args)
    {
      var serviceType = typeof(WMSProxyService);
      var _host = new WebServiceHost(serviceType);
      _host.Open();

      // Code to show what's running
      Console.WriteLine("Number of base addresses : {0}",
        _host.BaseAddresses.Count);
      foreach (var uri in _host.BaseAddresses)
      {
        Console.WriteLine("\t{0}", uri);
      }
      Console.WriteLine();
      Console.WriteLine("Number of dispatchers listening : {0}",
        _host.ChannelDispatchers.Count);
      foreach (ChannelDispatcher dispatcher in 
               _host.ChannelDispatchers)
      {
        Console.WriteLine("\t{0}, {1}",
          dispatcher.Listener.Uri,
          dispatcher.BindingName);
      }

      // Exit when user presser ENTER
      Console.ReadLine();
    }
  }
}
This basically just starts up the service. Everything between the comments "// Code to show what's running" and "// Exit when user presser ENTER" just displays some information about the service, using code I - er - borrowed from Dennis van der Stelt when I attend a WCF training by him at Class-A some two years ago. Notice I am using a WebServiceHost in stead of the normal ServiceHost. As long as you run your code locally, ServiceHost will do as well, but not when you want to harness your service in the cloud. But this is the only thing you need to take care of in code to make sure you can painlessly move from a locally hosted WCF service to the Azure .NET service bus - the rest is just configuration. Adding basic WCF configuration To get the service to work a REST service, you need to add the following configuration to the app.config of your console application:
<system.serviceModel>
  <services>
    <service name="CloudMap.Contracts.WMSProxyService" >
      <endpoint address="" binding="webHttpBinding"
        behaviorConfiguration="WebHttpBehavior"
        contract="CloudMap.Contracts.IWMSProxyService"
        bindingNamespace="http://dotnetbyexample.blogspot.com">
      </endpoint>
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8002/CloudMapper" />
        </baseAddresses>
      </host>
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="WebHttpBehavior">
        <webHttp />
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
The usage of [WebGet] and the webHttp tag are covered in a previous post so I'm skipping the details on that. Run the console application, and you will see something like this in your command window: Number of base addresses : 1 http://localhost:8002/CloudMapper Number of dispatchers listening : 1 http://localhost:8002/CloudMapper, http://dotnetbyexample.blogspot.com:WebHttpBinding If you have, like me, configured the proxy to be used for a WMS service you can now enter something like "http://localhost:8002/CloudMapper/WMS/DemoSrv/?SRS=EPSG:4326&FORMAT=GIF&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=PERCEEL,GBKN_BIJGEBOUW,GBKN_VERHARDING,GBKN_HUISNR&TRANSPARENT=TRUE&BBOX=5.855712890625,51.8221981833694,5.86669921875,51.8289883636691&WIDTH=256&HEIGHT=256&REASPECT=FALSE" in your browser and then get a map image. Nice format, WMS, isn't it? :-) Next - to the clouds and beyond ;-) Make a new .NET Services solution Go to http://portal.ex.azure.microsoft.com and make a solution. I have called mine "LocalJoost" and let us suppose the password is "dotnetbyexample" Add reference to ServiceBus dll In your console application, add a reference to Microsoft.ServiceBus.dll. On my computer it resides in "D:\Program Files\Microsoft .NET Services SDK (March 2009 CTP)\Assemblies" Add .NET service bus configuration In your app.config, change "webRelayBinding" into "webHttpRelayBinding" Then, change the baseAdress from "http://localhost:8002/CloudMapper" to "http://localjoost.servicebus.windows.net/CloudMapper/". Notice: "localjoost", the first part of the URL is the solution name. Yours is likely to be different. Finally, in your app.config, add the following configuration to the behaviur "WebHttpBehavior", directly under the "<webHttp />" tag:
<transportClientEndpointBehavior credentialType="UserNamePassword">
  <clientCredentials>
     <userNamePassword userName="LocalJoost" 
                          password="dotnetbyexample" />
  </clientCredentials>
</transportClientEndpointBehavior>
If you now run your console application, you will see this: Number of base addresses : 1 http://localjoost.servicebus.windows.net/CloudMapper/ Number of dispatchers listening : 1 sb://localjoost.servicebus.windows.net/CloudMapper/, http://dotnetbyexample.blogspot.com:WebHttpRelayBinding. Now your REST service is callable via the Service bus. It is THAT easy. You only have to replace "http://localhost:8002" in your browser by "http://localjoost.servicebus.windows.net" and there you go. Well... almost. Instead of a map you get a site called "http://accesscontrol.windows.net" that asks you, once again, to enter the solution name and password. And THEN you get the map. Enable anonymous access For an encore, I am going to show you how to allow anonymous access to your proxy. Whether or not that is a wise thing to do is up to you. Remember that your service is now callable by anyone in the world, no matter how many firewalls are between you and the big bad world ;-) Add the following configuration data in the system.serviceModel section of your console application
<bindings>
  <webHttpRelayBinding>
 <binding name="allowAnonymousAccess">
   <security relayClientAuthenticationType="None"/>
 </binding>
  </webHttpRelayBinding>
</bindings>
and add bindingConfiguration="allowAnonymousAccess" to your endpoint. This is what your systems.serviceModel section of your app.config should look like when you're done:
<system.serviceModel>
  <bindings>
    <webHttpRelayBinding>
      <binding name="allowAnonymousAccess">
        <security relayClientAuthenticationType="None"/>
      </binding>
    </webHttpRelayBinding>
  </bindings>

  <services>
    <service name="CloudMap.Contracts.WMSProxyService" >
      <endpoint address="" binding="webHttpRelayBinding"
       bindingConfiguration="allowAnonymousAccess"
       behaviorConfiguration="WebHttpBehavior"
       contract="CloudMap.Contracts.IWMSProxyService"
       bindingNamespace="http://dotnetbyexample.blogspot.com">
      </endpoint>
      <host>
        <baseAddresses>
          <add baseAddress="http://localjoost.servicebus.windows.net/CloudMapper/" />
        </baseAddresses>
      </host>
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="WebHttpBehavior">
        <webHttp />
        <transportClientEndpointBehavior credentialType="UserNamePassword">
          <clientCredentials>
            <userNamePassword userName="LocalJoost"
                                 password="dotnetbyexample" />
          </clientCredentials>
        </transportClientEndpointBehavior>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
And that's all there is to it. Moving a service to the cloud is mostly configuration, and hardly any programming. Are we spoiled by Microsoft or what? ;-) Complete sample downloadable here

07 May 2009

Cutting images with PresentationCore

In my business cutting images into smaller images is something that happens quite often these days, since tile based mapping systems like Google Maps, Virtual Earth and OpenLayers are becoming ever more popular. For the past few years I have been using GDI+ as my workhorse, but last week I've kissed it goodbye. Over are the days of messing around with Graphics and Bitmap and not forgetting to dispose them. Enter PresentationCore with the System.Windows.Media.Imaging classes! To use this API, you need to make references to both PresentationCore.dll and WindowsBase.dll. I created a small sample cutter class like this:
using System;
using System.Windows;
using System.Windows.Media.Imaging;
using System.IO;

namespace LocalJoost.ImageCutting
{
  public class ImageCutter
  {
    private string _fileName;
    public ImageCutter(string fileName)
    {
      _fileName = fileName;
    }

    public void Cut(int TileSize, int TilesX, int TilesY)
    {
      var img = new BitmapImage();
      img.BeginInit();
      img.UriSource = new Uri(_fileName);
      img.CacheOption = BitmapCacheOption.OnLoad;
      img.EndInit();

      var fInfo = new FileInfo(_fileName);

      for (int x = 0; x < TilesX; x++)
      {
        for (int y = 0; y < TilesY; y++)
        {
          var subImg = new CroppedBitmap(img,
                   new Int32Rect(x * TileSize,
                          y * TileSize,
                          TileSize, TileSize));
          SaveImage(subImg, fInfo.Extension, 
            string.Format( "{0}_{1}{2}", x, y, fInfo.Extension));

        }
      }
    }
 
    private void SaveImage(BitmapSource image, 
                           string extension, string filePath)
    {
      var encoder = ImageUtilities.GetEncoderFromExtension(extension);
      using (var fs = new FileStream(filePath, 
              FileMode.Create, FileAccess.Write))
      {
        encoder.Frames.Add(BitmapFrame.Create(image));
        encoder.Save(fs);
        fs.Flush();
        fs.Close();
      }
    }
  }
}
You construct this class with a full path to an image file as a string, and then call the "Cut" method with tilesize in pixels (tiles are considered to be square) and the number of tiles in horizontal and vertical direction. It then goes on to cut the image into tiles of TileSize x TileSize pixels. Notice a few things:
img.CacheOption = BitmapCacheOption.OnLoad;
makes sure the image is loaded in one go, and does not get locked The trick of cutting the image itself is done by
var subImg = new CroppedBitmap(img,
               new Int32Rect(x * TileSize,
               y * TileSize,
               TileSize, TileSize));
and then it is fed to a simple private method that saves it to a file. Last, I do not check if the image is large enough to cut the number of tiles you want from. This is a sample, eh? The sample uses a small utility class that gets the right imaging encoder from either the file extension or the mime type, whatever you pass on to it
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace LocalJoost.ImageCutting
{
  /// 
  /// Class with Image utilities - duh
  /// 
  public static class ImageUtilities
  {
    public static BitmapEncoder GetEncoderFromMimeType(string mimeType)
    {
      switch (mimeType.ToLower())
      {
        case "image/jpg":
        case "image/jpeg": 
          return new JpegBitmapEncoder();
        case "image/gif": 
          return new GifBitmapEncoder();
        case "image/png":
          return new PngBitmapEncoder();
        case "image/tif":
        case "image/tiff":
          return new TiffBitmapEncoder();
        case "image/bmp": 
          return new BmpBitmapEncoder();
      }
      return null;
    }

    public static BitmapEncoder GetEncoderFromExtension(string extension)
    {
      return GetEncoderFromMimeType( extension.Replace(".", "image/"));
    }
  }
}
Not only are the System.Windows.Media.Imaging classes easier to use, they are also faster: switching from GDI+ to System.Windows.Media.Imaging reduced processing time to 50%, with an apparant significant lower CPU load and memory requirement. A complete example, including a unit test project that contains a test image which performs the completely hypothetical action of cutting a large 2048x2048 map file into 256x256 tiles ;-), is downloadable here. This project contains the following statement
Path.GetDirectoryNameAssembly.GetExecutingAssembly().Location
don't be intimidated by this, that's just a way to determine the full path of the current directory, i.e. the directory in which the unit test is running - you will find the resulting images there.

17 February 2009

Silverlight data binding the lazy way

Your typical business class utilizing data binding in Silverlight (and possibly WPF too, but I don't have any experience with that) look like this:
using System.ComponentModel;

namespace Dotnetbyexample
{
  public class Person : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    private string firstName;
    public string FirstName
    {
      get { return this.firstName; }
      set
      {
        this.firstName = value;
        this.NotifyPropertyChanged("FirstName");
      }
    }

    private string lastName;
    public string LastName
    {
      get { return this.lastName; }
      set
      {
        this.lastName = value;
        this.NotifyPropertyChanged("LastName");
      }
    }

    private string address;
    public string Address
    {
      get { return this.address; }
      set
      {
        this.address = value;
        this.NotifyPropertyChanged("Address");
      }
    }

    private string city;
    public string City
    {
      get { return this.city; }
      set
      {
        this.city = value;
        this.NotifyPropertyChanged("City");
      }
    }

    private string state;
    public string State
    {
      get { return this.state; }
      set
      {
        this.state = value;
        this.NotifyPropertyChanged("State");
      }
    }

    private string zip;
    public string Zip
    {
      get { return this.zip; }
      set
      {
        this.zip = value;
        this.NotifyPropertyChanged("Zip");
      }
    }

    public void NotifyPropertyChanged(string propertyName)
    {
      if (PropertyChanged != null)
      {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
    }
  }
}
Silverlight data binding rocks, for if you change the attribute, the listening GUI elements will update automatically, but what I particulary not like is the fact that the NotifyPropertyChanged method needs to be called with the name of the property as a string. Change the property name and the event does not work anymore. I created the following extension method
using System.ComponentModel;
using System.Diagnostics;

namespace Dotnetbyexample
{
  public static class INotifyPropertyChangedExtension
  {
    public static void NotifyPropertyChanged(
       this INotifyPropertyChanged npc, 
       PropertyChangedEventHandler PropertyChanged)
    {
      if (PropertyChanged != null)
      {
        string propertyName =
           new StackTrace().GetFrame(1).GetMethod().Name.Substring(4);

        PropertyChanged(npc, new PropertyChangedEventArgs(propertyName));
      }
    }
  }
}
which allows me to rewrite the business object as follows
using System.ComponentModel;

namespace Dotnetbyexample
{
  public class Person : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    private string firstName;
    public string FirstName
    {
      get { return this.firstName; }
      set
      {
        this.firstName = value;
        this.NotifyPropertyChanged(PropertyChanged);
      }
    }

    private string lastName;
    public string LastName
    {
      get { return this.lastName; }
      set
      {
        this.lastName = value;
        this.NotifyPropertyChanged(PropertyChanged);
      }
    }

    private string address;
    public string Address
    {
      get { return this.address; }
      set
      {
        this.address = value;
        this.NotifyPropertyChanged(PropertyChanged);
      }
    }

    private string city;
    public string City
    {
      get { return this.city; }
      set
      {
        this.city = value;
        this.NotifyPropertyChanged(PropertyChanged);
       }
    }

    private string state;
    public string State
    {
      get { return this.state; }
      set
      {
        this.state = value;
        this.NotifyPropertyChanged(PropertyChanged);
      }
    }

    private string zip;
    public string Zip
    {
      get { return this.zip; }
      set
      {
        this.zip = value;
        this.NotifyPropertyChanged(PropertyChanged);
      }
    }
  }
}
and presto: I got rid of the custom NotifyPropertyChanged method at the bottom of the class, and now the call to the extension method NotifyPropertyChanged is the same for every setter. No need to remember to change the string in the NotifyPropertyChanged when the property name changes - or when you copy the getter/setter from somewhere else ;-) Key to the whole trick is the quite unorthodox usage of the Stacktrace
new StackTrace().GetFrame(1).GetMethod().Name.Substring(4);
credits for this of course go to Rockford Lhotka with his CSLA framework - in the BusinessBase object of this framework I noticed this trick a year or so ago and suddenly I wondered if it would work in a Silverlight environment as well. Update: in the newest version of the CSLA framework the method using this trick -CanWriteProperty - is marked deprecated, and is replaced by a method CanWriteProperty(string) that takes the property name as an explicit string - so Lhotka is now swinging round to follow the PropertyChangedEventHandler.