Archive

Archive for the ‘C#’ Category

C# Static Field Initializers

January 18th, 2012 No comments

I hit a problem recently where a singleton I was calling from an assembly resolver was throwing an exception. It turned out that the sync object used in the lock for the singleton pattern was null. How was this possible? Look at the code below:

using System;

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static readonly object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get
      {
         if (instance == null)
         {
            lock (syncRoot)
            {
               if (instance == null)
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}

How can this be, my static readonly field should be set by the field initializer. This should be run before it’s first usage. Normally, this is true but for some reason this was not the case. The C#spec though gives us a workaround, implement a static constructor. The section on static constructors states:

If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor.

Therefore, if we add a static constructor to our Singleton class, we get guaranteed initialization of the static field initializers before it is run, also:

The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • An instance of the class is created.
  • Any of the static members of the class are referenced.

Therefore our static constructor will run before our singleton Instance property.

Categories: C#, Programming Tags:

Building an Auto Complete control with Reactive Extensions (Rx)

November 22nd, 2011 1 comment

I have been meaning to get into Rx for a while now and haven’t quite found the excuse or opportunity to do so. While playing with SignalR it became apparent that Rx was something that could help and while I was researching it I seen a lot of people talking about using Rx in UI frameworks and I thought, hmmm, that sounds interesting.

So I set myself a challenge, I wanted to use Rx to create an auto-complete WPF control with some of the major use cases I have seen in these types of controls.

The App Shell

First thing I was going to need was a WPF application with a MainWindow that would hold my text box, the results and a log window.

 CropperCapture[1]

The XAML looks something like this:

<Window
    x:Class="AutoCompleteWithRx.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="AutoComplete with Rx"
    Height="451"
    Width="825"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:AutoCompleteWithRx="clr-namespace:AutoCompleteWithRx"
    mc:Ignorable="d"
    d:DataContext="{d:DesignInstance AutoCompleteWithRx:AutoCompleteViewModel}"
    FocusManager.FocusedElement="{Binding ElementName=SearchBox}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition
                Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock
            FontFamily="Segoe WP Light"
            FontSize="26.667"
            Text="Auto-Complete Sample"
            Grid.ColumnSpan="2" 

            />

        <StackPanel
            Grid.Row="2">
            <Label>Search</Label>
            <TextBox
                x:Name="SearchBox"
                Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}"/>
            <ProgressBar Height="19" IsIndeterminate="True"/>
            <ListBox
                ItemsSource="{Binding SearchResults}" />
        </StackPanel>
        <StackPanel Grid.Column="1" Orientation="Vertical" Grid.Row="1" d:LayoutOverrides="Height">
            <Label>Log</Label>
            <ListBox
                ItemsSource="{Binding LogOutput}" />
        </StackPanel>
    </Grid>
</Window>

So that is basically the view for now. I have cheated and just instantiated my viewmodel in the code behind class for now.

public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();
        DataContext = new AutoCompleteViewModel();
    }
}

Now that we have a window I need to get my view model up to scratch. I started with simply satisfying the data properties required by my form.

public class AutoCompleteViewModel : INotifyPropertyChanged {

    private string searchText;

    public string SearchText {
        get { return searchText; }
        set {
            if (searchText == value) {
                return;
            }
            searchText = value;
            NotifyPropertyChanged("SearchText");
        }
    }

    private readonly ObservableCollection<string> logOutput = new ObservableCollection<string>();

    public ObservableCollection<string> LogOutput {
        get { return logOutput; }
    }

    private readonly ObservableCollection<string> searchResults = new ObservableCollection<string>();

