RSS

Category Archives: Technology

Making 3rd-party API Libraries more Robust

In this post we’ll be combining Generics, Functions and Actions with the Decorator Pattern to solve the following problem:

Network requests are flaky

Every time you make a call “across the wire” you’ve got to provision for errors. Everything from gateway timeouts, server faults right down to your toddler pulling the lan cable out. If it can happen, at some point, it probably will.

Most solutions are very ad-hoc and resemble this:

using (var wc = new WebClient())
{
  for (int i = 0; i < 5; i++)
  {
    try
    {
      wc.DownloadFile(source, target);
      break;
    }
    catch (Exception e)
    {
      Thread.Wait(200);
    }
  }
}

This approach is fine if you only have a couple of calls in your application. In today’s hyper-connected world, however, it’s more likely that you’ll be making lots of these requests with wildly differing signatures. Very quickly your code will become unreadable as you battle to trap all the possible exceptions and manage the retries. What we need is a pattern for easily applying this retry mechanism to any call whilst keeping our client code clean.

Real-world Example

There are a myriad of 3rd party libraries that allow you to target platform APIs e.g. Twitter, Facebook etc. At PhotoPivot.com we rely heavily on Sam and Tim‘s great FlickrNet library to perform an enormous number of calls to Flickr. Here’s a greatly simplified bit of production code from our server-side application:

public class FlickrPhotoDataDownloadService
{
  private readonly IFlickr _flickr;

  public FlickrPhotoDataDownloadService(IFlickr flickr)
  {
    _flickr = flickr;
  }

  public void GetPhotoDataForUser(string userId)
  {
    var photoCollection = _flickr.PhotosGetAllNotInSet();

    foreach (var photo in photoCollection)
    {
      var photoInfo = _flickr.PhotosGetInfo(photo.PhotoId);
      var exifs = _flickr.PhotosGetExif(photo.PhotoId);

      // Do something with the data...
    }
  }
}

Potentially, any of the calls to the IFlickr interface can result in a sporadic network error. This is a serious pain if it happens inside the foreach loop when the routine is 90% through a list of 10,000 photos. If we implemented the ad-hoc solution at the start of this post the GetPhotoDataForUser method would become very untidy and a developer’s ability to read it would lessen. So, let’s look at some of the related classes. Below you can see the interface that the service uses to describe its requirements. We then used the Adapter Patternto “bring in” the interface to the main FlickrNet class.

public interface IFlickr
{
  PhotoCollection PhotosGetAllNotInSet();
  PhotoInfo PhotosGetInfo(photo.PhotoId);
  ExifTagCollection PhotosGetExif(photo.PhotoId);
}

public class FlickrEx : FlickrNet.Flickr, IFlickr
{
}

The client code that uses the service looks like this:

var flickr = new FlickrEx();
var service = new FlickrPhotoDataDownloadService(flickr);
service.GetPhotoDataForUser(userId);

So, how do we encapsulate all the methods, or at least the methods we need, in the main Flickr class? We can’t rely on just extending the class as it, or its methods, might be sealed. Let’s start by creating a class that can keep track on failed attempts and whether a retry is possible.

using System;using System.Threading;

internal abstract class RetryableBase
{
  private readonly int _maxAttempts;
  private readonly TimeSpan _delay;
  private int _attempts;

  internal RetryableBase(int maxAttempts, TimeSpan delay)
  {
    _maxAttempts = maxAttempts;
    _delay = delay;
  }

  protected bool CanRetry(Exception e)
  {
    _attempts++;

    Thread.Sleep(_delay);

    return (_attempts < _maxAttempts);
  }
}

Next we’ll extend this and, by leveraging C#’s Func capabilities, create a couple of classes that can wrap a function in some standardised retry routines.

using System;

internal class RetryableFunc<TResult> : RetryableBase
{
  private readonly Func<TResult> _func;

  public RetryableFunc(Func<TResult> func, int maxAttempts, TimeSpan delay)
  : base(maxAttempts, delay)
  {
    _func = func;
  }

  public TResult Call()
  {
    TResult result = default(TResult);

    bool success = false;

    while (!success)
    {
      try
      {
        result = _func();
        success = true;
      }
      catch (Exception e)
      {
        if (!CanRetry(e))
          throw;
      }
    }

    return result;
  }
}

internal class RetryableFunc<T, TResult> : RetryableBase
{
  private readonly Func<T, TResult> _func;

