RSS
 

Design-time Data in Expression Blend 3: Revisited

16 Dec

How do you make sure that what you (or your designer) sees in Expression Blend is exactly what the finished product will look like? A while ago I posted about the d:DataContext attribute in Blend, and how you could leverage that to populate Blend with realistic sample data. What was awesome about that?

  • You could see exactly how the finished product would look WHILE you were designing. True WYSIWYG means efficient designers!
  • Blend would provide typesafe data binding (I don’t think I called this out, but bringing up the Binding dialog box shows a chooser for correct property names. Bye bye magic strings!)
  • Having sample data in your ItemsPresenters/ListBoxes/TreeViews means that blend will let you edit the template in place, providing for an even more useful WYSIWYG experience.

If you haven’t tried it yet, but you are a XAML developer, I really suggest you try developing a screen in Blend when it’s populated with sample data. It’s just so easy. With unit tests on your viewmodel and sample data in Blend, you can finish a screen without ever having to press F5. Okay, maybe once, but you’ll be super happy because everything will work the way it was intended.

But at what cost?

Here are the problems that I’ve found with this approach in my own projects:

I often had to write alot of code, either dummy services to be passed into the viewmodel, or lots and lots of code to simply add things into the derived viewmodel’s collections. This code (often hacked together) got deployed, bloating my DLL file. This sucks extra for Silverlight where the DLL has to be downloaded every time) and, well, looking messy.

Depending on how your viewmodel is coded, you can’t always provide a simple design-time subclass that will populate everything you want. While Dependency Injection is awesome, we aren’t all the architects on our projects, and you might get handed a viewmodel that relies on hard coded dependencies that will do yucky things like call web services, read files or connect to a database. Other times, the ways in which the services are used are so watertight that it’s impossible (or at least it would take hundreds of lines of well thought out code) to make sure you had the right sample data for your designer.

Whenever the viewmodel or the services evolved, the design-time viewmodel needed to keep up. Often (on my project), the person adding features to the viewmodel wasn’t the person who cared about the design time viewmodel. Sometimes they took the effort to make sure the design-time viewmodel compiled, other times they deleted it. Which is fair enough, they didn’t write the code, they don’t see the point of it, all its doing is helping me design the XAML. So I’d end up restoring the file from source control, adding it back into the project, and maintaining it, which was often a lot of effort!

The solution

In the meantime, I’ve been reading around the blogosphere and found a better way to do design data in blend. It doesn’t rely on Dependency Injection (although DI is lovely), it’s easy to maintain and best of all it has NO effect on your compiled DLL. Stay tuned, having gone over (in tedious detail) the why of this new approach, I’m going write a new post about how.

 
 

Timeago for C#

10 Sep

Sometimes you don’t want to make your users think. There’s the odd situation where you want to represent time in natural language: “about 4 hours ago” instead of just printing out a full timestamp. If you’re building a website, then the jQuery plugin Timeago is a pretty sweet way to do it (as long as you can stand webpages that auto update text).

Sucks for me, I’m working with WPF! (Not really sucks at all). So I needed a C# implementation of the same thing. Surely someone’s done this, right? Well my Google-fu failed me, and even when I Googled on bing I came up with nothing, so I built it myself. And I’m posting it here for you (and for me, later). If you’ve found a good one, please let me know.

First, the test cases, so you can see if the format I want is the format you want:

[TestClass]
public class FriendlyTimeDescriptionTest
{
    private static string Run(TimeSpan span)
    {
        return FriendlyTimeDescription.Describe(span);
    }

    [TestMethod]
    public void TestNow()
    {
        Assert.AreEqual("now", Run(new TimeSpan(0, 0, 0, 0)));
    }

    [TestMethod]
    public void TestSeconds()
    {
        Assert.AreEqual("1 second ago", Run(new TimeSpan(0, 0, 0, 1)));
        Assert.AreEqual("2 seconds ago", Run(new TimeSpan(0, 0, 0, 2)));
        Assert.AreEqual("59 seconds ago", Run(new TimeSpan(0, 0, 0, 59)));
    }

    [TestMethod]
    public void TestMinutesAndSeconds()
    {
        Assert.AreEqual("about 1 minute ago", Run(new TimeSpan(0, 0, 1, 1)));
        Assert.AreEqual("about 3 minutes ago", Run(new TimeSpan(0, 0, 3, 1)));
    }