    public ObservableCollection<string> SearchResults {
        get { return searchResults; }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void NotifyPropertyChanged(string propertyName) {
        if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

 

Subscribing to Property Changed Events using Rx

OK. So that is simple enough but now I need to make my textbox do something when the user types into it. Before I start doing this though I will need to add Rx to my project. Right click the project choose “Manage Nuget Packages” and search for Rx, install Rx-Main and Rx-WPF.

Let’s start by simply logging the fact that the user has typed something. Add a constructor to our view model class with the following code:

public AutoCompleteViewModel() {
    // Listen to all property change events on SearchText
    var searchTextChanged = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
        ev => PropertyChanged += ev,
        ev => PropertyChanged -= ev
        )
        .Where(ev => ev.EventArgs.PropertyName == "SearchText");

    // Transform the event stream into a stream of strings (the input values)
    var input = searchTextChanged
        .Select(args => SearchText);

    // Log all events in the event stream to the Log viewer
    input.ObserveOn(DispatcherScheduler.Instance)
        .Subscribe(e => LogOutput.Insert(0,
            string.Format("Text Changed. Current Value - {0}", e)));
}

The first section of slightly unwieldy syntax creates an IObservable from the PropertyChanged event of INotifyPropertyChanged which our view model implements. You can think of the IObservable as a stream of events that will happen or a collection of future objects that will be added to each time the event is raised. Our code will then filter those events to only those concerning the SearchText that our textbox is bound to.

The next line transforms the type of the events in our IObservable from PropertyChangeEventsArgs to string, the content of the textbox. Much more useful.

Finally we need to subscribe to the event stream and do something with the string, firstly though we tell the subscription that we want to observe the events on the WPF dispatcher (This helper singleton comes from the Rx-WPF package). Then we simply provide an inline function to execute for each event, in our case inserting into the log stack which our LogOutput list box is bound to.

The result looks like this.

CropperCapture[2]

OK. So far so good. Now let’s add an actual search to the mix.

Chaining the Asynchronous Search

Before I add my search function I want to create a structure that will encapsulate the search term and it’s result.

public struct SearchResult {
    public string SearchTerm { get; set; }
    public IEnumerable<string> Results { get; set; }
}

Next I add my search function. For now I’ve just created a synchronous function but chances are you would be calling an external service with Async methods (BeginXXX and EndXXX) for which you should use the FromAsyncPattern method instead of the ToAsync I am using.

private SearchResult DoSearch(string searchTerm) {
    return new SearchResult {
        SearchTerm = searchTerm,
        Results =
            phrases.Where(item => item.ToUpperInvariant().Contains(searchTerm.ToUpperInvariant())).ToArray()
    };
}

private readonly string[] phrases = new[] {
    "The badger knows something",
    "Your head looks like a pineapple",
    "etc...",
};

And now for the magic. To invoke our search we add the following to our constructor:

// Setup an Observer for the search operation
var search = Observable.ToAsync<string, SearchResult>(DoSearch);

// Chain the input event stream and the search stream
var results = from searchTerm in input
              from result in search(searchTerm)
              select result;

// Log the search result and add the results to the results collection
results.ObserveOn(DispatcherScheduler.Instance)
.Subscribe(result => {
    searchResults.Clear();
    LogOutput.Insert(0, string.Format("Search for '{0}' returned '{1}' items", result.SearchTerm, result.Results.Count()));
    result.Results.ToList().ForEach(item => searchResults.Add(item));
    }
);

Here we firstly call ToAsync, this will create a function that takes a string (our search term) and returns an Observable that will only ever produce one event (the Completed / End) and then close.

We chain the incoming input stream with the result of the search function using simplified LINQ syntax and produce a new observable of SearchResult. We then observe the result, logging and updating the autocomplete items.

The result is this:

CropperCapture[4]

OK. So this is round about where my mind exploded and grey matter started to leak out of my ears. Basically what is happening is we are treating these incoming events as collections before they actually happen, then we can manipulate them using LINQ and even chain the events much like pipelining in UNIX / Powershell.

We’re not done yet. We still have a number of issues.

Using Throttle to enforce an idle period before searching

One of the issues you can see in the above screenshot is that the search was done after every single key press. The owner of the service we are calling will not be too happy with us flooding them with unnecessary searches, so how do we stop this from happening. Typically we would create a timer that would wait for a period of inactivity before searching, we would have to reset the timer every time the user typed something so that the search is not performed for each of the previous characters and there would be quite a few lines of code required to actually do this.

With Rx we can use the Throttle operator which will quite effectively do exactly the behaviour we want for free. We change our previous declaration of the input stream to add the Throttle method.

var input = searchTextChanged
    .Throttle(TimeSpan.FromMilliseconds(400))
    .Select(args => SearchText);

Now if we test we should get something like the following:

CropperCapture[5]

That was too easy.

Merging two event streams

The next requirement was that I may want a larger throttle timeout for strings of less than 3 characters as people tend to type slower at the start of a search. To do this I needed to split my input stream into two different event streams that could be throttled differently.

var input = searchTextChanged
    .Where(ev => SearchText == null || SearchText.Length < 4)
    .Throttle(TimeSpan.FromSeconds(3))
    .Merge(searchTextChanged
        .Where(ev => SearchText != null && SearchText.Length >= 4)
        .Throttle(TimeSpan.FromMilliseconds(400)))
    .Select(args => SearchText);

So above I have simply cut the searchTextChanged stream 2 different ways, throttled them differently and then I can use the Merge operator to join the streams back together again into one.

Creating a Reactive ICommand for MVVM

The next requirement is that the search should be executed immediately if the user hits the enter key. To do this I decided to use the MVVM ICommand pattern. We need to add the following Input KeyBinding to the TextBox in our XAML so that the enter key will be picked up and we point it at the command we will write below.

<TextBox
    x:Name="SearchBox"
    Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}">
    <TextBox.InputBindings>
        <KeyBinding
            Command="{Binding TextBoxEnterCommand}"
            Key="Enter" />
    </TextBox.InputBindings>
</TextBox>

The next thing we need to do is create our own command type. If you use an MVVM framework that understands Rx like ReactiveUI then you should get this for free but implementing a simple version yourself is not difficult. We simply take the RelayCommand defined by Josh Smith and add a Subject<T> exposed as an Observable.

public class ReactiveRelayCommand : ICommand {
    private readonly Action<object> execute;
    private readonly Predicate<object> canExecute;