  public RetryableFunc(Func<T, TResult> func, int maxAttempts, TimeSpan delay)
  : base(maxAttempts, delay)
  {
    _func = func;
  }

  public TResult Call(T t)
  {
    TResult result = default(TResult);

    bool success = false;

    while (!success)
    {
      try
      {
        result = _func(t);
        success = true;
      }
      catch (Exception e)
      {
        if (!CanRetry(e))
          throw;
      }
    }

    return result;
  }
}

You will, unfortunately, need to create a new class for each signature function call needed. For instance, the one’s above will work for calls that match Func<TResult> or Func<T, TResult> only. Func<T1, T2, TResult> will need another class. Functions that don’t return anything are Actions<>. You’ll need separate classes for these also. Once done, though, the ROI will be huge.

We now have the capability to make calls robust but how do we ‘invisibly’ add this to someone else’s class? We’ll use the Decorator Pattern to create a new class that “is a” IFlickr but also “has a” IFlickr. By initially abstracting our service’s needs to an interface we have enabled ourselves to do this very easily.

public class RetryableFlickrEx : IFlickr
{
  private readonly IFlickr _flickr;

  public RetryableFlickrEx(IFlickr flickr)
  {
    _flickr = flickr;
  }

  public PhotoCollection PhotosGetAllNotInSet()
  {
    var retry = new RetryableFunc&lt;PhotoCollection&gt;(_flickr.PhotosGetAllNotInSet);

    return retry.Call();
  }
  public PhotoInfo PhotosGetInfo(string photoId)
  {
    var retry = new RetryableFunc&lt;string, PhotoInfo&gt;(_flickr.PhotosGetInfo);

    return retry.Call(photoId);
  }
  public ExifTagCollection PhotosGetExif(string photoId)
  {
    var retry = new RetryableFunc&lt;string, ExifTagCollection&gt;(_flickr.PhotosGetExif);

    return retry.Call(photoId);
  }
}

Now that we have all our pieces in place the ONLYchange we need to make to our entire application is one line in the client. The service still gets the IFlickr it requires and simply doesn’t care about the implementation:

var flickrBase = new FlickrEx();

// New line: Use the Decorator Pattern to extend functionality at runtime...
var flickr = new RetryableFlickrEx(flickrBase);

var service = new FlickrPhotoDataDownloadService(flickr);
service.GetPhotoDataForUser(userId);

Please leave comments if you can see a way of enhancing this idea.

Advertisements
 
Leave a comment

Posted by on April 15, 2011 in Technology

 

Tags: , , ,

Standardising String Cryptography

I was writing the new Twitter Client for TweetPivot when I hit a problem. I needed to store a small amount of information on our users’ machines; specifically in isolated storage. Most of this would be fine as plain text but one field needed to be encrypted. This meant I had to solve a problem I seem to come back to again and again – simple string cryptography.

Crypto Rule #1 seems to be “Don’t roll your own.”. OK fine, so give me something pre-rolled. C# / .Net doesn’t contain the method I was looking for:

string Encrypt(string plainText, string password, string salt);

Luckily, @blowdart came to my rescue and posted this code. Now, there’s a few things worth pointing out about this:

  1. Barry’s book sales suggest he might actually know what he’s doing, but who else amongst us has the confidence and knowledge to say that it’s safe and reliable?
  2. Did anyone read the code and think “actually, TripleDES would suit my needs, not Rijndael”?

Answer: probably no.

So, given that a) it’s hard to do correctly and b) this standard method would probably suit 99% of developers 99% of the time why, then, do we not find this in the BCL? If I want to open a file I can use System.IO.File.OpenRead(string path). If I need to take more control over the process I can use a StreamReader and dictate encodings etc.

I’ve included my final code below (you deserve something for reading this far!). Porting it into Silverlight simplifies matters – mainly because there’s only one implementation of SymmetricAlgorithm. “But Barry defaulted to Rijndael. Does this mean that Silverlight is less secure than standard .Net applications?” Another crypto conundrum!