    [TestMethod]
    public void TestMinutesAndSecondsRounding()
    {
        Assert.AreEqual("about 4 minutes ago", Run(new TimeSpan(0, 0, 3, 31)));
    }

    [TestMethod]
    public void TestDaysHours()
    {
        Assert.AreEqual("about 3 hours ago", Run(new TimeSpan(0, 3, 3, 1)));
        Assert.AreEqual("about 2 days ago", Run(new TimeSpan(2, 0, 1, 1)));
    }
}

I’ve conveniently wrapped all this up into an IValueConverter implementation, but if you’re not using WPF you can rip out the necessary methods. Please excuse the newline-enthused formatting – this blog theme has limited column width!

[ValueConversion(typeof(DateTime), typeof(string))]
public class FriendlyTimeDescription : IValueConverter
{
    public object Convert(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        var time = System.Convert.ToDateTime(value);
        return Describe(DateTime.Now - time);
    }

    static readonly string[] NAMES = {
                                         "day",
                                         "hour",
                                         "minute",
                                         "second"
                                     };

    public static string Describe(TimeSpan t)
    {
        int[] ints = {
                         t.Days,
                         t.Hours,
                         t.Minutes,
                         t.Seconds
                     };

        double[] doubles = {
                               t.TotalDays,
                               t.TotalHours,
                               t.TotalMinutes,
                               t.TotalSeconds
                           };

        var firstNonZero = ints
            .Select((value, index) => new { value, index })
            .FirstOrDefault(x => x.value != 0);
        if (firstNonZero == null)
        {
            return "now";
        }
        int i = firstNonZero.index;
        string prefix = (i >= 3) ? "" : "about ";
        int quantity = (int)Math.Round(doubles[i]);
        return prefix + Tense(quantity, NAMES[i]) + " ago";
    }

    public static string Tense(int quantity, string noun)
    {
        return quantity == 1
            ? "1 " + noun
            : string.Format("{0} {1}s", quantity, noun);
    }