    public ReactiveRelayCommand(Action<object> execute)
        : this(execute, null) {
    }

    public ReactiveRelayCommand(Action<object> execute, Predicate<object> canExecute) {
        if (execute == null)
            throw new ArgumentNullException("execute");

        this.execute = execute;
        this.canExecute = canExecute;
    }

    [DebuggerStepThrough]
    public bool CanExecute(object parameter) {
        return canExecute == null || canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter) {
        execute(parameter);
        executed.OnNext(parameter);
    }

    private readonly Subject<object> executed = new Subject<object>();

    public IObservable<object> Executed {
        get { return executed; }
    }
}

Notice that it exactly the same as the standard RelayCommand except that we use a Subject<object> as the backing implementation for our IObservable. We call OnNext whenever the command is Executed.

Add the following field and property to the viewmodel class to store our command:

private ReactiveRelayCommand textBoxEnterCommand;
public ReactiveRelayCommand TextBoxEnterCommand {
    get { return textBoxEnterCommand; }
    set { textBoxEnterCommand = value; }
}

Then at the start of our constructor we setup the command itself:

// Setup the command for the enter key on the textbox
textBoxEnterCommand = new ReactiveRelayCommand(obj => { });

Next we need to change our input event stream to take into account our command and merge that with our SearchText property change events so that either can fire our search:

// Transform the event stream into a stream of strings (the input values)
var input = searchTextChanged
    .Where(ev => SearchText == null || SearchText.Length < 4)
    .Throttle(TimeSpan.FromSeconds(3))
    .Merge(searchTextChanged
        .Where(ev => SearchText != null && SearchText.Length >= 4)
        .Throttle(TimeSpan.FromMilliseconds(400)))
    .Select(args => SearchText)
    .Merge(
        textBoxEnterCommand.Executed.Select(e => SearchText));

Notice we have just added the last line to merge the Executed observable on our command. Now when we run we can type a single character and hit enter if we do not want to wait for the idle period. How easy was that? Are we done? Almost.

Removing duplicate consecutive events

We still have an issue that when the user presses Enter, the idle timeout will expire some time later and we will get another event firing, essentially performing our search twice. So how do we stop the second duplicate event from being fired, easy, we just use DistinctUntilChanged.

We want a distinct search but we still want to allow the same search to be done later if the user tries another search in between. In other words we can have the same search done twice as long as they aren’t consecutive searches.

// Transform the event stream into a stream of strings (the input values)
var input = searchTextChanged
    .Where(ev => SearchText == null || SearchText.Length < 4)
    .Throttle(TimeSpan.FromSeconds(3))
    .Merge(searchTextChanged
        .Where(ev => SearchText != null && SearchText.Length >= 4)
        .Throttle(TimeSpan.FromMilliseconds(400)))
    .Select(args => SearchText)
    .Merge(
        textBoxEnterCommand.Executed.Select(e => SearchText))
    .DistinctUntilChanged();

 

Cancelling previous searches with TakeUntil

The last issue here is that when searches return out of sequence, we could get the wrong results displayed. For example, the user searches for cr hits enter but then types crazy and hits enter. If the first search is taking a long time because of the number of results then the results for it will end up being displayed after the actual current search term is displayed. To simulate this we could add some latency to our search.

private readonly Random random = new Random(5);
private SearchResult DoSearch(string searchTerm) {
    Thread.Sleep(random.Next(100, 500)); // Simulate latency
    return new SearchResult {
        SearchTerm = searchTerm,
        Results =
            phrases.Where(item => item.ToUpperInvariant().Contains(searchTerm.ToUpperInvariant())).ToArray()
    };
}

To solve this we need to stop the Async stream when more input is given, this is pretty easy with the TakeUntil operator. Take operators define a completion for an event stream. In the case of an Async operation this will effectively cancel the Async subscription. TakeUntil takes an observable as input such that an event on that stream will complete the current stream. To implement this change we simply say the we TakeUntil the input stream in our chaining code.

// Chain the input event stream and the search stream, cancelling searches when input is received
var results = from searchTerm in input
              from result in search(searchTerm).TakeUntil(input)
              select result;

Summary

So we have managed to create the guts of an auto-complete control using Rx in a much more declarative way by responding to events in observables instead of writing lots of imperative code with little items of state sitting about to represent our state machine.

All of the heavy work can be easily seen in a single declaration of intent:

// Setup the command for the enter key on the textbox
textBoxEnterCommand = new ReactiveRelayCommand(obj => { });

// Listen to all property change events on SearchText
var searchTextChanged = Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
    ev => PropertyChanged += ev,
    ev => PropertyChanged -= ev
    )
    .Where(ev => ev.EventArgs.PropertyName == "SearchText");