I do feel that this functionality needs abstracting behind a simplified facade. I genuinely don’t care how long my initialisation vector is or whether I’m using DES, DoubleDES or even TripleDES. Cryptography is simply a tool for hiding stuff and it should be easier, safer and more confidence-imspiring than it currently is. @blowdart’s subsequent tweet kinda sums up the complexity of the subject. Signatures, really? You might just as well have asked me if I wanted tweeters with it! #referenceToOldJoke

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public static class CryptographicExtensions
{
  public static string Encrypt(this string plainText, string password, string salt)
  {
    var algorithm = new AesManaged();

    algorithm.SetKeyAndIV(password, salt);

    return Encrypt(algorithm, plainText);
  }

  public static string Encrypt(this string plainText, ref byte[] key, ref byte[] iv)
  {
    if (string.IsNullOrEmpty(plainText))
      return plainText;

    var algorithm = new AesManaged();

    if (key != null)
      algorithm.Key = key;
    else
      key = algorithm.Key;

    if (iv != null)
      algorithm.IV = iv;
    else
      iv = algorithm.IV;

    return Encrypt(algorithm, plainText);
  }

  private static string Encrypt(SymmetricAlgorithm algorithm, string plainText)
  {
    var plainTextAsBytes = Encoding.UTF8.GetBytes(plainText);

    using (ICryptoTransform transform = algorithm.CreateEncryptor())
    {
      using (var outputStream = new MemoryStream())
      {
      using (var inputStream = new CryptoStream(outputStream, transform, CryptoStreamMode.Write))
      {
        inputStream.Write(plainTextAsBytes, 0, plainText.Length);
        inputStream.FlushFinalBlock();
        var cipherText = outputStream.ToArray();
        return Convert.ToBase64String(cipherText);
      }
    }
  }

  public static string Decrypt(this string cypherText, string password, string salt)
  {
    var algorithm = new AesManaged();

    algorithm.SetKeyAndIV(password, salt);

    return Decrypt(algorithm, cypherText);
  }

  public static string Decrypt(this string cypherText, byte[] key, byte[] iv)
  {
    if (string.IsNullOrEmpty(cypherText))
      return cypherText;

    if (key == null)
      throw new ArgumentNullException("key");

    if (iv == null)
      throw new ArgumentNullException("iv");

    var algorithm = new AesManaged { Key = key, IV = iv };

    return Decrypt(algorithm, cypherText);
  }

  private static string Decrypt(SymmetricAlgorithm algorithm, string cypherText)
  {
    var cipherTextAsBytes = Convert.FromBase64String(cypherText);

    using (ICryptoTransform transform = algorithm.CreateDecryptor())
    {
      using (var outputStream = new MemoryStream())
      {
        using (var inputStream = new CryptoStream(outputStream, transform, CryptoStreamMode.Write))
        {
          inputStream.Write(cipherTextAsBytes, 0, cipherTextAsBytes.Length);
          inputStream.FlushFinalBlock();
          var plainTextAsBytes = outputStream.ToArray();

          return Encoding.UTF8.GetString(plainTextAsBytes, 0, plainTextAsBytes.Length);
        }
      }
    }
  }

  public static void SetKeyAndIV(this SymmetricAlgorithm algorithm, string password, string salt)
  {
    string paddedSalt = salt;

    while (paddedSalt.Length < 8 )
      paddedSalt += salt;

    var rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(paddedSalt));

    algorithm.Key = rfc2898.GetBytes(algorithm.KeySize / 8);
    algorithm.IV = rfc2898.GetBytes(algorithm.BlockSize / 8);
  }
}
 
3 Comments

Posted by on October 12, 2010 in C#

 

Tags: ,

Great, another Pivot!

The word ‘Pivot’ seems to be somewhat of a favourite amongst the tech community these days. It all started with Pivot tables back in the late 80’s. In the past few years we’ve added 3 new pivots to the list:

If that wasn’t enough we now have a fifth! The final Windows Phone 7 SDK launched a couple of days ago and contains, wait for it, a Windows Phone 7 Pivot Application template.

I work with two of these (the Lean Startup and Live Labs) and it’s already confusing trying to explain to potential customers which pivots our business uses.

Seriously, no more. Please?

Maybe this is a compelling reason for companies to trademark their products?

 
Leave a comment

Posted by on September 21, 2010 in Technology

 

Tags:

A Rebuke of Twifficiency

Unless you’ve been asleep under a stone for the past 48 hours you couldn’t have failed to notice the Twitter phenomenon that is Twifficiency. Created by James Cunningham it generated an efficiency score based on your Twitter usage. In order to access the service, though, you had to grant the application access to your Twitter account.

Unwittingly, or not, James had violated one of Twitter’s codes of practice re: abuse of privileged access to accounts. Specifically, the application automatically tweeted a message from the user’s account in the format:

My Twifficiency score is x%. What’s yours? http://twifficiency.com