    public object ConvertBack(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}

Enjoy!

 
5 Comments

Posted in .Net, Dot

 

Design-time Data in Expression Blend 3

02 Aug

Update: I’ve detailed another technique for implementing design time data in blend in this newer post (using something called DesignData)

How can you develop a complex GUI without ever needing to build and run it?

WYSIWYG tools have come a long way in recent years, and if you’re building a WPF app you can’t go past Microsoft’s newly-released Expression Blend 3. I’d always preferred Blend 2 over Visual Studio 2008 for building my XAML, not least because of the Silverlight support. But Blend 3 has some features that quite frankly put me in GUI developer nirvana. Sketchflow shows an awful lot of promise, but what’s really floating my boat is the almost undocumented design time only datacontext support. What does that even mean? Let me use a simple WPF game, Connect 4, to show you…

Lets say I’ve already built the game. Just pretend I’d even written most of the XAML by hand. Here’s what the game looks like when it’s just been launched:

running_startgame

and here’s a game that’s partway through:

running_midgame

Perfect! The game is finished. Let me tell you about how this was built:

First, I coded my ViewModel, a bunch of classes that the XAML binds to. I’ve implemented INotifyPropertyChanged where necessary, and am using ObservableCollections instead of Lists. Note that this is quite a simple game, and I don’t really have a Model (in the M-V-VM sense) to speak of:

viewmodel

The Game is the root of everything, it tracks the Players, whos turn it is, and the Columns. Columns have a collection of Cells, and Cells track whether or not  a Token has been placed within. I’ve exposed a Command on the Column class, which picks up mouse clicks through a tall, invisible button in my XAML.

The XAML for this game is quite straightforward. The window contains an ItemsControl for the columns, the column template contains an ItemsControl for the cells, and the cell template renders a blue rectangle with a hole in it, and an optional token. Grab the code and check it out if you like - you can download all this source at the bottom of the post.

Lets say that I had made this Viewmodel the datacontext of my main Window in the Window.Loaded event:

public void Window_Loaded(...){LayoutRoot.DataContext=new Game(7,5);}

When I come to edit the XAML in Blend (let’s say I was planning to make the UI look a bit foxier, with animations and gradients and whatnot), this is what I get:

No data in blend

Which is fair enough, because blend is effectively running my program with no data. The Window_Loaded event won’t be fired by Blend, Blend only works with the XAML. The Visual Studio WPF designer has the same problem:

Visual Studio with no data

A feature of WPF that has always existed, and is completely cool is that you can shift this datacontext declaration into your XAML (Note that the use of an ObjectDataProvider is optional. If we were using silverlight we’d turn these constructor arguments into properties):

xaml_datacontext

Even before Blend 3 came along, doing this would mean that Blend (and Visual Studio) would be able to render your XAML as though a game had just started:

blend_realdata

This is nice. Now we get a good idea of how the GUI will really look when it’s running. We can even edit the XAML Templates in place (to see what I mean, download the source, right click an ItemsControl and edit its ItemsTemplate). We’d be in big trouble, however, if our ViewModel tried to call anything external on construction. For example, if we were building a twitter client, we might start downloading tweets through a web service call. This may or may not work when your code is running inside blend, but you’d be working with variable results, and as soon as you have an exception your designer would die. Jonas Follesoe has a great post that talks about how you can leverage Dependency Injection to get design time data services and runtime data services going. Go read it – that’s the post that made me realise how cool and important it is to get realistic data into your design time experience.

Now that Blend 3 is out, however, we’ve got a new tool in our belt. I don’t know if you’ve ever tried to change the DesignWidth or DesignHeight of a UserControl or Window from Blend. This post explains it pretty well, if you haven’t… Well, Blend will go and add a bunch of namespace declarations to your XAML, the most important alias of which is “d”. You’ll notice that you can put d:DesignWidth in any element you like, and nothing will happen at runtime. If you’re lucky (or you put it in the right place), blend will pick up this design-time data, and will render your control at that width, but only from within blend. The fact that your XAML can contain directives that will only be executed / honoured / considered by Blend is quite a powerful one.  There aren’t very many of these attributes available, however,  Blend 3 introduced a big one: “d:DataContext”.

I stumbled across d:Datacontext when I was playing with Blend 3 and tried adding a “live datasource” to my window. I thought it was going to behave just like the old way of setting a DataContext, but when I ran my application, there was no data! I had a look at the XAML and saw that a Datacontext was being set on my root element, just like I expected. But why wasn’t this being applied at runtime? I had a really, really close look at the XAML and spotted the “d:” before the word datacontext. Sweet. I deleted that, and the app ran as expected. My next thought was to try setting both a design time (d:) and a run time (no d:) Datacontext. It worked!

So the upshot is, now we can write code like this:

Setting a runtime AND a designtime datacontext

Or we can even set the real DataContext at runtime through the Window_Loaded (or whatever) event. Why is this exciting? Now, it’s easyto have blend show a truly representative form of our gui at design time:

blend_designdata

This, by the way, was acheived with the following design time subclass of Game:

code_designgame

Simple, no? By using an ObjectDataProvider, we can even prevent the DesignTimeGame from even being instantiated at runtime. If you’re coding in silverlight, you’d use an alternative: “d:DataContext={d:DesignInstance vm:DesignTimeGame}”, which would only work with an empty constructor – which is fine, because even if the runtime game requires constructor parameters, we can just write an empty designtimegame constructor that passes some dummy ones in.

Now that we’ve got this design time data, it’s much easier to spruce things up in the XAML (note that I’m editing a template in-place, and that I deliberately coded the design time model to have a token in the top left cell):

Editing a template in place with DesignTime data

I can’t really express how much easier this design time data can make your coding. So please, download my example project, open it in blend 3, and try (for example) adding a gradient overlay to the tokens, or even just resizing them. I have to admit, I didn’t hand code the XAML, I blended it in about ten minutes once I had the design time data available to me. And I didn’t have to run it till I’d finished!

Download the Connect4 Source here

 
 

Use T4 code generation to add INotifyPropertyChanged to ADO.Net Data Services (Astoria) Entities

26 Mar

The current version of ADO.Net Data Services (Astoria) for Silverlight generates some extremely Plain Old CLR Objects. As Shawn Wildermuth notes, you dont even get INotifyPropertyChanged support. You might need this if you want to databind directly to your Astoria entities, but if you’re doing serious Silverlight work, it pays to wrap your entities up in a ViewModel. Even if you’re doing this, having INotifyPropertyChanged support can really help – for example, instead of saving every single entity on your model, you only need to fire the ones that change. For example:

entity.PropertyChanged += (sender, e) => dataContext.UpdateObject(sender);

Pretty soon, this functionality will be built into Astoria. In the meantime, however, it’s possible to add this functionality thanks to the partial methods in the web reference-generated entity. When you add an Astoria web reference to a silverlight project, the two most interesting things that get added (expand the service reference to see these files) are:

Reference.cs

This is the C# file that contains all of the code relating to the service reference. Look inside and you will see your DataContext and all of your Entities. Note that your entities don’t fire property changed events, but they do define partial methods:

        
    public string City
    {
        get
        {
            return this._City;
        }
        set
        {
            this.OnCityChanging(value);
            this._City = value;
            this.OnCityChanged();
        }
    }
    private string _City;
    partial void OnCityChanging(string value);
    partial void OnCityChanged();

service.edmx

This is an XML file that defines, among other things, each of the entities in your service reference:

      <EntityType Name="Address">
        <Key>
          <PropertyRef Name="ID" />
        </Key>
        <Property Name="ID" Type="Edm.Int32" Nullable="false" />
        <Property Name="Line1" Type="Edm.String" Nullable="true" />
        <Property Name="Line2" Type="Edm.String" Nullable="true" />
        <Property Name="City" Type="Edm.String" Nullable="true" />
        <Property Name="Country" Type="Edm.String" Nullable="true" />
      </EntityType>

This XML file serves as the perfect source for our data generation template!

DataServiceINotifyPropertyChanged

If you’re not familiar with T4 code generation and it’s integration into visual studio, now would be a good time to go and read Oleg Sych’s blog - he covers EVERYTHING. Or you could just go ahead and incorporate my template into your Silverlight project – it works on my machine! 

In order to make the namespace of the generated file match the namespace of your service classes, you need to put this template into a top level folder that matches the name of your service reference. The template will use that directory name to find the edmx file in question:

T4 Template

 

Basically, the template loops over all the entities in the edmx, generates a partial class (which will match the service entities), then loops over all the properties and generated a partial method implementation. Easy?

Download the template file here. You might have to change the extension from txt to tt…

 
4 Comments

Posted in .Net

 

Visualising Data with Dot (Part 2 of 4)

11 Mar

Welcome back to my four part series on Dot. In this installment, I go deeper on some of the options available regarding layout of Dot graphs.

Part 2: More Dot layout

I’m not sure that I can add value beyond what’s already available in the documentation - its simple, clear and concise. What I will do, however, is call out the things that I found most useful:

Colours, fonts and shapes (oh my?)

You have full control over the following layout attributes:

You could imagine modifying the sql that I demonstrated in part 1 to also select out some colour / formatting attributes into the nodes and edges. Another options is to generate your Dot code in an application layer – since ruby, C# or java are more expressive with SQL it’s a bit easier to generate some really interesting graphs.

HyperDot: URLs and Tooltips

Did you know that Dot can generate more than just image files? The Dot syntax supports adding tooltips and URLs into nodes, edges, and even arrowheads. However, there’s no way for this kind of information to be embedded into a gif, png or jpeg. Currently, the output formats that will let you see these are:

  • SVG, which is natively supported by all browsers except for the most important one, is a web-aware xml based vector format (that is soon to be superseded by XAML). In firefox, for example, you could be viewing a graph that will hyperlink you to the appropriate web page when you click on an item on the graph. 
  • HTML ImageMaps are elements that you can use to tack urls and tooltips onto specific areas of an image in a webpage. If you run Dot twice against the same piece of Dot code (but with different output formats), you can create the imagemap code that corresponds perfectly to the pixels drawn on the image. In Part 4, I will be talking further about how to achieve this in an ASP.Net web server. This functionality replicates what SVG provides you (without the pretty vector scaling, but with superb browser compatibility).  

Personally, I am hoping that someone will champion the Silverlight cause and write a native XAML output format for Dot :) . I have experimented with a couple of SVG to XAML converters, both XSLT files, but neither of them get the layout just right.

Next in this series: how to call into Dot from a .Net web server to dynamically generate server side images.

 
2 Comments

Posted in Dot

 

Getting started with iPhone development

28 Dec

My wife and I have recently been trying to build a simple game on the iPhone. Neither of us have tried to do any Mac development before, so it was a little bit of a challenge just working out where to start. Here’s some tips on where to go if you’re a beginner like us.