// Transform the event stream into a stream of strings (the input values)
var input = searchTextChanged
    .Where(ev => SearchText == null || SearchText.Length < 4)
    .Throttle(TimeSpan.FromSeconds(3))
    .Merge(searchTextChanged
        .Where(ev => SearchText != null && SearchText.Length >= 4)
        .Throttle(TimeSpan.FromMilliseconds(400)))
    .Select(args => SearchText)
    .Merge(
        textBoxEnterCommand.Executed.Select(e => SearchText))
    .DistinctUntilChanged();

// Log all events in the event stream to the Log viewer
input.ObserveOn(DispatcherScheduler.Instance)
    .Subscribe(e => LogOutput.Insert(0,
        string.Format("Text Changed. Current Value - {0}", e)));

// Setup an Observer for the search operation
var search = Observable.ToAsync<string, SearchResult>(DoSearch);

// Chain the input event stream and the search stream, cancelling searches when input is received
var results = from searchTerm in input
              from result in search(searchTerm).TakeUntil(input)
              select result;

// Log the search result and add the results to the results collection
results.ObserveOn(DispatcherScheduler.Instance)
.Subscribe(result => {
    searchResults.Clear();
    LogOutput.Insert(0, string.Format("Search for '{0}' returned '{1}' items", result.SearchTerm, result.Results.Count()));
    result.Results.ToList().ForEach(item => searchResults.Add(item));
    }
);

 

Lots of the ideas and even the odd piece of code were taken from:

Categories: C#, Programming, Rx, WPF Tags: , ,

More efficient file enumeration in .Net 4

November 18th, 2011 No comments

This may be basics to some people but I thought it was worth mentioning. I was writing some simple code recently to compare the files in a remote directory with those in a local directory to determined if the remote was newer in any way. This seemed like a really simple problem so I made my first stab at it.

return (from remoteFile in Directory.GetFiles(remotePath)
        join localFile in Directory.GetFiles(localPath)
            on Path.GetFileName(remoteFile) equals Path.GetFileName(localFile)
        where File.GetLastWriteTimeUtc(remotePath) > File.GetLastWriteTimeUtc(localPath)
        select remoteFile).Any();

 

It became very apparent that there were some performance issues when running this code, especially when the remote location introduces any form of latency. The first issue is with Directory.GetFiles, if you actually reflect this method you will see that it ultimately calls the following:

return new List<string>(FileSystemEnumerableFactory.CreateFileNameIterator(path, userPathOriginal, searchPattern, includeFiles, includeDirs, searchOption)).ToArray();

The existence of the ToArray means the full file list will be enumerated before the method returns, however we only care if any file has changed so it would be better if we had an enumerator so we could exit early when the first newer file is found. This is also true when performing the join as this will enumerate the joined collection first before enumerating the full original collection of remote files and then joining them.

We could solve the above issues using the new Directory.EnumerateFiles method which will return an enumerator that will yield each file as it is enumerated. We could also get rid of the join and enumerate all the local files first before in a separate operation to allow the more expensive remote enumeration happen in sequence.

The next problem in the original attempt is that we are returning to the remote files to call another operation to evaluate the last write time stamp on the file metadata. This requires us to return to the remote file system and incur the same latency per file. I originally tried to solve this problem using the Fast Directory Enumerator on code project which allowed me to enumerate the list of remote files at the same time as retrieving the file info, thus removing the need to return to the scene of the crime. This seemed to work ok but I was having an issue with it not completing the remote file enumeration sequence and discovered that there is actually an implementation introduced in .Net 4. The very well hidden EnumerateFiles on DirectoryInfo was the answer.

var localFiles = new DirectoryInfo(localPath).GetFiles();

return new DirectoryInfo(remotePath).EnumerateFiles()
    .Any(remoteFile => (from localFile in localFiles
                        where localFile.Name == remoteFile.Name
                        && remoteFile.LastWriteTimeUtc > localFile.LastWriteTimeUtc
                        select remoteFile).Any());

Notice the remote files retrieval now uses the EnumerateFiles method on DirectoryInfo. This allows us to exit when the first item matches the condition in the Any clause.

Categories: C#, Programming Tags: , , ,