Generally, this annoyed people but, because of its viral nature, the term “Twifficiency” started trending worldwide.

Now, can we please get some perspective on this?

Yes, it trended. Yes, it spread like wildfire. Yes, everyone’s talking about it; but so what? This is the Twitter version of “Britain’s Got Talented X-Factor for me Nan“. It was hugely popular but, ultimately, worthless. Shouldn’t we be discouraging this kind of sensationalism and, instead, be encouraging the trending of remarkable products (to quote Seth Godin). The mere fact that it trended says nothing about its worth – because it trended itself automatically, virally. This is the complete opposite of something that trends because users want to tell their friends about it. In fact self-promotion obfuscates this valuable measure.

James is, undoubtedly, a very nice chap who was just experimenting with an idea, but for some people to be considering offering him a job! Seriously, no. Stop.

Tech Crunch hits the nail on the head in their blog post and I would like to add to that by pointing out that Stephen Fry only scored 3%!!!

Now, if James had created the site with an opt-in option for re-tweeting (as opposed to its new opt-out option) and it had still trended; then, wow! That would have been a truly remarkable feat. The fact is, though, that you’ve removed any meaningful way of measuring your success.

I have no doubt that James will go on to great things but, I’m afraid, I think he should be infamous, not famous, for Twifficiency.

 
Leave a comment

Posted by on August 18, 2010 in Social Media

 

Tags: ,

Immutable, Auto-Implemented Properties in C#

Over the past few months I’ve been getting a lot more into immutability. If you want to know why you should be using immutable types start with this blog post by Bertrand Le Roy.

Until recently I, like most other developers had been creating my properties like this…

public class Person
{
  public DateTime BirthDate { get; private set; }
  public string FavouriteSong { get; set;}

  public Person(DateTime birthDate)
  {
    BirthDate = birthDate;
  }
}

Pretty straight forward – the BirthDate is required and must be set during construction of the object whilst the FavouriteSong is optional. The other reason for writing properties this way is simplicity and code succinctness. It also allows more ‘interesting’ properties to be more easily identified. For instance, this new Age property stands out from the other two and ‘asks’ to be unit tested.

public class Person
{
  public DateTime BirthDate { get; private set; }
  public string FavouriteSong { get; set;}

  public int Age
  {
    get
    {
      var now = DateTime.Today;
      var age = now.Year - bday.Year;

      if (bday > now.AddYears(-age))
        age--;

      return age;
    }
  }

  public Person(DateTime birthDate)
  {
    BirthDate = birthDate;
  }
}

I should, however, be making the BirthDate property immutable – it isn’t gonna change! This does make the code less neat though…

public class Person
{
  private readonly DateTime _birthDate;
  public DateTime BirthDate { get { return _birthDate; } }</pre>
  public string FavouriteSong { get; set;}

  public int Age
  {
    get
    {
      var now = DateTime.Today;
      var age = now.Year - bday.Year;

      if (bday > now.AddYears(-age))
        age--;

      return age;
    }
  }

  public Person(DateTime birthDate)
  {
    _birthDate = birthDate;
  }
}

Auto-implemented properties are a .Net construct and are used as a template, at design-time, to create a ‘real’ pair of _get _set methods. So, what I’d like to be able to do is this …

public class Person
{
  public DateTime BirthDate { get; private readonly set; }
  public Person(DateTime birthDate)
  {
    _birthDate = birthDate;
  }
}

Anyone from Microsoft like to chime in?

 
Leave a comment

Posted by on August 16, 2010 in C#

 

Tags:

I’ve been scammed! A follow-up to Twitter Auth Issues

This is a follow-up post to Social Network Authorisation Needs to Change.

Having written the above post over a month ago and considering myself to be quite net-savvy, I’m hugely embarrassed and mortified to admit that I’ve just been victim to a Twitter-related scam. This is the scam site that duped me: http://www.ipadappstesting.com/. It’s safe to browse to it – JUST DON’T LOG IN!

I received a Twitter Direct Message (DM) from a trusted friend that invited me to go to the site so that I could sign up to be an iPad tester. At the end of the test period I would get to keep the hardware. Superb! Yeh, right.

My spidey-senses were working well enough that I didn’t complete the in-depth financial survey they put in front of me. What did happen, however, was their servers sent DMs to, presumably ALL, my friends inviting them to do the same. Needless to say that this was without my knowledge – let alone my consent.