You will need:

  • A computer running the latest version of OSX (like a Mac)
  • XCode (the Apple IDE) installed on your OSX (This comes on the OSX install CDs, but not usually on the Mac itself)
  • Some internet (such as the one you’re using to read this blog)
  • An iPhone or iPod touch (although you can get quite far just using the simulator)
  • The iPhone SDK. Once you install this, XCode will be able to create iPhone projects. It also comes with a simulator and all sorts of performance testing tools. You’ll need to register as an iPhone developer before you can download this (or a number of other things I’m linking to), but you don’t have to fork out $99 until you want to deploy your app to an iPhone.

Apple have 11 introductory videos available on the iPhone development homepage. The first few I would recommend as mandatory, the others you should watch if they look interesting.

These links will help you to learn Objective C (The language you’ll be developing in):

One blog that I’ve found very useful is Mobile Orchard

The most important thing that I recommend doing is downloading Apple’s sample code and stepping through that. Playing with some sample code and seeing what changes are effected was probably what taught us the most. There’s a gallery of UIElements to browse through the different controls that apple provide, as well as examples of using the more complex input hardware that the iPhone provides, like GPS and the accelerometers.

Please leave a comment if you’ve got any further suggestions – I’ll add them to the list!

 
3 Comments

Posted in How To

 

Visualising Data with Dot (Part 1 of 4)

14 Nov

Welcome to part one of a four part series on getting some sweet visualisations of workflows, using the open source digraph tool “Dot”. This first post will be about dot’s DSL (which rocks), and how to generate it. Part two will look at some advanced styling and layout. Parts 3 and 4 will be about ways to publish this data over the Internet (Dot is a command line tool).

Dot’s input language is very simple. Here’s an example of a digraph generated by dot:

 

And the code to create this graph was:

digraph G{ //declare a digraph, and give it a name of “G”
    node[fontname=arial]; //sets the default font for all nodes
    bismuth212->thallium208[label="36%"]; //create a labelled edge
    bismuth212->polonium212[label="64%"];
    thallium208->lead208; //create an unlabelled edge
    polonium212->lead208;
    lead208[color=gray] //set the colour for the (already declared) lead 208 node
}

You can also give labels to nodes – the following code creates exactly the same graph:

digraph G{
    node[fontname=arial];

    1[label=bismuth212]
    2[label=thallium208]
    3[label=polonium212]
    4[label=lead208,color=gray]

    1->2[label="36%"];
    1->3[label="64%"];
    2->4;
    3->4;
}

You can get more information about the Dot language at the graphviz site.

I have recently started working on a project that involves a simple workflow. This workflow is modelled in my database. I’ve simplified it a bit, but here’s my schema:

 image

And here’s my data:

State Transition
ID    Name
1    Start
2    Write test
3    Run test (red stage)
4    Write function
5    Run test (green stage)
6    Refactor
7    Run test (refactor stage)
8    Finish
ID    FromStateID    ToStateID    Description
2    1    2   
3    2    3   
4    3    2    Passed
5    3    4    Failed
6    4    5   
7    5    6    Passed
8    5    4    Failed
9    6    7   
10    7    8    Passed
11    7    4    Failed

 

Not that easy to follow, huh? And this is a very simple example.

However, if we run the following (simple) SQL:

 

DECLARE @crlf varchar(2)
SET @crlf = char(13)+char(10)

DECLARE @s varchar(max)
SET @s = '  node[fontname=arial];'+@crlf

SELECT @s=@s+'  '
    +convert(varchar,ID)
    +'[label="'+Name+'"];'
    +@crlf
FROM State

SELECT @s=@s+'  '
    +convert(varchar,FromStateID)
    +'->'+convert(varchar,ToStateID)
    +'[label="'+Description+'"];'
    +@crlf
FROM Transition

SELECT 'digraph G{'+@crlf+@s+'}'

we’ll get the following output:

digraph G{

  node[fontname=arial];

  1[label="Start"];

  2[label="Write test"];

  3[label="Run test (red stage)"];

  4[label="Write function"];

  5[label="Run test (green stage)"];

  6[label="Refactor"];

  7[label="Run test (refactor stage)"];

  8[label="Finish"];

  1->2[label=""];

  2->3[label=""];

  3->2[label="Passed"];

  3->4[label="Failed"];

  4->5[label=""];

  5->6[label="Passed"];

  5->4[label="Failed"];

  6->7[label=""];

  7->8[label="Passed"];

  7->4[label="Failed"];

}

