Sunday, February 7, 2010

A Fluent RSS Reader for Silverlight Part 1: Proof of Concept

One of the most common examples to help learn a language or framework is an RSS Reader. This is an ideal mini-project because it includes networking, parsing XML, and binding to data elements such as lists. I wanted to provide an example that shows some more interesting solutions that are possible using C# in Silverlight. This is the first part in a series. By the end of this post, we'll have a working reader. What I'll then do is add some more detailed error handling, provide unit tests, tackle skinning and visual states, and hopefully end up with a fairly advanced client.

Today, let's focus on getting a client where we can enter a feed and get some listings. A perfect way to test this will be a Twitter feed. If you would like to read my recent tweets as RSS, for example, you can simply navigate to http://twitter.com/statuses/user_timeline/46210370.rss. By viewing the source, you can see the basic structure of an RSS feed. It is fairly straightforward.

Download the source for this project

Domain Entities

The first step is to define some domain entities. These are the "models" for our application, and represent the actual data we are working with. With an RSS feed, it is fairly simple. We'll work our way backward from the item up to the channel. Our item to start with looks like this:

 
public class Item
{
    public string Title { get; set; }

    public string Description { get; set; }

    public DateTime PublishDate { get; set; }

    public string Guid { get; set; }

    public Uri Link { get; set; }
}

A channel is simply some header information with a collection of items. For starters, we'll make it look like this:

public class Channel
{
    public Channel()
    {
        Items = new ObservableCollection<Item>();
    }

    public string Title { get; set; }

    public Uri Link { get; set; }

    public string Description { get; set; }

    public ObservableCollection<Item> Items { get; set; }
}

Note that I build my entities based on the actual content, not how the content is delivered. In other words, even though the RSS stream may encode a link or a date as text, I want my domain entity to be able to work with the property as it was intended. Therefore, there are no "hacks" to force something into a Uri that doesn't belong: we use that type for the links. Similarly, the date time is handled as a date, and we can worry about how to display it when the time is right. The point is this keeps the data we're dealing with abstracted from the way we receive it, so if down the road we are reading a database or connecting to a different type of service, we only need to change the way we adapt from the service into our domain.

De-serialization

One of the challenges we'll face with RSS feeds is taking the feed data and turning it into our domain objects (de-serializing the data). There are a number of different approaches, but I wanted to present one that I think makes it extremely easy to expand and extend entities that are mapped to XML documents. It involves using Silverlight's powerful LINQ to XML features.

The concept is relatively simple: XML data is mostly strings in elements and attributes. For RSS feeds, the data is entirely in elements. Therefore, it should be relatively straightforward to parse an XML element into an entity. We'll know the target property and the type of that property, so all we need is the element and the conversion.

To tackle the element, I decided to create a custom attribute called RssElement that allows me to tag a property with the name of the element the property's value is contained within. Here is the attribute:

[AttributeUsage(AttributeTargets.Property,AllowMultiple = false)]
public class RssElementAttribute : System.Attribute
{
    public readonly string ElementName; 

    public RssElementAttribute(string elementName)
    {
        ElementName = elementName;
    }
}

Now I can circle back to my entities and tag them with the source elements. First, the item:

public class Item
{
    [RssElement("title")]
    public string Title { get; set; }

    [RssElement("description")]
    public string Description { get; set; }

    [RssElement("pubDate")]
    public DateTime PublishDate { get; set; }

    [RssElement("guid")]
    public string Guid { get; set; }

    [RssElement("link")]
    public Uri Link { get; set; }
}

And then the channel:

public class Channel
{
    public Channel()
    {
        Items = new ObservableCollection();
    }

    [RssElement("title")]
    public string Title { get; set; }

    [RssElement("link")]
    public Uri Link { get; set; }

    [RssElement("description")]
    public string Description { get; set; }

    public ObservableCollection<Item> Items { get; set; }
}

Now that we have a way of tagging the properties, we can create a fluent extension to move from an XElement (what LINQ gives us) to an actual type.

I created a static class called LinqExtensions to extend my LINQ classes. Again, working backward, let's consider what happens to the value of an element in XML when we move it to our entity. We'll need to take that value (which is a string) and convert it based on the target type. It has a consistent method signature: receive a string, return a type. Therefore, I decided to implement a dictionary to map the conversion process to the target types. Working with the types I know I'll need, my dictionary looks like this:

public static class LinqExtensions
{
    private static readonly Dictionary<Type, Func<string, object>> _propertyMap;