Arghhh! Simultaneous Connection Limit in IIS (Windows 7)

November 10th, 2011 2 comments

I’ve been playing with SignalR recently and it drives me nuts that I can’t have more than a few simultaneous long polling requests open to the IIS server on Windows 7. It stops responding after about 2 clients. Even IIS Express supports unlimited simultaneous connections but we need AppFabric support.

We would seriously consider using it for our messaging solution but on a single machine developer install, we would need to come up with another solution for our many client apps.

Categories: ASP.Net, C# Tags: , ,

Responding to WF completion using the Creation Context

September 23rd, 2011 2 comments

This is the fourth post in a series on building an Enterprise Workflow system using WF4. Previously we looked at the WorkflowServiceHostFactory, the WorkflowCreationEndpoint and how we can use these to host activities as our own services. In this post I want to explore how we can execute some action once the workflow has completed.

Of course we could just put some activity at the end of our workflow but we are building an enterprise workflow system so we do not want to force our users to have to do this. Instead we want it to simply happen for them. Remember from the previous posts that we were creating a site that would allow users to create their own Magic Eight Ball implementations and upload them for an end user to consume, the end user could select an implementation, ask a question, supply an email address and get emailed a response.

In this example we do not want the implementation writer to have to worry about sending the email so how can we get this to happen automatically. Well, enter the WorkflowCreationContext. The WorkflowCreationContext is basically a class that captures some information at workflow creation, we used it previously to add the arguments in our creation endpoint when starting our workflow.

internal class EnterpriseWorkflowCreationEndpoint : WorkflowHostingEndpoint  {
    public EnterpriseWorkflowCreationEndpoint(Binding binding, EndpointAddress endpointAddress)
        : base(typeof(IEightBallContract), binding, endpointAddress) {}

    protected override WorkflowCreationContext OnGetCreationContext(object[] inputs, OperationContext operationContext, Guid instanceId, WorkflowHostingResponseContext responseContext) {

        if(!operationContext.IncomingMessageHeaders.Action.EndsWith("Ask")) {
            throw new InvalidOperationException();
        }

        EnterpriseWorkflowCreationContext workflowCreationContext = new EnterpriseWorkflowCreationContext();

        string question = inputs[0] as string;
        string email = inputs[1] as string;

        workflowCreationContext.WorkflowArguments.Add("Question", question);
        workflowCreationContext.Email = email;

        responseContext.SendResponse(instanceId, null);

        return workflowCreationContext;
    }
}

 

Notice that we have used an EnterpriseWorkflowCreationContext, we could have just used the standard WorkflowCreationEndpoint but I wanted to do something special, I wanted to add behaviour to the completion of our workflow but there was one other thing. If the author of the workflow should not have to worry about the email then they should not be sent the email address supplied by the user, therefore I needed a way to store some data (the email address) along with the workflow but outside of the workflow’s activities.

It just so happens that the WorkflowCreationContext gets serialized along with the instance so I am able to mark it up with DataContract and DataMember and add a property, this will survive till the end of the workflow and be available to my completion behaviour.

[DataContract]
public class EnterpriseWorkflowCreationContext : WorkflowCreationContext {
    [DataMember]
    public string Email { get; set; }

    protected override System.IAsyncResult OnBeginWorkflowCompleted(System.Activities.ActivityInstanceState completionState, System.Collections.Generic.IDictionary<string, object> workflowOutputs, System.Exception terminationException, System.TimeSpan timeout, System.AsyncCallback callback, object state) {

        if(terminationException == null) {
            MailMessage mail = new MailMessage();
            mail.To.Add(Email);

            mail.From = new MailAddress("peter.goodman@aderant.com");

            mail.Subject = "The workflow has completed";

            StringBuilder stringBuilder = new StringBuilder();

            stringBuilder.AppendLine("The result of the workflow was: ");

            workflowOutputs.ToList().ForEach(kvp =>
                stringBuilder.AppendLine(string.Format("{0}: {1}", kvp.Key, kvp.Value))
            );

            mail.Body = stringBuilder.ToString();

            mail.IsBodyHtml = false;

            SmtpClient smtp = new SmtpClient();
            smtp.Send(mail);

        }

        return base.OnBeginWorkflowCompleted(completionState, workflowOutputs, terminationException, timeout, callback, state);
    }

}

 

All I had to do was derive from WorkflowCreationContext and override the mind numbing OnBeginWorkflowCompleted method (basically when the workflow is starting to end). I use the previously saved Email address to construct an email and in this case I enumerate all the out arguments of the workflow into the body. The workflowOutputs will actually contain all the OutArgument and InOutArgument properties on your workflow definition keyed by their names.