Which we can run through the dot tool:

C:\Program Files\Graphviz 2.21\bin>dot -Tgif -ooutput.gif

output

It’s not pretty (yet), but it’s so much easier to follow than looking at numbers. Hopefully I’ve got you thinking about how you could rewrite that SQL statement to work against your own database tables.

I’ll be posting a guide to styling and laying out this Dot diagram soon – stay tuned!

 
4 Comments

Posted in Dot

 

How to fix a dzproj file when DeepZoom Composer has mangled your CompositionNode’s Ids

08 Oct

Warning: if you’re not into building deepzoom systems, stop reading. This post will BORE YOU. Was the title not a good enough indication?

Ok good, they’re gone!

The current release of the deep zoom composer has a little bug. Ok – it has a few bugs, but I hate this one the most. You close your DeepZoom project(*.dzproj), you open your project, and viola – your images have rearranged themselves (or just disappeared). The first thing to worry about is: have you moved your files? Deepzoom projects store file references as absolute paths, which is ridiculous, but not the problem I was having.

Tori talks about this problem on the “known issues page” for the composer.

I don’t know what causes it (language settings were mentioned on that thread – I’m using en-NZ), but if you look inside the dzproj file itself, the Ids of all the composition nodes are all wrong.

More like “Deep Zoom Confounder”!

Im sure theres a fix coming, but if you’re as desperate as me, then what you’ve got to do is this:

1) put :<filename> on the end of each image’s tag

2) run the following code across your dzproj file:

using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main(string[] args)
    {
        var file = string.Join(" ", args);

        XDocument d = XDocument.Load(file);

        var images = from i in d.Descendants("Image")
                     select Path.GetFileName(i.Element("File").Value);

        var imageList = images.ToList();

        var map = from e in d.Descendants("CompositionNode")
                  let tag = e.Attribute("Tag")
                  where tag != null
                  let fileName = tag.Value.Split(':').Last()
                  where images.Contains(fileName)
                  select new
                  {
                      Node = e,
                      NewId = imageList.IndexOf(fileName)
                  };

        foreach (var v in map)
        {
            v.Node.SetAttributeValue("Id", v.NewId);
        }


        d.Save(file);
        Console.Out.WriteLine("Press any key to continue");
        Console.ReadKey();
    }
}

This code will read in the xml, build a list of all the correct image ids, then update the ids of all your composition. Its not easy, but it’s a workaround!

 
1 Comment

Posted in How To

 

Build yourself a portable Dependency Injection container

30 Sep

It’s been too long since I promised to post this. But it’s worth it, I promise you. If you just want to grab the code, it’s at the bottom of this post.

What we have here is another do it yourself dependency injection container. I release it to you, dear world, free of charge, warranty or care.

Pros:

  • You can paste the code straight into your project – no DLL dependencies (easy to deploy, get approved, source control)
  • It won’t bulk up your silverlight application
  • It performs super-fast if you’re using it to resolve singletons
  • It can do lots of the things that the “real” DI containers can do (named parameters, value parameters, lifestyle choices)
  • It’s got a fluent interface
Cons
  • There’s a bunch of stuff that the real containers can do that mine can’t (consider this DIY container a “gateway drug”). That said, I seem to have covered three of Oren’s four basic requirements, and i think it’s pretty easy to use…
  • If you are doing a lot of transient resolves (say per each page request) you will find reflection is just too slow.
  • This version depends on LINQ and lambdas, so it’s VS 2008 only.

the tests:

[TestClass]
public class DemoContainerTest
{
    [TestMethod]
    public void NamedRegistration()
    {
        Container c = new Container();
        c.Register<IMathNode, Zero>("zero");
        IMathNode m = c.Resolve<IMathNode>("zero");
        Assert.AreEqual(0, m.Calculate());
    }

    [TestMethod]
    public void AnonymousRegistration()
    {
        Container c = new Container();
        c.Register<IMathNode, Zero>();
        IMathNode m = c.Resolve<IMathNode>();
        Assert.AreEqual(0, m.Calculate());
    }

    [TestMethod]
    public void AnonymousSubDependency()
    {
        Container c = new Container();
        c.Register<IMathNode, Zero>();
        c.Register<IFormatter, MathFormatter>();
        IFormatter m = c.Resolve<IFormatter>();
        Assert.AreEqual("$0.00", m.Format("C2"));
    }