    static LinqExtensions()
    {
        _propertyMap = new Dictionary<Type, Func<string, object>>
                           {
                               {typeof (string), s => s},
                               {typeof (Uri), s => new Uri(s)},
                               {typeof (DateTime), s => DateTime.Parse(s)}
                           };
    }

This is very simple when you see where I'm going. Everything is mapped to a function that takes a string and returns an object. A string is a pass-through (s => s). A Uri converts the string to a Uri (s => new Uri(s)) and a date time attempts to parse the date (s => DateTime.Parse(s)). By using the type as the key to the dictionary, I can do this:

...
DateTime date = _propertyMap[typeof(DateTime)]("1/1/2010") as DateTime; 
...

Of course, part of what we can do down the road is add some better error handling and contract checking. Next, let's use this conversion. I am taking in an element, then using the property information that I have to set the value onto an instance of the target class. Given a class instance T, an element, and the information about a property, I can inspect the custom attribute to find the element name, then use the conversion for the type of the property to set the value. My method looks like this:

private static void _ProcessProperty<T>(T instance, PropertyInfo property, XContainer element)
{
    var attribute =
        (RssElementAttribute) (property.GetCustomAttributes(true)
                                  .Where(a => a is RssElementAttribute))
                                  .SingleOrDefault();

    XElement targetElement = element.Element(attribute.ElementName);

    if (targetElement != null && _propertyMap.ContainsKey(property.PropertyType))
    {
        property.SetValue(instance, _propertyMap[property.PropertyType](targetElement.Value), null);
    }
}

As you can see, we grab the element, find the value in the XML fragment we're passed, then use the property's SetValue method to set the value based on the conversion we find in the property map.

How do we get the property info? Take a look at this fluent extension. It takes an element and is typed to a target class. It will create a new instance of the class and iterate the properties to set the values. By using it as a fluent extension, I can write this in code, which I think makes it very readable:

...
var widget = xmlElement.ParseAs<Widget>(); 
...

The "parse as" method looks like this:

public static T ParseAs<T>(this XElement element) where T : new()
{
    var retVal = new T();

    ((from p in typeof (T).GetProperties()
      where (from a in p.GetCustomAttributes(true) where a is RssElementAttribute select a).Count() > 0
      select p).AsEnumerable()).ForEach(p => _ProcessProperty(retVal, p, element));

    return retVal;
}

I basically grab all properties with the custom attribute, then pass the class, element, and property to the method we developed earlier to set the value. Finally, I return the new instance of the class. The ForEach is available with the toolkit, but you can roll your own enumerator extension like this:

public static class IteratorExtensions
{
    public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
    {
        foreach(var item in list)
        {
            action(item);
        }
    }
}

To me, it saves code and makes it easier to read what's going on if you have to perform a simple action and use the ForEach extension to do it.

While we're having fun with our fluent extensions, we're almost ready to take an RSS feed and turn it into a group of objects. We need a way to get the text we receive from the call into an XDocument, so I made this extension:

public static XDocument AsXDocument(this string xml)
{
    return XDocument.Parse(xml);
}

We also need to take the XDocument and iterate the elements to build channels and items. Because we already built our ParseAs method and have tagged the entities for channels and elements, this becomes as simple as:

public static List<Channel> AsRssChannelList(this XDocument rssDoc)
{
    var retVal = new List<Channel>();

    if (rssDoc.Root != null)
    {
        foreach(var c in rssDoc.Root.Elements("channel"))
        {
            var channel = c.ParseAs<Channel>();
            c.Elements("item").ForEach(item => channel.Items.Add(item.ParseAs<Item>()));
            retVal.Add(channel);                    
        }
    }

    return retVal;
}

Again, I believe the fluent extensions are making our life easier because one logical layer builds on the next. We already have our entities tagged and our parsing worked out, so now we simply iterate the channels and parse those as channels, then iterate the items and parse those as items. Could it be an easier? Now, if I have the text of an RSS feed in a variable called rssFeed, the only thing I need to do in order to turn it into a list of channels and items is this:

...
var channelList = rssFeed.AsXDocument().AsRssChannelList(); 
...

We've done most of the heavy lifting, so let's tackle actually going out and fetching the feed. If you've worked with Silverlight and tried to fetch any type of information from another website, you'll be familiar with the strict cross-domain policies that Silverlight has. You can read the Microsoft article on Network Security Access Restrictions in Silverlight to get the full scoop.

In a nutshell, it says most likely we won't be able to reach out from our Silverlight client to touch the RSS feeder and bring back the information. How do you like that twist? Fortunately, there is a workaround.

Using a Handler to Bypass Cross Domain Concerns

Silverlight is allowed to pull information from the same server that it is hosted from. One simple way to bypass the issue with going out directly from the client to the reader is to create a proxy. We don't have the same restrictions on the server with going across domains, so we can have Silverlight "ask" the server to pull the feed for us, and deliver it back.

This, however, has its own issues. I can make a handler that takes a Uri and then returns the data, but this would expose a potential security risk in my web application. It would open the door for malicious attackers to hit other websites and make it look like it is coming from my server! It's sort of like the old "call-forwarding" techniques that old school phreakers would use to hide their illicit telecommunications activities.

I am going to use the handler approach, but make it a little more difficult to abuse. In a production system, I'd implement a full brown encryption scheme. The issue with the Silverlight side is that it gets downloaded to the browser, so a would-be hacker can easily pull apart the code and dissect what's going on. You'll want a fairly strong algorithm to circumvent foul play. For this blog example, I'm going to implement a very light security piece that will thwart any casual foul play by preventing someone from guessing how to pull a feed without knowing the algorithm. OK, so it's not very secret because I'm letting you in on the deal.

For the sake of illustration, I'm simply going to have the Silverlight client generate a guid, then generate a hash on the GUID using SHA1. Again, for a more secured solution, I'd have a SALT and keywords, etc, but this at least shows a way to secure the communication and should get you thinking about security concerns when you start exposing services for Silverlight to consume.

In order for this to work, both the client and the server need to implement the same algorithm. I am a big fan of DRY (Don't Repeat Yourself) so I don't want to duplicate the algorithm in both places. Instead, I'll build this simple piece on the Silverlight side:

public static class SecurityToken
{        
    public static string GenerateToken(string seed)
    {
        Encoder enc = Encoding.Unicode.GetEncoder();

        var unicodeText = new byte[seed.Length * 2];
        enc.GetBytes(seed.ToCharArray(), 0, seed.Length, unicodeText, 0, true);

        System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1Managed();

        byte[] result = sha.ComputeHash(unicodeText);

        var sb = new StringBuilder();

        for (int i = 0; i < result.Length; i++)
        {
            sb.Append(result[i].ToString());
        }
        return sb.ToString();

    }        
}

It's a simple method that takes a string and returns the hash as digits. On the web server side, I go into my project and use "add existing item."

Then, I navigate to the security class in my Silverlight project, highlight it, then choose "add as link."

This allows me to share the code between the two sides. I can make a change once and ensure both are always in sync. I call this "poor man's WCF RIA." OK, bad joke. Let's move along.

In the ClientBin folder, I add a handler. I do it here because it makes it easy for Silverlight to reference the handler using a relative Uri. Otherwise, I'll have to hack around with the application root and parse strings and do lots of work I just don't care to do. This way, I can reference it as:

...
var handlerUri = new Uri("RssHandler.ashx"); 
...

And be done with it. Silverlight will pass the guid, the key, and the desired Uri. My handler will generate the key from the guid, make sure it matches what was passed, and then proxy the feed. The code looks like this:

[WebService(Namespace = "http://jeremylikness.com/rssReader")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class RssHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/xml";

        if (context.Request.QueryString["key"].Equals(SecurityToken.GenerateToken(context.Request.QueryString["guid"])))
        {
            using (var client = new WebClient())
            {
                context.Response.Write(client.DownloadString(context.Request.QueryString["rssuri"]));
            }
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Now we need to the build the service on Silverlight.

The Reader Service

First, let's start with the interface for the service. What we want is to pass in the URL of the RSS feed, and receive a list of channels with corresponding items that were fetched from the feed. That ends up looking like this:

public interface IRssReader
{
    void GetFeed(Uri feedUri, Action<List<Channel>> result);
}

Notice I'm making life easy for classes that use the service. They won't have to worry about the asynchronous nature of the service calls or how the result comes back, etc. All that is needed is to pass a method that will accept the list of channels when it becomes available.

As I mentioned earlier, we already did most of the heavy lifting with parsing out the feed, so wiring in the service is very straightforward. The implementation looks like this:

public class RssReader : IRssReader 
{
    private const string PROXY = "RssHandler.ashx?guid={0}&key={1}&rssuri={2}";

    public void GetFeed(Uri feedUri, Action<List<Channel>> result)
    {

        var client = new WebClient();

        Guid guid = Guid.NewGuid();
       
        client.DownloadStringCompleted += ClientDownloadStringCompleted;
        client.DownloadStringAsync(new Uri(
                                       string.Format(PROXY,
                                                     guid,                                                         
                                                     SecurityToken.GenerateToken(guid.ToString()),
                                                     feedUri), UriKind.Relative), result);
    }

    static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        var client = sender as WebClient;
        
        if (client != null)
        {
            client.DownloadStringCompleted -= ClientDownloadStringCompleted;
        }

        if (e.Error != null)
        {
            throw e.Error; 
        }

        var result = e.UserState as Action<List<Channel>>; 

        if (result != null)
        {
            result(e.Result.AsXDocument().AsRssChannelList()); 
        }
    }
}

Walking through the steps, we first get the Uri and the method to call when we're done. We wire up a web client and pass it the URL of our handler. This has parameters for the guid and our key, as well as the Uri we want to fetch. We also pass the method to call when we're done. The asynchronous calls all provide a generic object to pass state, so when the call returns we know which version of the call we're dealing with (nice of them, hey?)

When the call is completed, we unhook the event to avoid any dangling references. If there was an error, we throw it. (Yeah, part of our refactoring in future posts will be dealing with all of the errors I'm either throwing or not catching throughout the example). We take the state object and turn it back into an action, then pass the received value as the list of channels using our fluent extensions.

So now we can get it and load it into our models. We need a view model to host all of this!

The View Model

For the first pass on this, I'm going to wire everything myself. No fancy PRISM or MEF extensions, we can refactor those later. Let's get to showing something on the screen.

Our view model should be able to accept the URL of a feed, let the user click "load" and possibly "refresh" on the feed, then show it to us. We want to give them some feedback if the feed isn't a valid Uri, and we probably should keep the load button disabled until there is a valid feed. I ended up creating this for phase one:

public class RssViewModel : INotifyPropertyChanged
{
    private readonly IRssReader _reader; 

    public RssViewModel(IRssReader reader)
    {
        _reader = reader;
        Channels = new ObservableCollection<Channel>();
    }

    private Uri _feedUri;

    private string _uri; 

    public string FeedUri
    {
        get { return _uri; }
        set
        {
            // this will throw an error if invalid, for validation
            _feedUri = new Uri(value);
            _uri = value;
            RaisePropertyChanged("FeedUri");
            RaisePropertyChanged("CanRefresh");
        }
    }

    public bool CanRefresh { get { return _feedUri != null; }}

    public void RefreshCommand()
    {
        if (CanRefresh)
        {
            Channels.Clear();
            _reader.GetFeed(_feedUri, LoadChannels);
        }
    }

    public void LoadChannels(List<Channel> channelList)
    {
        channelList.ForEach(channel=>Channels.Add(channel));
    }

    public ObservableCollection<Channel> Channels { get; set; }

    protected void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

The view model implements INotifyPropertyChanged to support binding. In lieu of using a converter for the Uri, I decided to deal with it as a string, then cast it to a Uri. If the cast fails, it throws an error, so we can use the Silverlight validation engine to display the error. Only if the text was successfully cast to a valid Uri will we enable the refresh button. When it's clicked, we call the service and clear the list of channels, then populate the list on the return call.

A Basic Page

Now we can throw together some XAML to show it. In this first iteration I'm not about getting stylish or fancy, so I tossed together something fast. I'm using grids in lieu of stack panels so they auto-size well, and a custom ItemsControl that allows vertical scroll bars. We simply add the scroll viewer around the items presenter using a style, like this:

<Style 
    TargetType="ItemsControl" 
    BasedOn="{StaticResource ItemsControlStyle}"
    x:Name="ItemsControlOuterStyle">
    <Setter Property="ItemsControl.Template">
        <Setter.Value>
            <ControlTemplate>
                <ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
                    <ItemsPresenter />
                </ScrollViewer>
            </ControlTemplate>
        </Setter.Value>
    </Setter>            
</Style>

I know the high priests of MVVM are going to try and burn me for blasphemy with this next move, but we're still in the proof of concept, OK? So far we have no testing, IoC, nor beautiful command extensions. Yes, you are about to see a plain old code-behind event:

<TextBlock
    Grid.Column="0"
    Margin="5"
    Text="RSS Feed URL:"/>
<TextBox 
    Grid.Column="1"
    Width="200"
    Margin="5"
    Text="{Binding Path=FeedUri,Mode=TwoWay,NotifyOnValidationError=True,ValidatesOnExceptions=True}"/>
<Button
    Grid.Column="2"
    Margin="5"
    IsEnabled="{Binding Path=CanRefresh}"
    Content="Refresh"
    Click="Button_Click"/>

Here you can enter the feed. When you tab out, it will validate it and show an error if it is invalid. If it passes, the button will be enabled.

This next chunk of XAML shows the items. We'll do more refactoring as well. I will introduce the concept of formatters than will parse things like hyperlinks and Twitter hash terms to provide more interactive functionality, but for now let's just get it out there:

<ItemsControl
    Style="{StaticResource ItemsControlOuterStyle}"
    Grid.Row="1" 
    ItemsSource="{Binding Channels}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid 
                Margin="5"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Top">
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                    <HyperlinkButton 
                        Grid.Row="0"
                        Margin="5"
                        FontWeight="Bold"
                        Content="{Binding Title}"
                        NavigateUri="{Binding Link}"/>
                    <TextBlock 
                        Grid.Row="1"
                        Margin="5"
                        TextWrapping="Wrap"
                        Text="{Binding Description}"/>
                <ItemsControl 
                    Grid.Row="2"
                    Style="{StaticResource ItemsControlStyle}"
                    ItemsSource="{Binding Items}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid HorizontalAlignment="Stretch"
                                  VerticalAlignment="Top"
                                  Margin="5">
                                <Grid.RowDefinitions>
                                    <RowDefinition/>
                                    <RowDefinition/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto"/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <TextBlock 
                                    Margin="5"
                                    Grid.Row="0"
                                    Grid.Column="0"
                                    Text="{Binding PublishDate}"/>
                                <HyperlinkButton
                                    Margin="5"
                                    Grid.Row="0"
                                    Grid.Column="1" 
                                    Content="{Binding Title}"
                                    NavigateUri="{Binding Link}"/>
                                <TextBlock 
                                    Grid.Row="1"
                                    Grid.Column="0"
                                    Grid.ColumnSpan="2"
                                    TextWrapping="Wrap"
                                    Text="{Binding Description}"/>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Grid>                   
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Whew! Now we just need to put in a little bit of code behind. We'll enrage the dependency injection purists by creating hard coded instances and further stoke the ire of MVVM evangelists by wiring in a code behind for the button click:

public partial class MainPage
{
    public MainPage()
    {
        InitializeComponent();
        LayoutRoot.DataContext = new RssViewModel(new RssReader());
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ((RssViewModel)LayoutRoot.DataContext).RefreshCommand();
    }
}

Upon publishing and hitting the service, I was able to pull up my Twitter feed:

That's it. Now we have a proof of concept, and it worked. We have a lot more to do ... making it expandable to handle different types of feeds including HTML, styling it, perhaps looking at using multiple feeds, tests, and the lot (yes, I know, I know, the tests should have come earlier). I hope you enjoyed this first look into my process of creating a basic reader and we'll continue to evolve the project with time!

Download the source for this project

Jeremy Likness

Tuesday, February 2, 2010

Using Moq with Silverlight for Advanced Unit Tests

Moq is a library that assists with running unit tests by providing easily mocked objects that implement interfaces and abstract classes. You can learn more about Moq on their website. There is a distribution for Silverlight, and in this post I'll focus on some ways to use Moq for some more involved testing scenarios.

Download the source code for the example project

I started with the Simple Dialog Service in Silverlight and extended the example a bit. In the post, I promised that abstracting the dialog function behind an interface would facilitate unit testing. In this post, I'll deliver on the promise.

Adhering to the pattern I described in Simplifying Asynchronous Calls in Silverlight using Action, I created the interface for a "Thesaurus" service. In this contrived example, we are showing a list of words. You can highlight a word and see the related synonyms in another list. You may also delete the words from the list.

Because we assume in the real word that there are thousands upon thousands of available words and synonyms, the view model won't try to hold a complex object graph. I won't have a special "word" entity that has a nested list of synonyms. Instead, I'll maintain two lists: one of words, and one of the current synonyms. The service will be called when a word is selected to retrieve the list of synonyms for that word.

Enough set up ... let's take a refresher and look at the dialog service interface, along with the new thesaurus interface:

public interface IDialogService
{
   void ShowDialog(string title, string message, bool allowCancel, Action<bool> response);
}

public interface IThesaurus
{
    void GetSynonyms(string word, Action<List<string>> result);

    void ListWords(Action<List<string>> result);

    void Delete(string word);
}

As you can see, the interface is straightforward. In the sample project, I've implemented the dialog using the same code as my previous post (which involves a ChildWindow). The "implementation" of the thesaurus service actually only provides a few words and synonyms but is enough to run the application and see how it would function in the real world.

To run the actual "live" code, right-click on SimpleDialog.Web and choose "Set as startup project." Then, right-click on SimpleDialogTestPage.aspx and choose "Set as start page." Hit F5 and you'll be in business. In this screenshot, I've selected a word that we run into quite often in the development world, and you can see that it has synonyms listed for it:

The view model is straightforward. It expects an implementation of the dialog service and the thesaurus service, then manages well on its own:

public class ViewModel : INotifyPropertyChanged
{
    private readonly IThesaurus _thesaurus;

    private readonly IDialogService _dialog;

    public ViewModel()
    {
        Words = new ObservableCollection<string>();
        Synonyms = new ObservableCollection<string>();
       
        DeleteCommand = new DelegateCommand<object>( o=>ConfirmDelete(), o=>!string.IsNullOrEmpty(CurrentWord));
    }

   public ViewModel(IThesaurus thesaurus, IDialogService dialogService) : this()
    {
        _thesaurus = thesaurus;
        _dialog = dialogService;

        _thesaurus.ListWords(PutWords); 
    }

    public DelegateCommand<object> DeleteCommand { get; set; }

    public ObservableCollection<string> Words { get; set; }

    public void PutWords(List<string> words)
    {
        Words.Clear();
        foreach(string word in words)
        {
            Words.Add(word);
        }

        // default first word
        if (Words.Count > 0)
        {
            CurrentWord = Words[0]; 
        }
    }

    public ObservableCollection<string> Synonyms { get; set; }

    public void PutSynonyms(List<string> synonyms)
    {
        Synonyms.Clear();
        foreach (string synonym in synonyms)
        {
            Synonyms.Add(synonym);
        }
    }

    public void ConfirmDelete()
    {
        _dialog.ShowDialog("Confirm Delete", string.Format("Do you really want to delete {0}?", CurrentWord),
            true, b =>
                      {
                          if (b)
                          {
                              _thesaurus.Delete(CurrentWord);
                              _thesaurus.ListWords(PutWords);
                          }
                      });
    }

    private string _currentWord = string.Empty; 

    public string CurrentWord
    {
        get { return _currentWord; }
        set
        {
            _currentWord = value;
            _thesaurus.GetSynonyms(value, PutSynonyms);
            OnPropertyChanged("CurrentWord");
            DeleteCommand.RaiseCanExecuteChanged();
        }
    }

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Let's walk through it briefly. The constructor initializes the lists and the delete command, which requires that there is a CurrentWord selected. When the services are passed in, it requests the list of words and asks the service to call PutWords with the list. This will load the results and set a default "current word" based on the first item in the list.

The current word is interesting, because when it is set, it goes out to request a list of synonyms. This is populated to the synonym list. When the view model is constructed and the list of words is received, it will automatically fire a request for the synonyms by setting the current word. The current word also updates the DeleteCommand so it can be enabled or disabled based on whether or not a word is currently selected.

The delete command itself calls the dialog service for confirmation, and only if the user confirms will it then call the service, delete the word, and then request a new list of words.

This view model is written so that I need almost zero code behind in my user control. The XAML looks like this, and is driven completely by data-binding:

<UserControl x:Class="SimpleDialog.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:cal="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot" 
        HorizontalAlignment="Center"
        VerticalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions> 
        <ListBox 
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            ItemsSource="{Binding Words}"
            SelectedItem="{Binding CurrentWord, Mode=TwoWay}"
            SelectionMode="Single"
            Grid.Row="0"
            Grid.Column="0"/>
        <ListBox
            HorizontalAlignment="Center"
            VerticalAlignment="Center"            
            Width="Auto"
            ItemsSource="{Binding Synonyms}"
            Grid.Row="0"
            Grid.Column="1"/>
        <Button 
            HorizontalAlignment="Center"
            VerticalAlignment="Center"            
            Width="Auto"
            Content="Delete"
            Grid.Row="1"
            Grid.Column="0"
            cal:Click.Command="{Binding DeleteCommand}"/>
  </Grid>
</UserControl>

The key here is the bindings from the delete button to the delete command, and the list box of words to the "current word." This allows all of the other updates to cascade accordingly. I said I had "almost no" code behind. This is because I'm traveling light and decided not to drag an IoC container into the example. Therefore, in the code behind, I manually wire up the view model like this:

public MainPage()
{
    InitializeComponent();
    DataContext = new ViewModel(new Thesaurus(), new DialogService());
}  

Now that we've set the stage, the real focus of this post is how to test what we've just created. I have a view model that does quite a bit, and want to make sure it is behaving. To make this happen, I'll do two things. First, I'll add the Silverlight Unit Testing Framework. I first discussed it in my post about unit testing views AND view models. Next, I'll navigate to the Moq page and download the Silverlight bits (all of this is included in the reference project).

My test class is "view model tests." The first thing I need to do is set up some support for the tests. We want a pretend list of words and synonyms, and mocks for the services the view model depends on. Our class starts out like this:

[TestClass]
public class ViewModelTests
{
    private readonly List<string> _words = new List<string> {"test", "mock"};

    private readonly List<string> _synonyms = new List<string> {"evaluation", "experiment"};

    private readonly List<String> _mockSynonyms = new List<string> {"counterfeit", "ersatz", "pseudo", "substitute"};

    private Mock<IDialogService> _dialogMock;

    private Mock<IThesaurus> _thesaurusMock;

    private ViewModel _target;
}

We created two words with synonym lists. The mocking of the services is as simple as declaring Mock<T>. There is more to it that we'll cover, but this gets us started. I like to always have a reference to the object I am testing as target to make it clear what the test is run for.

Now we will need to set up the view model for all of our tests. Just like with the standard unit testing framework, we can flag a method as TestInitialize to do set up before each test is run. Take a look at my setup:

[TestInitialize]
public void InitializeTests()
{
    _dialogMock = new Mock<IDialogService>();

    _thesaurusMock = new Mock<IThesaurus>();

    _thesaurusMock.Setup(
        t => t.ListWords(It.IsAny<Action<List<string>>>()))
        .Callback((Action<List<string>> action) => action(_words));

    _thesaurusMock.Setup(
        t => t.GetSynonyms(It.Is((string s) => s.Equals(_words[0])), It.IsAny<Action<List<string>>>()))
        .Callback((string word, Action<List<string>> action) => action(_synonyms));

    _thesaurusMock.Setup(
        t => t.GetSynonyms(It.Is((string s) => s.Equals(_words[1])), It.IsAny<Action<List<string>>>()))
        .Callback((string word, Action<List<string>> action) => action(_mockSynonyms));

    _target = new ViewModel(_thesaurusMock.Object, _dialogMock.Object);
}

We create a new mock for every test so the internal counters are reset. Then, it gets a little interesting. The setup command allows you to determine what an expected call will be, and to provide results. Many methods return values, and there is a Result method to use for providing what those values should be. In our case, however, the methods do not return anything because they call the Action when complete. Therefore, we set up a callback so that we can perform an action when the method is fired.

To see how that works, take a look at the first set up. We are setting up our mock for the thesaurus service. The lambda expression indicates we expect the ListWords to be called, and the parameter can be any action that acts on a list of a strings. Now the important part: the callback. The callback has the same signature as the method. When the method is called, Moq will fire the callback and send the parameters. In our case, we take the action that was passed in, and call it with our list of words. This will mock the process of the view model requesting the word list, then having the PutWords method called with the actual list.

Next, we set up the GetSynonyms method twice. This is because we want to pass a different result based on the word that the method is called with. Instead of IsAny, we'll use Is with a lambda that determines what will pass. In this way, we can compare specific values or even ranges. If the passed value is the first word, we call the action with the synonym list. If the passed value is the second word ("mock"), we call the action with the list of mocks. If any other value is passed in, we simply don't care so we haven't set that up.

The first test we'll make is for setup. In other words, after the view model is constructed, we simply want to test that everything was set up appropriately. The view model promises to provide us with lists and commands, so we need to ensure these will be available when we bind to it.

[TestMethod]
public void TestConstructor()
{
    // make sure it made the call
    _thesaurusMock.Verify(t => t.ListWords(_target.PutWords), Times.Exactly(1),
                          "List words method was not called.");
    _thesaurusMock.Verify(
        t => t.GetSynonyms(It.Is((string s) => s.Equals(_words[0])), It.IsAny<Action<List<string>>>()),
        Times.Exactly(1),
        "Synonym method never called for first word.");
    Assert.AreEqual(_target.CurrentWord, _words[0], "View model did not default target word.");
    Assert.IsNotNull(_target.DeleteCommand, "Delete command was not initialized.");
    Assert.IsTrue(_target.DeleteCommand.CanExecute(null),
                  "Delete command is disabled when selected word exists.");
    CollectionAssert.AreEquivalent(_words, _target.Words, "Words do not match.");
    CollectionAssert.AreEquivalent(_synonyms, _target.Synonyms, "Synonyms do not match.");
}

The setup commands "rigged" what we expect when a method is called. If these were the only actions we took, this would really be a "stub" (something there to make it happen) rather than a mock (something that changes and can be inspected after the test to determine the outcome). With Moq, we use verify to inspect the state of the mocked object. First, we verify that the word list was called exactly once. Next, we verify that the synonym list was called specifically with the first word. Next, we are comparing values, lists, and commands to make sure they are as we expect. For example, the view model should have already populated a list of synonyms that matches the first word, so we use the CollectionAssert to make sure the lists are equivalent.

Now we can do a little more in depth test. Let's test selection. When we select the second word by setting the CurrentWord property, the view model should call the thesaurus service to retrieve the list of synonyms for 'mock.' The test looks like this:

[TestMethod]
public void TestSelection()
{
    _target.CurrentWord = _words[1]; 

    CollectionAssert.AreEquivalent(_mockSynonyms, _target.Synonyms, "Synonyms did not update.");
}

Technically, I could have verified the call as well and if you feel that is necessary, then by all means include that test. In this case, I know the synonym list simply won't update itself, so if it ends up changing to the list I'm expected, I'm confident that the call took place. Therefore, I simply test that the mock synonyms were updated to the collection of synonyms on the view model.

What about a more complicated test? Our delete command requires confirmation, so the user doesn't accidentally delete a word they did not intend to. Therefore, we need to set up the dialog service to return the results we want. We'll have two tests: one that ensures the delete service is called when the user confirms, and another that ensures it is NOT called when the user cancels. The confirm test looks like this:

[TestMethod]
public void TestDeleteConfirm()
{
    _thesaurusMock.Setup(t => t.Delete(It.IsAny<string>())); 

    _dialogMock.Setup(
        d => d.ShowDialog(It.IsAny<string>(),
                          It.IsAny<string>(),
                          It.IsAny<bool>(),
                          It.IsAny<Action<bool>>()))
        .Callback(
        (string title, string message, bool cancel, Action<bool> action) => action(true));

    _target.DeleteCommand.Execute(null);

    _thesaurusMock.Verify(
        t => t.Delete(It.Is((string s) => s.Equals(_words[0]))),
        Times.Exactly(1),
        "The delete method was not called on the service.");
}

First we set up the service to expect the delete call. Next, we set up the dialog. We don't care about the parameters passed in. All we care about is that we call the action with "true" to simulate a user confirming the dialog. Once this is set up, we trigger the delete command, and verify that the delete service was called for the appropriate word.

For the cancel, we pass false in the action, and use Times.Never() on the method signature to ensure the delete service was not called.

Finally, because our delete command is only enabled when a current word is selected, we need to test that it is disabled with no words:

[TestMethod]
public void TestDeleteEnabled()
{
    _target.CurrentWord = string.Empty; 

    Assert.IsFalse(
        _target.DeleteCommand.CanExecute(null),
        "Delete command did not disable with empty word selection.");
}

We already tested for the positive case in the constructor. Now, we simply clear the selection and confirm that the command is no longer allowed to execute.

If you ran the application earlier, you simply need to set the "test" project as the start-up project to run the unit tests. They will run directly in the browser.

As you can see, using the MVVM pattern appropriately ensures straightforward XAML (mostly binding-driven without cluttered code-behind) and very granular testing. Tools like Moq can make it much easier to test complicated scenarios by allowing you to easily set up dependencies, mock returns, and ultimately validate that the view model is behaving the way it is expected to.

Download the source code for the example project

Jeremy Likness

Friday, January 29, 2010

Programmatically Accessing the Live Smooth Streaming API

Live Smooth Streaming is a Microsoft technology that allows you to take a live, encoded, incoming video stream and rebroadcast it using Smooth Streaming technology. This technology multicasts the video stream in segments of varying bandwidths. This can then be played with a Silverlight-based client like the built-in MediaElement or more advanced player like the Silverlight Media Framework.

The incoming streams could be from your web cam or third party sources, or even from a file encoded on disk that is being webcast at a particular point in time. The live smooth streaming allows the client to adjust to the current network load and gracefully degrade quality when the network slows to avoid having to pause the playback and force the user to wait for a new buffer. The user can also rewind the "live content," and there are options to archive it to play on demand at a later date.

A content network with many live streams might have multiple servers and cabinets in their data centers to serve content. In that scenario, programmatic management of endpoints becomes essential to effectively scale the operation. If you find yourself needing to automate some aspects of starting, stopping, shutting down or creating publishing points for live streaming, you're in luck!

Let's start with a few entities to help us handle publishing points. A publishing point can have a stream state (the status of the encoding stream it is listening to), and archive state (the status of the stream it is archiving to) and a fragment stream that enables insertion of other content to the stream. These various nodes on the publishing point share a common set of states:


public enum State
{
    Disabled,
    Started,
    Stopped,
    Unknown
}

These are fairly self-explanatory. "Unknown" simply means the publishing point is in a status, such as stopped or shut down, when it doesn't make sense for the node to have a valid status.

The publishing point itself has a more involved list of states. For an excellent overview, read this article on creating and managing publishing points. Here are the states:


public enum PublishingPointState
{
    Idle,
    Starting,
    Started,
    Stopping,
    Stopped,
    Shuttingdown,
    Error,
    Unknown
}

Again, these are fairly self-explanatory. Idle happens when the publishing point has been created, but no action has been taken against it, or it is shut down. Starting indicates it is ready to receive a feed, and started means it is actively processing one.

Let's go ahead and build an entity to represent the publishing point:


public class PublishingPoint
{        
    public State StreamState { get; set; }

    public State ArchiveState { get; set; }

    public State FragmentState { get; set; }

    public PublishingPointState PubState { get; set; }

    public string SiteName { get; set; }

    public string Path { get; set; }

    public string Name { get; set; }
}

The first few properties are the various states of the nodes and the publishing point itself. The site name is the website it is configured on. This will usually be "Default Web Site." The Path is the virtual path (not the physical path) the publishing point resides in (also known as the Application), and the name is the actual name of the publishing point.

While there is not a strongly typed API to interface directly with the live smooth streaming configuration as of this writing, we can easily reach it through the new administration classes. With IIS 7.0 and smooth streaming installed, you should be able to find Microsoft.Web.Administration.dll in your %windir%\system32\inetsrv directory. Reference this DLL, and you can programmatically access web sites. You can also interact with configurations through a reflection-style interface that we'll cover here.

Get the List of Publishing Points

Our first task is to get a list of publishing points.


private const string LIVESTREAMINGSECTION = "system.webServer/media/liveStreaming";
private const string METHODGETPUBPOINTS = "GetPublishingPoints";
private const string ATTR_SITENAME = "siteName";
private const string ATTR_VIRTUALPATH = "virtualPath";
private const string ATTR_NAME = "name";
private const string ATTR_ARCHIVES = "archives";
private const string ATTR_FRAGMENTS = "fragments";
private const string ATTR_STREAMS = "streams";
private const string ATTR_STATE = "state";
        
public List<PublishingPoint> GetPublishingPoints()
{
    var retVal = new List<PublishingPoint>();

    using (var serverManager = new ServerManager())
    {
        Configuration appHost = serverManager.GetApplicationHostConfiguration();

        try
        {
            ConfigurationSection liveStreamingConfig = appHost.GetSection(LIVESTREAMINGSECTION);

            foreach (Site site in serverManager.Sites)
            {
                foreach (Application application in site.Applications)
                {
                    try
                    {
                        ConfigurationMethodInstance instance =
                            liveStreamingConfig.Methods[METHODGETPUBPOINTS].CreateInstance();

                        instance.Input[ATTR_SITENAME] = site.Name;
                        instance.Input[ATTR_VIRTUALPATH] = application.Path;

                        instance.Execute();

                        ConfigurationElement collection = instance.Output.GetCollection();

                        foreach (var item in collection.GetCollection())
                        {
                            retVal.Add(new PublishingPoint
                                           {
                                               SiteName = site.Name,
                                               Path = application.Path,
                                               Name = item.Attributes[ATTR_NAME].Value.ToString(),
                                               ArchiveState = (State) item.Attributes[ATTR_ARCHIVES].Value,
                                               FragmentState = (State) item.Attributes[ATTR_FRAGMENTS].Value,
                                               StreamState = (State) item.Attributes[ATTR_STREAMS].Value,
                                               PubState =
                                                   (PublishingPointState) item.Attributes[ATTR_STATE].Value
                                           });
                        }
                    }
                    catch (COMException ce)
                    {
                        Debug.Print(ce.Message);
                    }
                }
            }
        }
        catch (COMException ce)
        {
            Debug.Print(ce.Message);
        }
    }

    return retVal;
}

The ServerManager is our hook into administration. All of the configuration for the live smooth streaming is in the APPHOST section of the configuration, which we fetch at the beginning of the method by grabbing the configuration and then navigating to system.webServer/media/liveStreaming.

The method to fetch publishing points requires a web site and an application (virtual directory). We iterate through these and use the ConfigurationMethodInstance to ask for the this. The new IIS configuration extensions allow methods and API hook points to be defined in the configuration itself, with a set of inputs and outputs. You can read more about the ConfigurationMethod. We use this and pass in the web site name and application, to receive the list of publishing points. Notice how we get a generic collection of ConfigurationElement and reference the attributes to build our more strongly-typed PublishingPoint object.

Of course, there are multiple areas where exceptions may be thrown. In the example, I capture the COM errors and just print them to debug. You can interrogate the error code and provide more specific feedback as to why the call failed.

Starting, Stopping, and Shutting Down Publishing Points

Now that we have a publishing point, we can stop, start, and shut it down. This is also done through a configuration method. The method names for the action are:


public enum PublishingPointCommand
{
    Start,
    Stop,
    Shutdown
}

The method names are the actual text, so we can use the ToString() method on the enum to pass the command. Issuing a command against a specific publishing point now looks like this:


private static void _IssueCommand(PublishingPoint publishingPoint, PublishingPointCommand command)
{
    using (var serverManager = new ServerManager())
    {
        Configuration appHost = serverManager.GetApplicationHostConfiguration();

        ConfigurationSection liveStreamingConfig = appHost.GetSection(LIVESTREAMINGSECTION);

        if (liveStreamingConfig == null)
        {
            throw new Exception("Couldn't get to the live streaming section.");
        }

        ConfigurationMethodInstance instance =
            liveStreamingConfig.Methods[METHODGETPUBPOINTS].CreateInstance();

        instance.Input[ATTR_SITENAME] = publishingPoint.SiteName;
        instance.Input[ATTR_VIRTUALPATH] = publishingPoint.Path;

        instance.Execute();

        // Gets the PublishingPointCollection associated with the method output
        ConfigurationElement collection = instance.Output.GetCollection();

        foreach (var item in collection.GetCollection())
        {
            if (item.Attributes[ATTR_NAME].Value.ToString().Equals(publishingPoint.Name))
            {
                var method = item.Methods[command.ToString()];
                var methodInstance = method.CreateInstance();
                methodInstance.Execute();
                break;
            }
        }
    }
}

Of course, you can probably see a place where it makes sense to refactor some code, because we're spinning through the collection again. This time, instead of turning it into a concrete type, we are taking the specific item in the collection for the publishing point we're targeting, then creating an instance of the command method and firing it off. Simple as that!

Creating the Publishing Point

So now we can manipulate and gather information about a point, but what about creating it? If you are frustrated trying to find where in the API you can call a "Create" method, take a deep breath and step away from the configuration collection. It's not there. To create a publishing point, we simply drop a file on the system! That's right. If you create a new publishing point, you can navigate to the file system and set an .isml file. Open it in notepad and you'll find the format is straightforward:

<?xml version="1.0" encoding="utf-8"?>
   <smil xmlns="http://www.w3.org/2001/SMIL20/Language">
      <head>
         <meta name="title" content="Pub Point Title" />
         <meta name="module" content="liveSmoothStreaming" />
         <meta name="sourceType" content="Push" /><!-- or Pull -->
         <meta name="publishing" content="Fragments;Streams;Archives" />
         <meta name="estimatedTime" content="00:11:22" />
         <meta name="lookaheadChunks" content="2" />
         <meta name="manifestWindowLength" content="0" />
         <meta name="startOnFirstRequest" content="False" />
         <meta name="archiveSegmentLength" content="0" />
      </head>
   <body/>
</smil>

That's it ... very straightforward. Give it a title, make it push or pull, and estimate the time. Of course, you can manipulate some of the more advanced features as well, but for a basic interface, this is all we need. We'll store the XML with a constant that holds the template called ISML_TEMPLATE. When the user requests a new publishing point, we'll find the right virtual directory, get the physical path, and then write out the file:

public enum LiveSourceType
{
    Push,
    Pull
}

public bool CreatePublishingPoint(PublishingPoint publishingPoint, string title, string duration, LiveSourceType type)
{

    bool retVal = false;

    using (var manager = new ServerManager())
    {
        Site site = manager.Sites[publishingPoint.SiteName];

        Application application = site.Applications[publishingPoint.Path];

        string template =
            string.Format(ISML_TEMPLATE, title, type, duration ?? string.Empty);

        try
        {
            string path = string.Format(@"{0}\{1}", application.VirtualDirectories[0].PhysicalPath,
                                        publishingPoint.Name);

            File.WriteAllText(path, template);

            retVal = true;
        }
        catch (Exception ex)
        {
            Debug.Print(ex.Message);
        }
    }

    return retVal;
}

This is fairly straightforward to give you the point. In production, you'll need to test for nulls (i.e. if the site doesn't exist, a null template is passed in, etc) and may want to validate that it was created successfully by enumerating the list after creation. I'd also recommend creating an XmlDocument or XDocument for more advanced titles ... in this example, using string format, we can make it fast but must make sure the title is clean or escape it before making it part of the source XML.

That's it ... in a nutshell, you now have all of the bits and pieces needed to interface programmatically with the Live Smooth Streaming APIs. I have no sample project because this is intended to be a guideline for your own explorations and use of the system. I would also suggest the excellent blog by Ezequiel Jadib which contains loads of information about smooth streaming.

Jeremy Likness

Wednesday, January 27, 2010

Introduction to Debugging Silverlight Applications with WinDbg

I've had a few users ask me about finding memory leaks and understanding what happens with references in Silverlight. One very powerful tool to use when debugging Silverlight applications is the Windows Debugging Tools. You can download the 32-bit (x86) version side-by-side with the 64-bit (x64) version.

Both WPF and Silverlight ship with an extension DLL you can load called SOS. This extension contains many powerful commands.

In the video, Silverlight Debugging with WinDbg (30 minutes long), I walk through a debugging scenario using my Fractal Koch Snowflakes.

I show how to dump the heap, walk object references, see which references are targetted for garbage collection and which ones still have root references, examine event handlers and delegates to trace back to the target methods, an unroll lists and arrays. It's sort of a "firehose" approach but with a real world example that I hope helps drive home how powerful it can be.

Watch the video by clicking here (30 minutes).

Jeremy Likness

Saturday, January 23, 2010

Simple Dialog Service in Silverlight

I noticed on the forums there are a lot of users not comfortable with asynchronous programming who struggle a bit in Silverlight with getting their arms around the concept of a dialog box. In other environments, you can simply shoot out a dialog, wait for the response, and continue. In Silverlight, of course, the action is asynchronous. I would argue it should be this way most of the time.

The problem is that many people tend to take the approach of trying to force the process into a synchronous one, instead of changing the way they think and approach the application. There is a reason why processes are asynchronous in Silverlight. There is one main UI thread, and a blocking process would block the entire thread and effectively freeze the Silverlight application. Having the process asynchronous allows you to continue to render graphics elements, perform actions in the background, even display a soothing animation while you await the user's response.

I spoke to a more highly decoupled approach in a post awhile ago that was more an experiment with the event aggregator: Decoupled Child Window Dialogs with Silverlight and PRISM. Here, I want to show the more straightforward approach.

The first step is to choose what the dialog will be displayed with. In Silverlight, the ChildWindow makes perfect sense because it is a modal dialog that appears, waits for the user response, and then saves the response. We'll create a new child window and call it Dialog.xaml. It looks like this:

<controls:ChildWindow x:Class="SimpleDialog.Dialog"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
           Width="400" Height="300" 
           Title="{Binding Title}">
    <Grid x:Name="LayoutRoot" Margin="2">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBlock TextWrapping="Wrap" Grid.Row="0" Text="{Binding Message}"/>
        <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
        <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
    </Grid>
</controls:ChildWindow>

You'll notice I made very few changes from the provided template. The key here is that I changed the title to bind with the Title property, and added a text block to display a message from the Message property.

Because this is a simple dialog box, I really feel a view model is overkill. Some purists will insist on this but I argue the functionality is simple enough that we don't need the extra overhead. We'll be using an interface to the solution down the road that we can easily unit test, and this makes the dialog function (which lives entirely in the UI) a self-contained implementation.

Next, I made a few changes to the code behind:

public partial class Dialog : ChildWindow
{
    public Action<bool> CloseAction { get; set; }

    public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(
        "Message",
        typeof(string),
        typeof(Dialog),
        null);


    public string Message
    {
        get { return GetValue(MessageProperty).ToString(); }
        set { SetValue(MessageProperty, value); }
    }

    public Dialog()
    {
        InitializeComponent();
        DataContext = this;
    }        

    public Dialog(bool allowCancel)
        : this()
    {
        CancelButton.Visibility = allowCancel ? Visibility.Visible : Visibility.Collapsed;
    }

    private void OKButton_Click(object sender, RoutedEventArgs e)
    {
        this.DialogResult = true;            
    }

    private void CancelButton_Click(object sender, RoutedEventArgs e)
    {
        this.DialogResult = false;           
    }
}

Again, not too many changes here. I added the Message property as a dependency property, and in the constructor I set the data context to itself. This allows me to bind to the title and message. This allows us to simply set the message on the dialog and have it appear. I also added an action for it to retain when closed. This will store a callback so that it can notify the host of the user's final actions. Finally, there is a method that conditions whether or not there is the option for a cancel button. For alerts, we'll simply show an OK button. For confirmations, we'll show the Cancel button as well.

Next is a simple interface to the dialog. Nothing in our application should know or care how the dialog is displayed. There is simply a mechanism to display the dialog and possibly acquire a response. The interface looks like this:

public interface IDialogService
{
    void ShowDialog(string title, string message, bool allowCancel, Action<bool> response);
}

In our simple demonstration, I'm allowing for a title, a message, whether or not you want to show the cancel button for confirmations, and then an action to call with the response. With this simple interface we have all we need to wire in unit tests for services and controls that rely on the dialog. You can create your own mock object that implements the IDialogService interface and returns whatever response you want to stage for the unit test.

In the production application, we'll need to show a real dialog. Here is the class that handles it:

public class DialogService : IDialogService
{
    #region IDialogService Members

    public void ShowDialog(string title, string message, bool allowCancel, Action<bool> response)
    {
        var dialog = new Dialog(allowCancel) {Title = title, Message = message, CloseAction = response};
        dialog.Closed += DialogClosed;
        dialog.Show();
    }

    static void DialogClosed(object sender, EventArgs e)
    {
        var dialog = sender as Dialog;
        if (dialog != null)
        {
            dialog.Closed -= DialogClosed; 
            dialog.CloseAction(dialog.DialogResult == true);
        }
    }

    #endregion
}

This is fairly straightforward. When called, we'll create an instance of the dialog and set the various properties, including the callback. We wire into the closed event. Whether the user responds by clicking a button or closing the dialog, this event is fired.

There is a reason why we are using the snippet DialogResult == true. The result is null-able, so we cannot simply refer to the value itself and make a true/false decision (null, by definition, is unknown). So only if the user explicitly provides a true response by clicking the OK button will the expression evaluate to true. Otherwise, we assume false and call back with the response.

There is also a very important step here that is important to recognize. Many beginners fail to catch this subtle step and end up with memory leaks. When the closed event fires, the dialog box effectively closes. Typically, there would be no more references to it (it is no longer in the visual tree) and it can be cleaned up by garbage collection. However, there is a fatal mistake you can make that will result in the dialog box never going away.

That mistake has to do with how events work. When we register the closed event, the thought process is often that the dialog box has an event, and therefore knows to call back to the dialog service. This is flawed, however. A reference exists from the dialog service to the dialog box. The dialog service effectively "listens" for the event, and when it is raised, will respond. We must unregister the event like this:

dialog.Closed -= DialogClosed;

Otherwise, the reference remains and garbage collection will never claim the dialog box resource. In a long running application, this could prove to be a serious flaw. This line is not included in the code sample download. I encourage you to run with windbg or even step through debug in Visual Studio and watch the object graphs and reference counts as you fire multiple dialogs. Then, add the line of code above and re-run it to see the difference when you appropriately unregister the event.

To demonstrate the use of the service, I put together a quick little page with a few buttons and a text block:

<UserControl x:Class="SimpleDialog.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" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
        <StackPanel Orientation="Vertical">
            <Button x:Name="ToggleEnabled" 
                    HorizontalAlignment="Center"
                    Margin="5" Width="Auto" Content="Disable Dialog Button" Click="ToggleEnabled_Click"/>
            <Button x:Name="DialogButton" 
                    HorizontalAlignment="Center"
                    Margin="5" Width="Auto" Content="DialogButton" Click="DialogButton_Click"/>
            <TextBlock x:Name="TextDialog" 
                       HorizontalAlignment="Center"
                       Margin="5" Width="Auto" Text="Result Will Show Here"/>
        </StackPanel>
    </Grid>
</UserControl>

The first button is a toggle to enable or disable the second button. It shows how to receive a response and act based on the user input. If the user confirms, the button is toggled to enabled or disabled. If the user cancels or closes the dialog, the state of the button remains the same. The second button raises a dialog, and simply shows the result. Because it is an alert dialog, we know a false response indicates the user closed the window instead of clicking OK.

Here is the code behind:

public partial class MainPage : UserControl
{
    private bool _toggleState = true;
    private readonly IDialogService _dialog = new DialogService();

    public MainPage()
    {
        InitializeComponent();
    }

    private void ToggleEnabled_Click(object sender, RoutedEventArgs e)
    {
        _dialog.ShowDialog(
            _toggleState ? "Disable Button" : "Enable Button",
            _toggleState
                ? "Are you sure you want to disable the dialog button?"
                : "Are you sure you want to enable the dialog button?",
            true,
            r =>
                {
                    if (r)
                    {
                        _toggleState = !_toggleState;
                        DialogButton.IsEnabled = _toggleState;
                        ToggleEnabled.Content = _toggleState ? "Disable Dialog Button" : "Enable Dialog Button";
                    }
                });
    }

    private void DialogButton_Click(object sender, RoutedEventArgs e)
    {
        _dialog.ShowDialog(
            "Confirm This",
            "You have to either close the window or click OK to confirm this.",
            false,
            r => { TextDialog.Text = r ? "You clicked OK." : "You closed the dialog."; });
    }
}

Notice that in the click events, we call to the dialog service and pass it anonymous methods for the return types. We could point to real methods on the class as well. The important part is to change your thought process from synchronous step one => wait => step two to asynchronous step one => delegate to step two, then step two is called when ready.

In a production application, instead of creating an instance of the dialog box, we would either register it with a container:

Container.RegisterInstance<IDialogService>(Container.Resolve<DialogService>());

And inject it in a constructor, or use something like MEF and import the dialog service:

[Import]
public IDialogService Dialog { get; set; }

We would simply flag the implementation as the export or use the InheritedExport attribute on the interface itself.

Click here to download the source code for this example.

Jeremy Likness