Of course this example is rather contrived but you could do more interesting things like respond to the workflow being terminated or cancelled by processing the exception, or as I have done before, implement a sub workflow activity.

Sub Workflow

It’s probably worth a quick overview of how you could implement a sub workflow using the WorkflowCreationContext. Basically you have an activity that knows how to call another workflow’s creation endpoint, passing the id of the source workflow and a correlation token as arguments. Immediately following that creation call, the calling activity sets up a Receive activity waiting on a response.

Meanwhile the target workflow runs to completion and in the OnBeginWorkflowCompleted event realises that it has a source workflow id and correlation token to callback a source workflow to notify it that the target workflow has completed. It does so thus resuming the source workflow as if it had just called another activity instead of a whole other workflow.

The only complexity is in mapping the arguments and providing a generic way of doing so. I tend to use IDictionary<string, object> for this kind of stuff.

Why is this useful? Well, it allows for finer grained versioning of aspects of large processes. The more state you have in a long running workflow the more likely you will have problems versioning any aspect of it. If you split these large processes up into smaller ones, you can easily upgrade a sub-process and have it affect larger workflows. More on that in a later post.

So that was the use of the WorkflowCreationContext. In the source I have supplied I have also created a Manual Task Activity based on my earlier posting about manual tasks in workflow.

Download the Code EnterpriseWorkflowDemo.zip

Starting WF Instances using the Creation Endpoint

September 19th, 2011 No comments

This post is the third in a series on building an Enterprise Workflow System using WF4. Previously we discussed how to get the activity authoring experience for workflow service authors by using a custom WorkflowServiceHostFactory to tell the WorkflowServiceHost to host a compiled activity instead of a xamlx file.

Now we have a problem in that our workflow service cannot be started because it does not have a Receive Activity with a “CanCreateInstance” flag. Well, this is where the WorkflowCreationEndpoint steps in. This little beauty is an endpoint that can sit on our workflow service and when a request is processed by this endpoint, it will start a new instance of our workflow.

The only strange thing about this class is that it is a little different to implement than a standard WCF service. In WCF we would normally have an interface that represented our contract and we would only have to write a class that implements that contract. The WorkflowCreationEndpoint works slightly differently, before we get to that, lets create the interface that our clients will use to start a new instance of our workflow. Remember that we are building a Magic Eight Ball service such that we can ask a question, provide an email address and we will be emailed the response. Therefore our contract looks like this:

 

[ServiceContract(Name = "IEightBallContract")]
public interface IEightBallContract {
    [OperationContract]
    Guid Ask(string question, string email);
}

Notice that we have an operation called Ask that takes a question and an email address. The Guid return value will be our Workflow Instance Id.

Now for the implementation of the WorkflowCreationEndpoint:

internal class EnterpriseWorkflowCreationEndpoint : WorkflowHostingEndpoint  {
    public EnterpriseWorkflowCreationEndpoint(Binding binding, EndpointAddress endpointAddress)
        : base(typeof(IEightBallContract), binding, endpointAddress) {}

    protected override WorkflowCreationContext OnGetCreationContext(object[] inputs, OperationContext operationContext, Guid instanceId, WorkflowHostingResponseContext responseContext) {

        if(!operationContext.IncomingMessageHeaders.Action.EndsWith("Ask")) {
            throw new InvalidOperationException();
        }

        EnterpriseWorkflowCreationContext workflowCreationContext = new EnterpriseWorkflowCreationContext();

        string question = inputs[0] as string;
        string email = inputs[1] as string;

        workflowCreationContext.WorkflowArguments.Add("Question", question);
        workflowCreationContext.Email = email;

        responseContext.SendResponse(instanceId, null);

        return workflowCreationContext;
    }
}

 

In the creation endpoint, we override the OnGetCreationContext method and first validate that we are dealing with the “Ask” operation that we expect. We will cover the WorkflowCreationContext in more detail in the next post but notice that we can take the inputs, in this case only the question, and pass them as arguments to our Workflow using the creation context. We then send a response to the user containing the instance id and we are done.

The last step here is to wire up the creation endpoint on our WorkflowServiceHostFactory. For this we override the CreateWorkflowServiceHost method in the factory and add the endpoints as follows:

protected override WorkflowServiceHost CreateWorkflowServiceHost(System.Activities.Activity activity, Uri[] baseAddresses) {
    WorkflowServiceHost workflowServiceHost = base.CreateWorkflowServiceHost(activity, baseAddresses);
    AddBehaviorsAndEndpoints(workflowServiceHost);
    return workflowServiceHost;
}