    [TestMethod]
    public void WithValue()
    {
        Container c = new Container();
        c.Register<IMathNode, Number>("five").WithValue("number", 5);
        int i = c.Resolve<IMathNode>("five").Calculate();
        Assert.AreEqual(5, i);
    }

    [TestMethod]
    public void NamedSubDependency()
    {
        Container c = new Container();
        c.Register<IMathNode, Number>("five").WithValue("number", 5);
        c.Register<IMathNode, Number>("six").WithValue("number", 6);
        c.Register<IMathNode, Add>("add").WithDependency("m1", "five").WithDependency("m2", "six");
        int i = c.Resolve<IMathNode>("add").Calculate();
        Assert.AreEqual(11, i);
    }

    [TestMethod]
    public void NamedSubDependencyOutOfOrder()
    {

        Container c = new Container();
        c.Register<IMathNode, Add>("add").WithDependency("m1", "five").WithDependency("m2", "six");
        c.Register<IMathNode, Number>("five").WithValue("number", 5);
        c.Register<IMathNode, Number>("six").WithValue("number", 6);
        int i = c.Resolve<IMathNode>("add").Calculate();
        Assert.AreEqual(11, i);
    }

    [TestMethod]
    public void Singleton()
    {
        Container c = new Container();
        c.Register<IMathNode, Zero>().AsSingleton();
        Assert.AreSame(c.Resolve<IMathNode>(), c.Resolve<IMathNode>());
    }

    [TestMethod]
    public void NonSingleton()
    {
        Container c = new Container();
        c.Register<IMathNode, Zero>();
        Assert.AreNotSame(c.Resolve<IMathNode>(), c.Resolve<IMathNode>());
    }

    public interface IFormatter
    {
        string Format(string format);
    }

    public class MathFormatter : IFormatter
    {
        private readonly IMathNode math;

        public MathFormatter(IMathNode math)
        {
            this.math = math;
        }

        public string Format(string format)
        {
            return math.Calculate().ToString(format);
        }
    }

    public interface IMathNode
    {
        int Calculate();
    }

    public class Zero : IMathNode
    {
        public int Calculate()
        {
            return 0;
        }
    }

    public class Number : IMathNode
    {
        private int number;

        public Number(int number)
        {
            this.number = number;
        }

        public int Calculate()
        {
            return number;
        }
    }

    public class Add : IMathNode
    {
        private IMathNode m1, m2;

        public Add(IMathNode m1, IMathNode m2)
        {
            this.m1 = m1;
            this.m2 = m2;
        }

        public int Calculate()
        {
            return m1.Calculate() + m2.Calculate();
        }
    }

}

The container:

The way this bad boy works is by storing dictionary of services as “Func<object>”s. These are keyed by name, which is usually provided by the Resolve method. If the parameterless overload of resolve is used, then the service name is looked up in the dictionary serviceNames. This simply stores the first  ever registration of a service type’s name. If the nameless Register method is used, then a random name is generated.

Whenever you register a component, you get back a “dependency manager” object. That object lets you specify further configuration on your component via a fluent interface. It contains most of the logic for resolving an object, and manages the parent container’s Func<object> for resolving that dependency.

public class Container
{
    protected readonly Dictionary<string, Func<object>> services = new Dictionary<string, Func<object>>();
    protected readonly Dictionary<Type, string> serviceNames = new Dictionary<Type, string>();

    public DependencyManager Register<S, C>() where C : S
    {
        return Register<S, C>(Guid.NewGuid().ToString());
    }

    public DependencyManager Register<S, C>(string name) where C : S
    {
        if (!serviceNames.ContainsKey(typeof(S)))
        {
            serviceNames[typeof(S)] = name;
        }
        return new DependencyManager(this, name, typeof(C));
    }

    public T Resolve<T>(string name) where T : class
    {
        return (T)services[name]();
    }

    public T Resolve<T>() where T : class
    {
        return Resolve<T>(serviceNames[typeof(T)]);
    }

    public class DependencyManager
    {
        private readonly Container container;
        private readonly Dictionary<string, Func<object>> args;
        private readonly string name;

        internal DependencyManager(Container container, string name, Type type)
        {
            this.container = container;
            this.name = name;

            ConstructorInfo c = type.GetConstructors().First();
            args = c.GetParameters()
                .ToDictionary<ParameterInfo, string, Func<object>>(
                x => x.Name,
                x => (() => container.services[container.serviceNames[x.ParameterType]]())
                );

            container.services[name] = () => c.Invoke(args.Values.Select(x => x()).ToArray());
        }