Twitter, seriously guys, this needs to change quickly otherwise you’re going to go the way of Facebook.

The access granted to my account for an application needs to be segmented and I need to have the ability to REVOKE any aspect I’m not entire happy with at login time. For instance, the shill application in question should have had to request DM read / write access during their registration with Twitter. This should then have appeared as a checkbox on the Twitter OAuth screen. I would then have unchecked it.

Feeling rather violated now but, hey, how was I to know? I currently just have to put my trust in the application developers and I don’t think that’s either fair or sustainable.

 
Leave a comment

Posted by on August 11, 2010 in Social Media

 

Tags: , ,

Faking PivotViewer in Blend 4

If you’ve been using the new PivotViewer Silverlight control then you’ve probably come across the Blend problem. Basically, it doesn’t work and you get the following error…

Error HRESULT E_FAIL has been returned from a call to a COM component.

This problem does not occur in Visual Studio 2010 (VS2010) – although the page view does look a little suspect. Some people have suggested commenting out the PivotViewer element when opening the page in Blend, but there’s a much better approach – fakes.

First, create a new “Silverlight Class Library” project in VS2010 called FakePivot and, once loaded, delete the Class1.cs file. Now add a new Code File called PivotViewer.cs with the following starting code:

using System;

namespace FakePivot
{
  public class PivotViewer
  {
  }
}

Next add a reference to the PivotViewer library (System.Windows.Pivot.dl) and the SharedUI library (System.Windows.Pivot.SharedUI.dll). If you don’t find them under the .Net tab you can browse for them at <Program Files>\Microsoft SDKs\Silverlight\v4.0\PivotViewer\Jun10\Bin\. Now update your PivotViewer class to look like this…

using System;

namespace FakePivot
{
  public class PivotViewer : System.Windows.Pivot.PivotViewer
  {
  }
}

Right click on Microsoft’s PivotViewer and choose “Go To Definition”. You should now see the following metadata file:

#region Assembly System.Windows.Pivot.dll, v2.0.50727
// C:\Program Files\Microsoft SDKs\Silverlight\v4.0\PivotViewer\Jun10\Bin\System.Windows.Pivot.dll
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Resources;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;

namespace System.Windows.Pivot
{
  [ScriptableType]
  [TemplatePart(Name = "PART_Container", Type = typeof(Grid))]
  public class PivotViewer : Control, INotifyPropertyChanged
  {
    public PivotViewer();
    public PivotViewer(ResourceDictionary colorScheme);

    public IDictionary<string, IList<string>> AppliedFilters { get; }
    public int CollectionItemCount { get; }
    public string CollectionName { get; }
    public Uri CollectionUri { get; }
    public string CurrentItemId { get; set; }
    public ICollection<string> InScopeItemIds { get; }
    public string SortFacetCategory { get; }
    public string ViewerState { get; }

    public event EventHandler CollectionLoadingCompleted;
    public event EventHandler<CollectionErrorEventArgs&gt; CollectionLoadingFailed;
    public event EventHandler<ItemActionEventArgs> ItemActionExecuted;
    public event EventHandler<ItemEventArgs> ItemDoubleClicked;
    public event EventHandler<LinkEventArgs> LinkClicked;
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual List<CustomAction> GetCustomActionsForItem(string itemId);
    public PivotItem GetItem(string id);
    public void LoadCollection(string collectionUri, string viewerState);
    public override void OnApplyTemplate();
    public static void SetResourceManager(ResourceManager resourceManager);
  }
}

What we want to do next is extract the interface for the standard PivotViewer class. If you have a refactoring tool I’d use it, otherwise you just have to do it manually. Either way, we should now have an interface in our project called IPivotViewer.cs …

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Pivot;

namespace FakePivot
{
  public interface IPivotViewer : INotifyPropertyChanged
  {
    IDictionary<string, IList<string>> AppliedFilters { get; }
    int CollectionItemCount { get; }
    string CollectionName { get; }
    Uri CollectionUri { get; }
    string CurrentItemId { get; set; }
    ICollection<string> InScopeItemIds { get; }
    string SortFacetCategory { get; }
    string ViewerState { get; }

    event EventHandler CollectionLoadingCompleted;
    event EventHandler<CollectionErrorEventArgs> CollectionLoadingFailed;
    event EventHandler<ItemActionEventArgs> ItemActionExecuted;
    event EventHandler<ItemEventArgs> ItemDoubleClicked;
    event EventHandler<LinkEventArgs> LinkClicked;