/// <summary>
/// Adds the standard behaviors and endpoints to our workflow service host.
/// </summary>
/// <param name="workflowServiceHost">The workflow service host.</param>
private void AddBehaviorsAndEndpoints(WorkflowServiceHost workflowServiceHost) {
    // Check whether we have already initialised the service host
    if (workflowServiceHost.Description.Endpoints.Where(endpoint => endpoint is EnterpriseWorkflowCreationEndpoint).Any()) {
        return;
    }

    // Add endpoints for any services that have been defined in the workflow
    workflowServiceHost.AddDefaultEndpoints();

    ServiceEndpoint firstEndpoint = (from endpoint in workflowServiceHost.Description.Endpoints
                         where endpoint.IsSystemEndpoint == false
                         select endpoint).FirstOrDefault();

    BasicHttpBinding binding = new BasicHttpBinding();
    EndpointAddress endpointAddress = new EndpointAddress(workflowServiceHost.BaseAddresses[0]);

    // Add the creation endpoint
    EnterpriseWorkflowCreationEndpoint creationEndpoint = new EnterpriseWorkflowCreationEndpoint(firstEndpoint != null ? firstEndpoint.Binding : binding, firstEndpoint != null ? firstEndpoint.Address : endpointAddress);

    workflowServiceHost.AddServiceEndpoint(creationEndpoint);

}

 

There is a lot more that can be done here but the important things to know are that we are using AddDefaultEndpoints to first add any endpoints that are specified by Receive activities on our workflow activity, this is important if we want to support a workflow that can be called from outside while in process.

Next we create a default endpoint address and binding in case we are going to need it and then we try to reuse the address and binding of a previous endpoint if one exists otherwise use our new ones. Finally we simply call AddServiceEndpoint to add the WorkflowCreationEndpoint to our host. Now we have a workflow that can be started by calling Ask. You can test this using the WCF Test Client as below:

CropperCapture[8]

We can also write client code to access our service easily, either by using the Add Service Reference in Visual Studio or using the ChannelFactory.

// Start the EightBall workflow
IEightBallContract eightBall = ChannelFactory<IEightBallContract>.CreateChannel(
    new BasicHttpBinding(),
    new EndpointAddress(
       "http://localhost/HardcoreWorkflow/BasicMagicEightBall/EightBall.svc"));

eightBall.Ask(model.Question, model.Email);

 

In the next post we will look at the WorkflowCreationContext and how we can use it to store state about how our instance was started without requiring our workflow to know about it. We will also look at how we can respond to the completion of the workflow and perform an action once it is complete, cancelled or terminated.

Download the Code EnterpriseWorkflowDemo.zip

Hosting an Activity as a Service using the WorkflowServiceHostFactory

September 7th, 2011 No comments

This is the second post in a series about Building an Enterprise Workflow system with WF4.

In the previous post we discussed how the default workflow service design experience wasn’t really what we would want for an enterprise workflow system. We decided that the activity authoring experience we wanted was much better and we even hinted that the WorkflowServiceHostFactory would enable us to host an activity as a service. Lets look at how we can do this.

I have modified the Magic Eight Ball sample from the previous post to make it an activity rather than a xamlx workflow service file.

 CropperCapture[7]

In a normal .xamlx workflow service like the one you get with the workflow service library template, the web.config makes no mention of the .xamlx file or workflow or anything that would suggest the app will host a workflow. In fact the .xamlx is automatically mapped by the runtime with a default binding and endpoint using the simplified configuration feature of WCF 4. This means that a .xamlx file will be hosted as a service using the BasicHttpBinding at the address of the xamlx file, much like the svc file for standard WCF services.

We can however specify our own service activation in the web.config as follows:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  ...
  <system.serviceModel>
    ...
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" >
      <!-- Add the service Activations section-->
      <serviceActivations>
        <add relativeAddress="~/EightBall.svc"
             service="BasicMagicEightBall.EightBall, BasicMagicEightBall"
             factory=" EightBallLibrary.Hosting.EnterpriseServiceHostFactory, EightBallLibrary"/>
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>
  ...
</configuration>

 

If we break the serviceActivation element down:

  • relativeAddress: The relative URI that we will use, this does not have to end with .xamlx and the file in the path does actually exist
  • service: The service to load, in our case this is the compiled xaml activity name and assembly name
  • factory: This is our custom service host factory

Notice that when we implement a custom class deriving from WorkflowServiceHostFactory that we have 2 overrides for CreateWorkflowServiceHost, one that takes a WorkflowService and one that takes an Activity. Obviously the second one is the one that is going to run in our case.

protected override WorkflowServiceHost CreateWorkflowServiceHost(WorkflowService service, Uri[] baseAddresses) {
    WorkflowServiceHost workflowServiceHost = base.CreateWorkflowServiceHost(service, baseAddresses);
    AddBehaviorsAndEndpoints(workflowServiceHost);
    return workflowServiceHost;
}