        public DependencyManager AsSingleton()
        {
            object value = null;
            Func<object> service = container.services[name];
            container.services[name] = () => value ?? (value = service());
            return this;
        }

        public DependencyManager WithDependency(string parameter, string component)
        {
            args[parameter] = () => container.services[component]();
            return this;
        }

        public DependencyManager WithValue(string parameter, object value)
        {
            args[parameter] = () => value;
            return this;
        }
    }
}
 
2 Comments

Posted in .Net

 

How to get your iPhone on WiFi when your proxy uses NTLM (thanks to NTLMAPS)

30 Sep

I have been struggling to get my iPhone working against my corporate ISA proxy server. Once I had connected to WiFi, Safari would continually prompt me for my domain user name and password, and none of the apps would work (maybe because they didn’t know how to prompt me for credentials).

After a bit of poking around with fiddler, telnet, and all sorts of settings, I was certain that the problem was our ISA Proxy server’s NTLM authentication.

NTLM is an authentication mechanism from Microsoft. Microsoft’s ISA Proxy Server uses NTLM to be able to tell which active directory user is attempting to access the internet.

If you’re surfing with Internet Explorer, it picks up your username directly from your login, and you might not even realise that IE is authenticating you. If you’re using firefox, you might get prompted the first time you go on the internet. As far as I can tell, Google Chrome prompts you each time you launch it.

If you’re trying to get online with an iPhone, you’re not so lucky. Safari will prompt you for credentials every time you change domains (actually, I’m pretty impressed that it can authenticate at all – nice work Apple, don’t give up!). This gets tiresome. Whats more, anything else that wants to use the internet from your iPhone has no chance.

iPhone and ISA don’t play nicely

So how do we get around this? It’s not easy. It has the potential to let other people leech your personal bandwidth and get you into trouble, if you don’t do it right. But I HAD to get online, so i started writing my own proxy server that would “chain” to ISA. It would be capable of hiding the NTLM authentication from whatever system was using it as a proxy, and then providing a preconfigured username and password to ISA “up” the chain. In order to keep my login safe from other people who could just use my proxy server, I would have locked down which IP addresses could use my proxy server.

As it turns out, someone’s already built an “NTLM Authorization Proxy Server”, and thoughtfully called it “NTLMAPS“. It’s written in python, and it works perfectly. It even has a feature to lock down IP addresses, which I strongly recommend you use.

NTLMAPS hides ISA’s nastiness from the iPhone

So how to get started? I installed NTLMAPS on my workstation – you’ll need administrative rights.

  1. Install Python from http://www.python.org/download/
  2. Unzip the NTLMAPS release from https://sourceforge.net/project/showfiles.php?group_id=69259&package_id=68110&release_id=388621
  3. Edit the server.cfg file. You will need to change the following keys
    • PARENT_PROXY – your ISA proxy server
    • PARENT_PROXY_PORT – your ISA proxy port
    • ALLOW_EXTERNAL_CLIENTS – set this to 1 to allow yourr iphone to connect
    • FRIENDLY_IPS – put your iPhone’s current wifi IP here unless you want to let everyone on your account! You’ll have to change this a lot.
    • NT_DOMAIN
    • USER
    • PASSWORD – you can leave this blank if you want – every time you start the server it will prompt you.
  4. Edit the batch file so that it points to the correct python.exe
  5. Launch the batch file. You’ll now have the NTLMAPS proxy server up & running. It will tell you the hostname and the port. If you’ve got a firewall going, and you’re lucky, the firewall will ask if you want to unblock that port.
  6. Make sure that whatever firewall you’ve got installed allows incoming connections to NTLMAPS
  7. Setup your iPhone to use your own computer as a proxy. You can do this in settings>general>network>wifi>your current wifi network. You can turn authentication off, but the server and the port (under manual proxy) should be what ntlmaps have told you to use.

There! you should be good to go. You can make sure your iPhone is getting its internet through wifi by temporarily changing your cellular data gateway to something incorrect. Google maps, the app store, weather, they should all start working once you’ve done this, as long as NTLMAPS is running.

Let me know how it goes!

 
8 Comments

Posted in How To