    PivotItem GetItem(string id);
    void LoadCollection(string collectionUri, string viewerState);
  }
}

Next, we want to go back to our PivotViewer class and make it extend Control and implement our new IPivotViewer interface like this…

using System;
using System.Collections.Generic;
using System.Windows.Pivot;
using System.ComponentModel;
using System.Windows.Controls;

namespace FakePivot
{
  public class PivotViewer : Control, IPivotViewer
  {
    public IDictionary<string, IList<string>> AppliedFilters { get { throw new NotImplementedException(); } }

    public int CollectionItemCount { get { throw new NotImplementedException(); } }

    public string CollectionName { get { throw new NotImplementedException(); } }

    public Uri CollectionUri { get { throw new NotImplementedException(); } }

    public string CurrentItemId { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }

    public ICollection<string> InScopeItemIds { get { throw new NotImplementedException(); } }

    public string SortFacetCategory { get { throw new NotImplementedException(); } }

    public string ViewerState { get { throw new NotImplementedException(); } }

    public event EventHandler CollectionLoadingCompleted;

    public event EventHandler<CollectionErrorEventArgs> CollectionLoadingFailed;

    public event EventHandler<ItemActionEventArgs> ItemActionExecuted;

    public event EventHandler<ItemEventArgs> ItemDoubleClicked;

    public event EventHandler<LinkEventArgs> LinkClicked;

    public event PropertyChangedEventHandler PropertyChanged;

    public PivotItem GetItem(string id) { throw new NotImplementedException(); }

    public void LoadCollection(string collectionUri, string viewerState) { throw new NotImplementedException(); }
  }
}

OK, I know, I know – this is pretty convoluted. But, what we now have is a ‘real’ Silverlight control that exposes the same interface as Microsoft’s control. Here’s how to use it…

Let’s add a new “Silverlight Application” project to our solution – we’ll call it PivotViewerApp. For this example we don’t need to “Host the Silverlight application in a new Web site”. Now add three references to this project (2 of which we already added to our FakePivot project):

  1. System.Windows.Pivot
  2. System.Windows.Pivot.SharedUI
  3. Our FakePivot project

VS2010 should have opened the MainPage.xaml file in “split view” mode. Let’s add some references to our 2 namespaces of interest (pivot and fakepivot) and then create our pivot control…

<UserControl x:Class="PivotViewerApp.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:pivot="clr-namespace:System.Windows.Pivot;assembly=System.Windows.Pivot"
    xmlns:fakepivot="clr-namespace:FakePivot;assembly=FakePivot"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
  <Grid x:Name="LayoutRoot" Background="White">
    <pivot:PivotViewer x:Name="pivotViewer1" />
  </Grid>
</UserControl>

If you now right click on MainPage.xaml in the Solution Explorer and choose “Open in Expression Blend” you’ll see the exception I mentioned at the start of this post. So let’s go back to VS2010 and change the namespace of our pivotViewer1 control from pivot to fakepivot…

<UserControl x:Class="PivotViewerApp.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:pivot="clr-namespace:System.Windows.Pivot;assembly=System.Windows.Pivot"
    xmlns:fakepivot="clr-namespace:FakePivot;assembly=FakePivot"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">
  <Grid x:Name="LayoutRoot" Background="White">
    <fakepivot:PivotViewer x:Name="pivotViewer1" />
  </Grid>
</UserControl>

Because both namespaces contain a PivotViewer class our xaml is perfectly happy and the solution will still compile. Now go ahead and reopen the same file in Blend – ta dah, no exceptions.

The real beauty of this approach, however, becomes evident when working with the fake control in Blend. Because it exposes exactly the same events, methods and properties as the Microsoft control we can use the Blend UI to hook into these. Selecting pivotViewer1 in our Objects and Timeline window we can then click the Events button in the Properties tab and see all the events that we’d expect our real control to expose.

Once we’ve done your design work in Blend we, obviously, have to revert our fakepivot namespace to pivot before we can build anything useful. One option is to go back to VS2010 to do this. However, if you hide the Design window in Blend and just have the XAML window visible you can change it there and successfully compile it.

Hopefully, that wasn’t too complicated and, once you have your FakePivot library, you can reuse it in any related projects. If anyone want me to do a video of this process please let me know in the comments.

Finally, click here to download the example solution for this post.

 
1 Comment

Posted by on July 12, 2010 in Silverlight

 

Tags: , , ,