protected override WorkflowServiceHost CreateWorkflowServiceHost(System.Activities.Activity activity, Uri[] baseAddresses) {
    WorkflowServiceHost workflowServiceHost = base.CreateWorkflowServiceHost(activity, baseAddresses);
    AddBehaviorsAndEndpoints(workflowServiceHost);
    return workflowServiceHost;
}

 

We can add our own behaviors etc, hence the call to my AddBehaviorsAndEndpoints method. With this we can do many things to configure our WorkflowServiceHost including:

  • Hard Code Instance Store persistence
  • Add WF Idle Behavior
  • Add WF Unhandled Exception Behavior
  • Add a WF control endpoint for controlling running instances
  • Add a custom WF tracking behavior
  • Add custom WF extensions
  • Customize behaviors etc on WF hosted endpoints (Like adding security behaviors etc)
  • Add a WF Creation Endpoint – more on that later.

Now we have a workflow activity hosted as a service, just one problem. Remember that in our workflow service xamlx created by the Workflow Service Library project template we had a Receive activity with a SendReply. If you look closer on the properties for the Receive activity you will notice that there is a property called CanCreateInstance set to true.

When you have a Receive /SendResponse activity pair on a workflow definition, the workflow service host sets up that activity pair as a WCF service operation on the workflow service when the service host starts. If it has “CanCreateInstance” set, any call to that service operation will create a new instance of our workflow definition.

With our new hosted activity we have no way of starting a new instance as we do not have a Receive activity waiting on an incoming call. This is where the WorkflowCreationEndpoint comes in, it will allow us to have a standard contract for creating new instances of our workflow, it will also be the subject of the next post.

Download the Code EnterpriseWorkflowDemo.zip

Code and slides for TechEd NZ 2011–DEV 404 Hardcore Workflow

August 29th, 2011 No comments

Below are the slides and the code for the talk Stef and I did at Teched NZ 2011. I hope to do a post in the future explaining this in more detail.

Categories: C#, Presentations, TechEd, WCF, WF4 Tags: , ,

Getting Entity Framework and MySQL to play nice on my Hosting Provider

January 23rd, 2011 No comments

After moving my blog to wordpress, I decided to update the recent posts section on my main site to point to the wordpress repository instead of the old SubText one. SubText was using MSSQL but WordPress is using MySQL so I had to get things strung together again.

For the original code talking to the SubText repository I had created an EDMX and simply queried against it using LINQ to extract the top 5 most recent blog posts and display them on my sites main page.

The first thing I figured I would have to do is to find a connector for MySQL to allow the Entity Framework to talk to MySQL. A quick google supplied me with the location to go pick that provider up directly from the guys at MySQL.Once that was installed I had to restart VS2010 and go through the process of adding a new EDMX model for the WordPress repository. Once that was done I had to change some of the nonsensical casing and naming in the Entity list, the model namespace and entities class.

I added a quick WCF Data Service and used LinqPad to prove that everything was working. I then updated the query in my home page to talk to the new entities source. So far, so good. Time to upload to my hosting provider and job done.

Now this is where things got a little pear shaped. Firstly I received the following error.

Unable to find the requested .Net Framework Data Provider. It may not be installed.

OK I figured, I looked at my local project and I had no references to anything MySql, therefore I added the references and set them to copy local, then re-deployed. Same thing.

Next I did a bit more googling.  At this point I should make it clear that I’m using WinHost as my hosting provider, they are really good, they seem to be pretty responsive on their forums and I can mostly find the answers I need (without ever having to ask them directly) when it comes to getting some relatively new tech working on their kit. Therefore I came across this forum post which pointed me to the fact that I had to add this config section in my web.config (remember to change the assembly version to whichever you have downloaded from MySQL).

<configuration>
  <system.data>
    <DbProviderFactories>
      <add name="MySQL Data Provider"
           invariant="MySql.Data.MySqlClient"
           description=".Net Framework Data Provider for MySQL"
           type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.3.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
    </DbProviderFactories>
  </system.data>

Righto, now publish my changes and away we go….almost.

This time I had something like the following error.

System.Security.SecurityException: Security error.

The details mentioned that something was making a request to perform an action that wasn’t allowed under medium trust. A bit more googling and I found this winhost kb article on enabling full-trust. What nice people!

After correcting a few problems with my web.release.config and relocating the MySql password I was up and running.

Categories: ASP.Net, C#, Entity Framework, MVC, MySQL, WCF Tags:

Code and slides for Dev208 at Tech Ed NZ

August 31st, 2010 No comments

Here are the slides and demos for the Tech Ed NZ talk Stef and I did on Intro to Workflow 4. It includes the Approval Sample we didn’t manage to fit in.

P.S. I know this blog sucks in IE, working on a fix when I get some time.