Wednesday, 25 September 2019

Joining GoPro video files together automatically

GoPros split up large video files into chapters, joining them back together into a single, large file is a bit fiddly.  Here's how to do it automatically using the Automator application I created (StitchGoProSession.app)

tl;dr;

Install ffmpeg using Homebrew and then drop the folder containing your GoPro chapters onto the Automator application StitchGoProSession.app

The details:

There are a few moving parts, the most important is to have ffmpeg installed.  I did this using Homebrew and the bash script in the Automator application depends on that path.  It's easy enough to change in the script, which is listed below.

Essentially the StitchGoProSession automator application is a wrapper round the bash script, but the first step is 'GetFolderContents', which produces a list of the files in the folder, which are then passed through to the script.

Tuesday, 11 June 2019

Using Automator to hack together tests of MessageBird's IVM flows

I'm in the fortunate position of being able to do some freelance work for my former employer (DrDoctor), helping them transition their Interactive Voice Message/Interactive Voice Response functionality from a well known SaaS telecomm's behemoth to their main telecomm's provider MessageBird.  Specifically moving to using their Flow Builder.

Part of that involved extensive acceptance testing of the flows we would be using for patient interactions.  This started as as very manual process, with me POSTing to the MessageBird API, receiving a call and recording it with a microphone.  This was both slow and error-prone as there were quite a few occasions when I failed to hit the record button in time (as the application didn't have focus), or I had the gain set on the mic incorrectly, or because I was thinking about the other two issues I selected the wrong option in the IVR menu.  Bad times.

However, I'm a nerd and once I start doing repetitive work I think to myself: a machine should do this while I read about AI/Blockchains/Quantum Computing etc.  With that in mind I realised that I could do almost all of this work 'in the box' (as my music producing friends say) using Automator to join up all the moving parts.

It ended up a bit Heath Robinson/Rube Goldberg, but it worked.  Automator does this:
  1. Display a list of test scenarios
  2. Remember which one is selected
  3. Generate a GUID 
  4. POST to MessageBird via curl in the Terminal
  5. Launch QuickTime 
  6. Run an AppleScript that waits until FaceTime isn't running and then saves the audio file from step 5 using the values from steps 2 and 3 to name it
I used Loopback (from Rogue Amoeba) to route the audio out of FaceTime to the input of the QuickTime audio recording.

The magic happens because when my iPhone rings, I'm able to take the call on my computer. So basically I run the Automator workflow (using the keyboard combo 'cmd + r', obvs) and wait for the call to come from MessageBird.  When FaceTime rings I accept the call on my Mac, and respond to the IVR menu on my Mac as well.  When I end the call the audio file is saved automatically (with a meaningful name, from the list of scenarios) and I can send it off to my Product Owner for review (and they in turn can send it to the client if they wish).

They say a picture speaks a 1000 words, so hopefully this video will show what all the words above mean in practice ...



Sunday, 12 February 2017

PowerShell to connect to a VPN more efficiently

TL;DR;

On starting PowerShell autoload a function that will prompt for a password which it then uses in a call to rasdial to open a previously configured VPN connection.  Why?  To stop using the mouse.

Details

If you have to frequently connect to a VPN from Windows 10, using the GUI starts to feel quite long-winded.  Particularly if (like me) you cannot save your password as part of the VPN profile (in my case the password is a token that has to be requested for every new connection, but you might equally have it mandated that the password is not to be stored locally). Fortunately with just a few lines of code, PowerShell offers a faster, mouse-free alternative.

The first thing to do is create the VPN profile (see the instructions from MS on how to do this).
Now create a script file that contains a function that will do the actual connecting to the VPN, e.g.
Function vpnMyProfile
{
$password = Read-Host -Prompt 'Enter password'
rasdial "[your VPN profile name]" [your vpn user name] $password
}

Save it in a sensible location (you'll use the path in a moment).

Finally, add a line into your PowerShell profile to the file.  I have a few scripts that I want to load when PowerShell starts so it's slightly more convoluted, but the principle is get PowerShell to
$psdir = "C:\Users\[YourUser]\Documents\WindowsPowerShell\AutoLoad" #The path from the step above
Get-ChildItem "${psdir}\*.ps1" | %{.$_} #loop through all the .ps1 files in the dir and load them

Now you should be able to simply type 'vpnMyProfile' at the PowerShell prompt and you will be prompted for your password.  Enter it and hit 'return' and hopefully you should connect to your VPN.

Added bonus: Disconnect from your VPN without using the GUI.
In the same file that contains your function to connect to your VPN, add the following:
Function vpnKill { rasdial /Disconnect}

Which is slightly quicker than typing out the command it effectively aliases (with the flag).

Using Castle Windsor to implement a Circuit breaker

TL;DR;

So that we don't send out vast numbers of SMSes or emails unintentionally, we have taken the 'Circuit Breaker' design pattern described in 'Release It!' (Michael Nygard) and implemented it using Castle Windsor's Interceptor functionality.

Details

Michael Nygard explains that a software circuit breaker works by "wrapping dangerous operations with a component that can circumvent calls when the system is not healthy", which is an excellent fit for Castle's Interceptor as it proxies method calls and the implementation (of the interceptor) can decide whether or not to invoke the original operation, based on whatever logic makes sense (in our case number of emails or SMSes sent that day, compared against historical data).

Even better, because the component that sends emails and SMSes subscribes to a message queue, "once the danger has passed, the circuit breaker can be reset to restore full function to the system." and we can simply replay any failed messages on the bus that should have been processed.

Implementation

It is very important to us that we do not send lots of SMSes or emails accidentally, perhaps because of a bug in our software or incorrect application configuration.  A circuit breaker is conceptually a good fit for that requirement: it should stop the system from going haywire when it tries to do too much of something (in same way that a real circuit breaker prevents your house from burning down because you've plugged in five electric fires in your living room).

As part of our distributed, bus-based system we have a single component that deals with sending SMSes and emails and that's all it knows how to do (there is no domain knowledge in there, it simply receives requests to send messages and makes the relevant API request to various 3rd party providers).  It listens out for various (very similar) requests for messages (generated by other components in the system) and calls our providers' apis, which again makes it a very good fit for a circuit breaker as there is, effectively, only one place to insert it.

Using a very light wrapper around EasyNetQ we have a number of 'Processors' whose job is to pick messages up from a queue and process them.  Since they all implement the same interface, it is very easy to write an interceptor for requests for various types of email that looks like this:

public class EmailVolumeInterceptor : IInterceptor
{
        private readonly EmailVolumeBreaker circuitBreaker;

        public EmailVolumeInterceptor(EmailVolumeBreaker circuitBreaker)
        {
            this.circuitBreaker = circuitBreaker;
        }

        public void Intercept(IInvocation invocation)
        {
           if(circuitBreaker.ProcessMessageTripsBreaker()
           {
                 throw new CircuitBreakerException("Limit hit for emails to be sent today");
           }

           invocation.Proceed();
        }
}

We wire these up directly in an installer class for Windsor:
Component.For<IDrDrEventProcessor<SendEmail>>().ImplementedBy<EmailSender>().Interceptors<EmailVolumeInterceptor>(),

In our case (for emails) we don't need to know anything about the request, we just need to increment a count of emails that have been sent.  Our circuit breaker has some logic around working out what its limit is and then checking whether this request would exceed that, not to mention alerting us if there's a problem.  It also has some logic around what to do when 2/3 of capacity have been reached, which extends the metaphor somewhat, but we believe could be useful.

When the breaker trips all requests to send an SMS or email (depending on which breaker has tripped) cause an exception (the method always returns true), which means that all the requests are put onto our error queue so we can replay them once we have resolved the issue.

Resetting the breaker requires manual intervention, forcing someone to resolve the issue that caused the problem in the first place.

This is our first implementation of a circuit breaker and it's definitely been a learning experience. Technically it's been reasonably straight forward, but the difficulties have arisen from business questions:
 - what is a reasonable test for the breaker to perform? i.e. what is the metric you choose in order to decide whether your call to send an SMS should be ignored or not?
 - are we prepared to deal with having to fix things after it trips (akin to having to reset your microwave clock after a real circuit breaker trips)?
 - wait, what happens if we send a load of junk but the volume of it doesn't trip the breaker? (a circuit breaker won't stop you getting an electric shock from something that's wired incorrectly ... although it might trip if you create a short to Earth ... but I digress).
 - are you sure it's working?  Should we test it in production?

Wednesday, 8 July 2015

Commandline VLC with global hotkeys (using QuickSilver and Karabiner)

TL;DR;

Create a trigger in QuickSilver that pipes the word 'pause' to the rcold interface of VLC.

Details

Imagine having a Mac and not wanting to use iTunes.  Imagine hating iTunes so much that you'd rather use an interface that looks like this:
Unlikely, I realise, but that's where I'm at.  I really don't need or want a complicated media center [sic] application that puts the kettle on while it tries to download album art, so I use the VLC NCurses interface.  It's far from perfect, but I really, really hate iTunes, so this it's an OK option.

However, what I do miss is having a single key to pause music play back, whether the player has focus or not i.e. what I used to have with the F8/play-pause in iTunes. It turns out there are ways to achieve this.

First up, this is how I launch VLC

Which basically says, launch VLC using the NCurses interface, starting in the following browse directory, also use an extra interface, Old Remote Control and while you're at it create a socket to communicate with it called /tmp/vlc.sock. Which means that I now have two interfaces controlling VLC: NCurses, which I use to browse for music from my music library, and oldrc, which I use to be able to stop and start playback using a global hotkey.

As I mainly use my laptop keyboard I'm missing a few function keys that would be really handy here.  Enter Karabiner which allows me to map Fn + SPACE to F13, with something like this in the private.xml

The final step is to create a hotkey using QuickSilver which is done in the Triggers section of the QuickSilver Configuration. Click the '+' symbol and select 'HotKey'.  Paste the following
into the 'Select an item' field and set the action to 'Run Command in Shell'.

Job done, every time I hit 'Fn + SPACE' I send the command 'pause' to that socket.  On the other end of that socket the VLC rc interface understands that and toggles pause/play. Unfortunately there is a minor irritation in that the rc interface produces output like this:
status change: ( play state: 3 )
pause: returned 0 (no error)
status change: ( pause state: 3 ): Pause

that is then dumped out onto the NCurses console space (which looks terrible).  A simple solution is to hit 'Ctrl + l' to clear the UI.  Ideally I'd stop this happening at all, but I haven't figured out how.  Yet.

Monday, 6 July 2015

Parallels, Ubuntu, Emacs - weird Meta key behaviour

I'd been tearing my hair out over an issue I was having with Emacs (24.3.1) on an Ubuntu (14.04) VM running under Parallels (10.1.2) where I had to hold down the Meta key and hit the character key twice in order to make it work i.e. in order to get Emacs to respond to M-x I had to type M-x-x, or for M-w I had to type M-w-w.  Whilst this wasn't the end of the world, it was annoying as I want a consistent experience across environments when using Emacs.

I'm not sure where the problem stemmed from, but I do use Karabiner to remap my OSX modifier keys, so that I have Command, Control,  Option, Space, Option, Control, as that way I have two sets of Control and Meta keys, one under each hand.  Anyway, after spending too long trying to do more and more convoluted remapping in Karabiner to work around the problem (and failing) I discovered a far simpler solution in Parallels itself.

Opening up the configuration for the VM (Actions > Configure ...) then selecting the 'Hardware' tab, then 'Mouse & Keyboard' and clicking 'Shortcuts' presents you with a list of keyboard mappings (e.g. Command+x -> Ctrl+x).  Clicking the '+' symbol allows you to add further mappings and if you select 'Alt' in the 'From' row and 'Alt' in the 'To' row this maps 'Option' to 'Alt' and voila the Meta key works as expected in Emacs in the Ubuntu VM.

Sunday, 22 March 2015

Overriding dependencies with Castle Windsor in SpecFlow tests

At DrDoctor we have a reasonable set of Spec tests using SpecFlow.  These tests tend to be a lot more involved than our unit tests as they always exercise most (close to all) of an application - and sometimes even multiple applications that make up portions of the entire system.  We don't have hard and fast rules about how much of the system a set of specs should cover, but they tend to end up as fairly significant integration tests, almost always hitting the database for example.

As these specs tend to be written prior to the implementation* we often start with dependencies mocked out and as we implement the system under test move to real objects.  For instance, we might start with a mock IGetThatObjectYouNeed data access class that ends up being implemented as part of the functionality we are building.

However, once the functionality is built, we finish in a situation where the component we have been working on has its dependencies composed using an IoC container (Castle Windsor) and the specs build up the required dependency graph manually.  While that's not catastrophic, we really like our specs because they show up problems with an application in a way that unit tests don't, so knowing that the application is composed in the same way in the specs and in the real world also helps us sleep easy.  It's kind of like the difference between knowing that all the parts of a car work and knowing that all the parts work and they've been put together the right way.

A fairly simple way to do this is to use Castle's fluent registration to call your application's installer e.g.
var container = new WindsorContainer().Install(new YourApplication.Installers.YourInstaller());
var sut = container.Resolve<ApplicationEntryPoint>();

A problem with this though is that it may use every concrete implementation that your application requires, which might not be what you want for tests that are run many times a day.  For instance if your application sends SMSes via a 3rd party service, you probably don't want your automated tests using that.

In order to avoid this, you can have multiple installers in Windsor and then only call the installers you need.  We have a separate BusInstaller for exactly this reason, so that we can use a different implementation in our tests.  Having said that you probably want your installers separated out into areas that make sense for your application, not that make sense for your specs.  Also, you probably don't want to have to change your installers because of modifications to your specs.

In order to avoid using specific implementations that are registered in an installer that you don't want to modify, you can use another feature of Castle Windsor that allows you to register multiple implementations of a type and declare one as default (http://docs.castleproject.org/Windsor.Registering-components-one-by-one.ashx)

Thus you might have an installer that looks something like this:
public class MyComponentInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<IDoSomethingYouCareAbout>().ImplementedBy<SpecificImplementation>(),
            Component.For<IStuffRepository>().ImplementedBy<StuffRepository>(),
            Component.For<IHitAnExternalResource>().ImplementedBy<ServiceYouDoNotWantToHit>(), // don't want this to be used in the specs
            Component.For<IAmAlsoUsefulToTest>().ImplementedBy<AnotherSpecificImplementation>(),
            Component.For<IAmAnotherRepository>().ImplementedBy<AnotherRepository>(),
            Component.For<ApplicationEntryPoint>());
    }
}

Then in your spec wherever you set up your system under test:

var container = new WindsorContainer().Install(new MyApplication.MyComponentInstaller());
container.Register(Component.For<IHitAnExternalResource>().UsingFactoryMethod(Mock.Of<IHitAnExternalResource>).IsDefault());
systemUnderTest = container.Resolve<ApplicationEntryPoint>();

The second line, using 'IsDefault()', means that rather than having to remove the 'ServiceYouDoNotWantToHit' from the container, we override it with our mock (we're using MOQ, if you're wondering about the syntax), by setting it as the default implementation that Castle returns.

In this way you can avoid whichever concrete implementations you want, but still have quite a high level of confidence that your actual application is composed correctly.


*we're not purist BDDers, but it's a style that works well for us a lot of the time.

Monday, 10 November 2014

Launching Windows applications in Parallels from OSX without UAC prompts

TL;DR; 

Use a scheduled task to avoid UAC prompts in Windows; create a shortcut to the scheduled task; use a shell script to tell Parallels to use Windows Explorer to open the shortcut.

Details ... 

As a .Net developer using an OSX machine I'm a big fan of Parallels Desktop. I'm also a big fan of not taking my hands off the keyboard as I find that using a trackpad or mouse gives me some pain in the back of my hand and wrist. One way I help myself with this is by not using the mouse to launch applications. In both Windows and OSX this is relatively straightforward, but in Windows two of the applications I use a lot I really need to use with admin privileges (the console/command line and Visual Studio). The best way I've found to avoid doing extra mouse work (or just extra key presses) is to use a Scheduled Task in Windows and create a shortcut to it. Details of how to do this here: http://www.7tutorials.com/use-task-scheduler-launch-programs-without-uac-prompts

Great, so now I don't have to say "yes, please let me run this application as an administrator" every time I want to use Visual Studio. But I want more. I want a single way of launching applications on Windows and OSX.

Step forward QuickSilver - free and awesome. It used to be the case that I could just double-click on my Windows Shortcut (.lnk) files to launch the applications in OSX, so I kept them in my Quick Silver catalog and just used QuickSilver in the normal way, but recently this stopped working.

Double clicking on the shortcut in Windows still worked, double-clicking or right-clicking and selecting 'Open with' either 'Parallels Link' or 'Windows Explorer' didn't work either.

I never worked out what had changed (Windows? Parallels? Sun spot activity?) but I did find a solution. I now have a bunch of shell-scripts that look like this:
Which means that I can easily launch the applications I use most, without UAC prompts, from OSX.

Saturday, 27 September 2014

OSX, .NET vNext and file paths

I've been playing around with .Net vNext on my OSX laptop and hit a stupid issue with file paths that might possibly trip someone else up.  I was trying to get a .NET program to launch another application and open a file (VLC and an mp3). I had code that looked like this:
var filePath = "/Volumes/StorageHD/Audio/iTunes Music/Air/Talkie Walkie/01 Venus.mp3";
var p = new Process();
p.StartInfo.FileName = "/Applications/VLC.app/Contents/MacOS/VLC";
p.StartInfo.Arguments= filePath;
p.Start();
Console.ReadKey();

This code launches VLC, but each space in the file path is parsed as a new file name, so VLC attempts (and fails) to play iTunes, Talkie, Walkie, 01 and Venus.mp3.

My first attempt to fix this was to escape the file path as a Unix file path i.e.
"/Volumes/StorageHD/Audio/iTunes\ Music/Air/Talkie\ Walkie/01\ Venus.mp3"
which is what I'd use if I were trying to do something similar from the shell:
$ vlc /Volumes/StorageHD/Audio/iTunes\ Music/Air/Talkie\ Walkie/01\ Venus.mp3

This was not the correct option ;) - my little console application threw a lot of stack-tracey goodness, but the main point was "Unrecognized escape sequence".

Instead I needed to escape the path as I would on windows, with the path with spaces in wrapped in double quotes:

var filePath = "\"/Volumes/StorageHD/Audio/iTunes Music/Air/Talkie Walkie/01 Venus.mp3\"";
Notice the escape character ("\") before the wrapping quote.
The final full code is available as a gist https://gist.github.com/StephenFriend/593aa94366cd4733be46

Monday, 25 August 2014

Scripting Parallels VM backup

In an attempt to automate all the things, I've scripted the backup of my Parallels VM for disaster recovery.  Ultimately I plan on using something like this in conjunction with Launchd, but for now the script is available as a gist:
https://gist.github.com/StephenFriend/69477732bbb1423942f4

Hopefully someone else will find it useful.

Saturday, 21 June 2014

Lean and Agile - what does that actually mean in practice at DrDoctor?

At DrDoctor there is a very strong belief that the business should be Lean (note the capital 'L'), so we analyse data on how our services are used in order to guide product development.  An important aspect of that is that we need to get features out there in order to see how they're used, which fits neatly with a Scrum-based, Agile approach.  We do favour working software over comprehensive documentation and we aim to deliver that working software every sprint (i.e. every two weeks).  Worse than that, following lean principles, we don't just value responding to change over following a plan we acknowledging that a core strength is our ability to change our plans.  Yes there is a vision, but no, I don't pretend to know for certain what I'll be working on in two months' time.

What does this mean in practice?  At a very high level, it means that we need to be able to release features easily.  Or put another way, having a 'release sprint' (which I've seen in lots of places) means we've failed.  We haven't always succeeded in this, but we're getting there and we are now at the stage where we have decent CI and automated deployment, we can ...
  • Push changes to our central code repository
  • Which triggers a build on our build server
  • Which runs our test suite (unit tests, integration tests that exercise the DB and bigger 'Spec' tests that lean on even more infrastructure)
  • We're notified if the build passes or fails
  • With 5 button clicks we can deploy the build to our 'smoke test' environment where we can do a full end-to-end test - our product owners get to run through the feature they've asked for
  • 5 more button clicks and we've deployed to production
To achieve all of this, we use Git, BitBucket, TeamCity, NUnit, SpecFlow, HipChat and Octopus Deploy and I'll write a post on some of the technical details of how that's set up.

However, the main point isn't about the tools, it's about the mindset.  Lots of companies talk about Lean and Agile but don't deliver (if you've ever sat through a 30 minute "stand-up", you know what I'm talking about), but at DrDoctor the value of delivering software rapidly is understood, which translates into investing time into making delivery easy.  There is a lot more to do, but the whole company agrees that we don't say a story is delivered unless the code is running somewhere.

Wednesday, 27 November 2013

Open source tools we use - addendum

I realised that in my previous post I forgot to mention log4net on the list of OSS that we use at DrDoctor.  This is probably because it's like Léon - does the job quietly, professionally and you barely notice it's there.  Until you it's really important that it's there.

So yeah, just a bit of love for log4net because it got overlooked because we don't have to think about it.

Saturday, 23 November 2013

Open source tools we use

At DrDoctor we're on a .NET stack (and we're Bizspark members) but that doesn't mean we don't love open source tools - what we want is the right tools - and the .NET world is full of them. We've used a few and I thought it might be useful for people to see what choices we've made.  So here goes:

1) RabbitMQ.  Correct, it's not MS, but at no point did we ever consider using MSMQ.  It's an awesome messaging infrastructure with a great .NET client.  It works and it works well.
2) EasyNetQ Fantastic light-weight, open source Bus implementation on top of RabbitMQ.  It's actively developed, well documented and we got it working in about two days.  It's at a 0.x release at the moment, so breaking changes do happen, which means we've taken a cut of the code that we're happy with (I possibly managed to push a breaking change into our build before I realised this ;)  ).  Hopefully at some point we can contribute something back.
3) Topshelf Makes working with Windows Services a pleasure.  It's used by a lot of other projects (e.g. NServiceBus) because it's great. 
4) Castle Windsor Powerful IoC with a tonne of well written documentation.
5) Magnum library We only we use one thing from this library (the State Machine) but it's at the core of our business logic. Created by the same guys who brought you Topshelf (see above).  Almost non-existent documentation, but really handy utilities.
6) Simple Data Mark Rendle's rather excellent data access library (we use it on top of SQL Server).
7) NancyFX Nice light-weight web framework (an alternative to MS's WebAPI and MVC frameworks).

Of those six seven tools I'd say that easyNetQ, Topshelf, Magnum, NancyFX & Simple Data are all about developer productivity.  Simply put, they are tools that allow us as developers to work on business features rather than infrastructure.

RabbitMQ is a fundamental architectural choice.  DrDoctor is event driven by its very nature, so a messaging infrastructure fits perfectly.  It also leads to a clean separation of concerns with components that communicate via RabbitMQ in an asynchronous fashion.  This in turn leads to a much easier development and deployment cycle: if we're working on our appointment management logic and need to deploy an update it's one component that needs to come down, while our entire application remains up.  SOA baked in from the start.

NancyFX feels more like the Python/Rails world and doesn't carry all the kludge that comes with the .NET MVC/WebAPI frameworks.  Seriously, I don't need the Entity Framework stuff.  I really, really don't.

Which really just leaves Castle.  There are loads of IoC containers out there, I just happen to feel most comfortable with Castle. 

Saturday, 9 November 2013

Changing the ways queues are named in EasyNetQ

Update: In the time it took me to make the change to our code and write the blog post below, EasyNetQ got updated, thus rendering this post obsolete.  I'll soon be doing a new version that uses the latest version.

At my current company (DrDoctor) we're using EasyNetQ as a lightweight bus implementation on top of RabbitMQ. EasyNetQ has a lot of very nice features, one of which is auto-creation of exchanges and queues. It uses the fully qualified name of the message type as its basis, but we have quite a deep hierarchy of messages, which makes sense in the tree-structure of our solution, but makes looking at the queues painful as we end up with long names.

Fortunately EasyNetQ is very extensible which allows you to change those conventions (and many others). The basis for this is taken from the documention: https://github.com/mikehadlow/EasyNetQ/wiki/Replacing-EasyNetQ-Components

The 'CreateBus' method has an overload that allows you to pass in your own services. When 'CreateBus' is called, if you pass in your own service (for instance IEasyNetQLogger from the example in the documention), your service gets registered first and so the default service registration doesn't happen (take a look at DefaultServiceProvider.Register for details).

In our case we wanted to alter the way queues and exchanges are named, which is slightly more complex because there isn't a separate service for each of those, instead there is a 'Conventions' service which sets these. However, that service is itself easy to poke from the outside. Here's some code:
 IConventions conventions = new Conventions();
conventions.QueueNamingConvention = (messageType, subscriptionId) =>
{
    var queuePrefix = EasyNetQNamingConvention.GetNameFromType(messageType);
    return string.Format("{0}:{1}", queuePrefix, subscriptionId);
};

conventions.ExchangeNamingConvention = EasyNetQNamingConvention.GetNameFromType;            
RabbitHutch.CreateBus(connectionString.ConnectionString, serviceRegister => serviceRegister.Register(provider => conventions));


The method 'GetNameFromType' is a static method that returns a string, based on the type passed in.
public static string GetNameFromType(Type type)
{
 if (type.GetInterface("IMyMessage") == null)
  throw new ArgumentException("Type must implement IMyMessage");

 string category = null;

 foreach (var attr in type.GetCustomAttributes(false).OfType<MessageCategoryAttribute>())
 {
  category = attr.Category;
 }

 if (category == null)
  throw new ArgumentException("Implementation must be marked with MessageCategoryAttribute");

 return category + "_" + type.Name;
}
This suits our needs as it means we can (and indeed have to) mark up our messages with an attribute that categorises them.

There is a bit of gotcha with this, however. We have effectively replaced the use of the EasyNetQ method 'TypeNameSerializer.Serialize' for our exchanges and message queue names, which is fine, but this method is used elsewhere that could cause a problem. There is another service that is registered
.Register<SerializeType>(x => TypeNameSerializer.Serialize)
, and SerializeType is used in DefaultMessageValidationStrategy.

Again though the solution is simple, substitute in your own implementation:

RabbitHutch.CreateBus(connectionString.ConnectionString, serviceRegister =>
 {
  serviceRegister.Register(provider => conventions);
  serviceRegister.Register<SerializeType>(provider => EasyNetQNamingConvention.GetEasyNetQNameFromType);
 });
);

Sunday, 1 September 2013

Wire up a chain of responsibility with Castle Windsor

As part of the greenfield project I'm currently working on I decided that I'd use the chain of responsibility design pattern, but it took me a little while to work out how to set up Castle Windsor to support this.  It's pretty simple, but the stuff I found on the interwebs all seemed to be slightly out of date, so I thought I'd explain it here.

The short version is you can use the 'DependsOn' and 'Dependency.OnComponent<T, U>' methods when registering your components to do this pretty easily.  You can use an installer that looks something like this:
public class ChainOfResponsibilityInstaller : IWindsorInstaller
{
 public void Install(IWindsorContainer container, IConfigurationStore store)
 {
  container.Register(Component.For<IChainItem>()
         .ImplementedBy<ChainItemOne>()
         .DependsOn(Dependency.OnComponent<IChainItem,ChainItemTwo>()),
         Component.For<IChainItem>()
          .ImplementedBy<ChainItemTwo>()
          .DependsOn(Dependency.OnComponent<IChainItem, ChainItemThree>()),
         Component.For<IChainItem>()
           .ImplementedBy<ChainItemThree>());
 }
}

I've put a very basic project up on GitHub - https://github.com/StephenFriend/ChainOfResponsibility-with-Castle - to demonstrate an actual working solution.

Monday, 24 June 2013

Replacing Forms Authentication with the Session Authentication Module

In this post I'm going to run through how to use the SessionAuthenticationModule (SAM) (part of Windows Identity Foundation (WIF) in .Net 4.5) for authentication and authorization in a simple MVC application, replacing Forms Authentication. It won't be production code, but if after reading this you'd like to see a more complete Membership and Identity management library take a look at Brock Allen's Membership Reboot on GitHub https://github.com/brockallen/BrockAllen.MembershipReboot

The solution that goes along with this post is available at https://github.com/StephenFriend/AuthWithWIFAndSAM and it will probably be easier to look at the code as you read this. In the walkthrough below, I've used Visual Studio 2012 and there are different tagged commits, so that it's easy to see the changes that are made as we move from Forms Authentication to using the Session Authentication Module.

First, I'll set up an extremely simple solution using forms auth.  If you've cloned from github, simply type git checkout -f formsAuth

The first step is to create a new MVC4 app (imaginatively called 'DemoSite' in the code), using the 'Internet Application' Project template.  Next we want to amend the Web.config file at the root of the MVC site. 

In the controllers folder create a Home controller using the 'Empty MVC Controller' template from the drop-down in the scaffolding options section of the dialogue.  The code for the Home Controller should look like this:
[Authorize]
public class HomeController : Controller
{
 [AllowAnonymous]
 public ActionResult Index()
 {
  return View();
 }

 public ActionResult MyStuff()
 {
  return View();
 }
}

Note the use of the 'Authorize' attribute on the whole class and the 'AllowAnonymous' attribute on the 'Index()' method.  This should mean that anyone is able to access the Index view, but only users that are authorized can access the MyStuff view.

Next up let's create an Account controller.  The code for this will look like this initially:
public ActionResult Login()
{
   return View();
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginInput model)
{
   if (ModelState.IsValid && LoginDetailsAreValid(model))
   {
    FormsAuthentication.SetAuthCookie(model.Email, false);
    return RedirectToAction("MyStuff", "Home");
   }

   ModelState.AddModelError("", "The user name or password provided is incorrect.");
   return View(model);
}

// In the real world this would be likely be a call to the database to get the user details, with a validation 
// that the user exists and that their password is correct.  See WebMatrix.WebData.SimpleMembershipProvider.ValidateUser()
// for an example (download the ASP.Net web stack here: http://aspnetwebstack.codeplex.com/)
private bool LoginDetailsAreValid(LoginInput loginDetails)
{
 return (string.Compare(loginDetails.Email, "you@example.com",
         StringComparison.InvariantCultureIgnoreCase) == 0 &&
   string.Compare(loginDetails.Password, "password", StringComparison.Ordinal) == 0);
}

In order for this to compile you'll also need to create a LoginInput class (in the Models folder), which is a simple View Model that we'll use to create the login view and user input.  It should look like this:
public class LoginInput
{
 [Required]
 public string Email { get; set; }
 [Required]
 [DataType(DataType.Password)]
 public string Password { get; set; }
}

The end point of this first stage is to create the views that go with the various controller actions. Home/Index looks like this:
@{
    ViewBag.Title = "Index";
}

Welcome to the demo

@Html.ActionLink("Login", "Login", "Account") @Html.ActionLink("My Stuff", "MyStuff", "Home")

Account/Login looks like this:
@model DemoSite.Models.LoginInput

@{
    ViewBag.Title = "Login";
}

Login

@if (User.Identity.IsAuthenticated) { You are already logged in as @User.Identity.Name
} else { using (Html.BeginForm()) { @Html.ValidationSummary()
@ViewBag.Title @Html.EditorForModel()
} }

and Home/MyStuff looks like this:
@{
    ViewBag.Title = "MyStuff";
}

Congratulations, you're authenticated


If you start up the website now, you should be able to log in (as you@example.com, password = 'password') and if you check your cookies, you will see that a cookie called .ASPXAUTH has been created.  If you try to access Home/MyStuff without logging in you will be automatically redirected back to Account/Login

Now, we're going to stop using Forms Authentication, initially not replacing it with anything.  (Use git checkout -f noAuth to see the code in the repo).

To start, go to the web.config file and change the authentication node from:

  

to:

This means that the FormsAuthenticationProvider module will no longer be loaded at application start-up.  Once you've done this, you'll see that if you log on you'll be presented with a 401 error when you are redirected to 'MyStuff'.  If, however, you check your cookies, you'll see that the call to FormsAuthentication.SetAuthCookie in the AccountController has set a cookie, but there is no provider specified so the 401 error is displayed on actions that have an 'Authorize' attribute.

In order to use the SAM module you will need to alter your web.config so that includes the following elements in the <config sections> element:

The first of these is to "configure a service or application to use Windows Identity Foundation" [1], the second names the configuration section for federation configuration, which you'll need to add to the config file:

    
      
    
  

The default configuration requires SSL, so you will need this section if you don't want to sort out setting up SSL for this example.

Under <system.webServer><modules> you will need to add the following so that the SessionAuthenticationModule is added to the ASP.Net pipeline.:


In order to have access to the classes you have just configured, you will also need to add references to System.IdentityModel and System.IdentityModel.Services to your project.

Finally, you need to alter the Account controller to look like this:
public class AccountController : Controller
    {
       public ActionResult Login()
       {
           return View();
       }

       [HttpPost]
       public ActionResult Login(LoginInput model)
       {
           if (ModelState.IsValid && LoginDetailsAreValid(model))
           {
               WriteAuthCookie(model.Email);
               return RedirectToAction("MyStuff", "Home");
           }

           ModelState.AddModelError("", "The user name or password provided is incorrect.");
           return View(model);
       }

        // In the real world this would be most likely be a call to a database to get the user details, with validation 
        // that the user exists and that their password is correct.  See WebMatrix.WebData.SimpleMembershipProvider.ValidateUser()
        // for an example (download the ASP.Net web stack here: http://aspnetwebstack.codeplex.com/)
        private bool LoginDetailsAreValid(LoginInput loginDetails)
        {
            return (string.Compare(loginDetails.Email, "you@example.com",
                                   StringComparison.InvariantCultureIgnoreCase) == 0 &&
                    string.Compare(loginDetails.Password, "password", StringComparison.Ordinal) == 0);
        }

        private void WriteAuthCookie(string userEmail)
        {
            var claims = new List();
            claims.Insert(0, new Claim(ClaimTypes.Name, userEmail)); 
            var claimsId = new ClaimsIdentity(claims, "Password");
            var cp = new ClaimsPrincipal(claimsId);
            var sam = FederatedAuthentication.SessionAuthenticationModule;
            var token = new SessionSecurityToken(cp);

            sam.WriteSessionTokenToCookie(token);
        }
    }

As you can see the new WriteAuthCookie method deals with persisting the authentication details to a cookie.  In it we create a new Name claim (the only claim we use in this example), that is then used to create a ClaimsIdentity, which in turn is used to create a new ClaimsPrinciple that is then persisted to a cookie.
Once you have logged in, if you check your cookies, you should see that you have a new 'FedAuth' cookie, which is what the SAM module uses.  If you then go back to Account/Login you should see that the claim of 'Name' is used for the User.Identity.Name property that is displayed on that page if you're logged in.

[1] http://msdn.microsoft.com/en-us/library/hh568638.aspx - MSDN WIF Configuration Schema

Monday, 10 June 2013

How not to manually manage Garbage Collection

Sometimes code tells you something about the person that wrote it.  I've had the pleasure of working with a codebase that contains the following code*:
while (MainApplicationWork())
{
 GC.Collect();
 GC.WaitForPendingFinalizers();
 GC.Collect();
 GC.WaitForPendingFinalizers();
}

NullMyObjectGraph();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers(); 

Which I think bears some scrutiny - whenever you see a call to GC.Collect your .Net spidey sense should be going bonkers.

Code like this is dotted throughout the suite of applications this snippet comes from, specifically this:

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();

which implies that this is standard practice for the dev that wrote it, rather than the response to a problem.  It's conceivable that this person has done a lot of performance tests and could demonstrate that all the calls to GC.Collect are justified.  Or more formally, it's a logical possibility, like the sky being green or everyone from Birmingham having six fingers on their right hands.

Unfortunately because the code is proprietary I can't share the full horror and give the performance metrics to demonstrate how truly awful this is - for instance, the application that contains the top snippet calls GC.Collect() at least four times for every iteration of the while loop.  However what I can do is examine this code, look at why you might do something like this and try to show that the code tells you that the person who wrote it doesn't really understand it.

There are many sources that tell devs to not call GC.Collect() [1, 2], however there are some circumstances when it might be the right thing to do.  According to Microsoft you should "Use the Collect method when there is a significant reduction in the amount of memory being used at a defined point in your application's code."[3]  Rico Mariani also offers this piece of advice for when you might call GC.Collect, "if some non-recurring event has just happened and this event is highly likely to have caused a lot of old objects to die."[4]

At first glance this code doesn't seem to fit that last piece of advice, since it sits in a while loop, however the method that is used for the loop termination criterion (MainApplicationWork()) effectively returns false when there are no more records for the application to process.  Those records do not arrive in a regular fashion, so it is arguable that this is an event that occurs repeatedly, but is irregular (perhaps akin to the canonical example of a user closing a windows form - it might happen multiple times, but it's not a predictable event and so the GC algorithm self-tuning will not work).

When the call to GC.Collect() is made it "Forces an immediate garbage collection of all generations."[5]  Part of this process involves moving pointers from the finalization queue to the freachable queue for all objects with Finalizer methods that have been found to be garbage (i.e. are unreachable).  Interestingly this resurrects the objects you are trying to get rid of because there is now a reachable reference to them (on the freachable queue, which is considered a root) and they will only become unreachable again once their finalizers have been run by the Finalization thread (which runs automatically whenever there are objects in the freachable queue).

Because of this it is recommended[6] to call GC.WaitForPendingFinalizers after GC.Collect as this forces the current thread to wait until all the finalizers in the objects you are trying to clear up have been executed and thus avoids the objects getting promoted to Gen1.  Given that we've just resurrected some objects, it is recommended to call GC.Collect again to finally release the memory of all the objects that have just been finalized. So you should end up with:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

But in this codebase there is a further call to GC.WaitForPendingFinalizers which does, ummmm, precisely nothing since the only compaction/garbage collection that takes place as part of the second call to GC.Collect() is of the objects on the heap that have just been finalized.  Nothing else has changed in the application in the meantime since both GC.Collect() and GC.WaitForPendingFinalizers() block the current thread.

Does it do any harm?  Probably not (although that requires some actual performance metrics to be confident on), but what it does shout is that this snippet is a piece of cargo-cult programming, repeated through a codebase, no doubt with the best of intentions, but almost certainly for no good reason and very likely damaging application performance.


* more or less - the application method names have been changed to protect the innocent
1. http://blogs.msdn.com/b/ricom/archive/2003/12/02/40780.aspx - Rico Mariani "Two things to avoid for better memory usage"
2. http://msdn.microsoft.com/en-us/library/ff647790.aspx - MS Patterns & Practices "Improving Managed Code Performance"
3. http://msdn.microsoft.com/en-us/library/bb384155.aspx - MSDN "Induced Collections"
4. http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx - Rico Mariani "When to call GC.Collect()"
5. http://msdn.microsoft.com/en-us/library/xe0c2357.aspx - MSDN Library GC.Collect definition
6. http://msdn.microsoft.com/en-us/library/ff647790.aspx - MS Patterns & Practices "Improving Managed Code Performance"

Sunday, 26 May 2013

AngularJS Tutorial and .Net Web API (part 5)

In this blog post I'll look at getting steps 9, 10 & 11 of the AngularJS tutorial running on top of the .Net Web API (http://docs.angularjs.org/tutorial/step_09 http://docs.angularjs.org/tutorial/step_10). None of these tutorials requires changes to the .Net code, so this should be fairly straightforward.

First step 9. Do the usual git checkout thing one, other or both the original AngularJS tutorial code and this version. git checkout -f step9 for the .net version.

Copy app/js/filters.js from the Angular tutorial into the Scripts directory of the .Net project. Update Scripts/app.js to register the dependency on the phonecatFilters module. Update Views/Home/Index.cshtml to include a reference to the new Scripts/filters.js file. Update the Angular template (AngularPartials/phone-detail.html) to use the new filter. Ummm, that's it - behold the cross or the tick under GPS and Infrared on the phone-detail page.

On to step 10 - for the .Net code use git checkout -f step10.
Just follow along with the AngularJS tutorial. Update Scripts/controllers.js and update the template AngularPartials/phone-detail.html to change the main image source and add the 'ng-click' attribute to the smaller images. Finally copy across the latest version of app/css/app.css so that you get the cursor changing to 'pointer' when hovering over the click-able images.

And so finally onto step 11.

This tutorial is about tidying up the Angular code so that some of the implementation details are abstracted away, in effect moving the call to the .Net Web API to a different place. As such it means we don't need to touch the .Net code, however there is a change to the way in which AngularJS makes its requests, which needs a bit of attention.

Working along with the original AngularJS tutorial, amend Views/Home/Index.cshtml to include references to Scripts/services.js and Scripts/angular-resource.js. This latter should exist already (coming down with the nuget package), but you'll need to copy the services file into the Scripts directory. You'll also need to amend the registration of the 'Phone' service in the Scripts/services.js file to reference the Web API controller.
angular.module('phonecatServices', ['ngResource']).
    factory('Phone', function($resource){
         return $resource('api/phones/:phoneId', {}, {
            query: {method:'GET', isArray:true}
  });
});
Note the slight differences here from the AngularJS tutorial. First the path is to api/phones, secondly when the 'query' is set up I've removed the paramDefaults array because in its original state it causes Angular to make an http request to api/phones/phones when there is no parameter specified, which we don't want because that makes the Web API try to return us a PhoneDetail item with the id 'phones'. In the original tutorial this will cause a call to /phones/phones.json which works perfectly.

Now you just need to register the services in app.js, then amend the Scripts/controllers.js to use the service. This should be exactly the same as the Angular tutorial.

That's it - hopefully the AngularJS tutorial now looks the same live demo http://angular.github.io/angular-phonecat/step-11/app/#/phones

Friday, 24 May 2013

AngularJS Tutorial and .Net Web API (part 4)

In this post I'll get step 8 of the AngularJS tutorial http://docs.angularjs.org/tutorial/step_08 running on top of the .Net Web API.  This tutorial uses more data, so we'll be plumbing in further ApiController actions to connect the Angular code to the data source (JSON text files).  I'll also take a look at some of the under-the-covers stuff about how the ApiController works when resolving requests to actions.

The code for the Web API can be got by using git checkout -f step8.

As per the Angular tutorial, use git to checkout out step 8 of the original tutorial, then copy all the phone model json files from app/phones (i.e. everything apart from phones.json, which you should have edited previously and don't want to overwrite).  Unfortunately all of these files contain a reference to an image file that won't work with our website directory structure, so you'll need to amend the paths in the 'images' section of the JSON files so that the paths point to "Content/img/phones" rather than "img/phones".

Following along with the original tutorial we're going to update the Angular controller (Scripts/AngularControllers/controller.js) so that it makes an http get request for the data the phone-detail view requires.  However it's going to call an action on our Phones controller, rather than make a direct call to a JSON file.  So the function call should look like this:
function PhoneDetailCtrl($scope, $routeParams, $http) {
    $http.get('api/phones/' + $routeParams.phoneId).success(function (data) {
        $scope.phone = data;
    });
}
Once again the path is to 'api/phones' so we'll be calling the Phones controller.  Note that we're also passing the phoneId, which in this case is a string.

Now update the AngularPartials/phone-detail.html file so that it matches the one from the AngularJS tutorial (app/partials/phone-detail.html).

In order for this to work we will need to update the PhonesController class so that it has a method that can respond to this call.
public PhoneDetail GetPhoneBy(string id)
{
 return this.phoneRepo.GetBy(id);
} 
There are a couple of things to note here.  First and most obviously, there's no 'PhoneDetail' class or GetBy(id) method on the repository - we'll add those in shortly.  More subtly, it's also worth thinking about what the ApiController does when it receives a Get request.  The base ApiController class uses a convention whereby it will try to match requests to method names that contain the the request type and the route parameters, (in this case 'Get' and a string).  What this means is that you cannot have two methods names that contain the same request verb (in this case 'get') that have the same signature in your ApiController.  It also implies that it doesn't matter what your methods are called from the application's point of view, those method names are really just for your benefit. 

If you do have two methods with the request type in their name and the same signature, the framework will throw a System.InvalidOperationException which will be caught and transformed into a 500 error response. For further detail download the code from http://aspnetwebstack.codeplex.com/ and take a look at System.Web.Http.Controllers.ActionSelectorCacheItem.SelectAction. Look for:
throw Error.InvalidOperation(SRResources.ApiControllerActionSelector_AmbiguousMatch, ambiguityList);
and
System.Web.Http.Dispatcher.SendAsync
Ultimately this means that Angular will return an empty template and you'll have to track down what the 500 error means.

Having said that, our controller has a single 'Get' method that takes a string as a parameter, so no issues there. It then calls a non-existent method on the repository class.  So, let's update the repository interface and implementation accordingly.
public interface IPhoneRepository
{
 IEnumerable<Phone> GetAll();
 PhoneDetail GetBy(string id);
}

public class FileDrivenPhoneRepository : IPhoneRepository
{
 public IEnumerable<Phone> GetAll()
 {
  string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
  var phonesText = System.IO.File.ReadAllText(dataDirectory +"/phones.json");
  return JsonConvert.DeserializeObject<List<Phone>>(phonesText);
 }

 public PhoneDetail GetBy(string id)
 {
  string dataDirectory = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
  var phoneText = System.IO.File.ReadAllText(dataDirectory + "/" + id + ".json");
  return JsonConvert.DeserializeObject<PhoneDetail>(phoneText);
 }
}
Finally I'll create a new PhoneDetail Model (or ViewModel if you prefer).  Add a class 'PhoneDetail' to the Models folder:
public class PhoneDetail
{
 public string additionalFeatures { get; set; }
 public AndroidDetail android { get; set; }
 public string[] availability { get; set; }
 public BatteryDetail battery { get; set; }
 public CameraDetail camera { get; set; }
 public ConnectivityDetail connectivity { get; set; }
 public string description { get; set; }
 public DisplayDetail display { get; set; }
 public HardwareDetail hardware { get; set; }
 public string id { get; set; }
 public string[] images { get; set; }
 public string name { get; set; }
 public SizeAndWeightDetail sizeAndWeight { get; set; }
 public StorageDetail storage { get; set; }

 public class AndroidDetail
 {
  public string os { get; set; }
  public string ui { get; set; }
 }

 public class BatteryDetail
 {
  public string type { get; set; }
  public string talkTime { get; set; }
  public string standbyTime { get; set; }
 }

 public class CameraDetail
 {
  public string[] features { get; set; }
  public string primary { get; set; }
 }

 public class ConnectivityDetail
 {
  public string bluetooth { get; set; }
  public string cell { get; set; }
  public bool gps { get; set; }
  public bool infrared { get; set; }
  public string wifi { get; set; }
 }

 public class DisplayDetail
 {
  public string screenResolution { get; set; }
  public string screenSize { get; set; }
  public bool touchScreen { get; set; }
 }

 public class HardwareDetail
 {
  public bool accelerometer { get; set; }
  public string audioJack { get; set; }
  public string cpu { get; set; }
  public bool fmRadio { get; set; }
  public bool physicalKeyboard { get; set; }
  public string usb { get; set; }
 }

 public class SizeAndWeightDetail
 {
  public string[] dimensions { get; set; }
  public string weight { get; set; }
 }

 public class StorageDetail
 {
  public string flash { get; set; }
  public string ram { get; set; }
 }
}
Once again that I'm going with the convention of Camel case in my C# class to reduce the amount of work I have to do with the copied code for the Angular templates.  Also, I'm struck again by how clever newtonsoft json library is when it comes to transforming a fairly intricate object structure to and from JSON.  I guess that's  why MS use it under the hood.

Finally you'll need to update the CSS in Content/app.css to match what's in app/css/app.css in the Angular tutorial.

Hopefully you now have a working version of step8 of the AngularJS tutorial.

Monday, 20 May 2013

AngularJS Tutorial and .Net Web API (part 3)

This is the third post in a series about using the .Net Web API to run the AngularJS tutorial app on. So far all that's happened is we've created a project that runs step5 of the tutorial.

In this post I'll move onto steps 6 & 7 http://docs.angularjs.org/tutorial/step_06 & http://docs.angularjs.org/tutorial/step_07
Step 6 of the AngularJS tutorial is about updating the template to use images and generate links to individual phones that for the moment don't go anywhere.

Check out step 6 with git checkout -f step6

If you look at app/index.html in the original tutorial directory (or just follow the AngularJS tutorial) you'll see that the content of the 'li' element has changed. Simply copy the new code over the top of the old:
  • {{phone.name}} {{phone.snippet}}
  • In order for this to work, you'll need to update your css, add the images to the project and amend the JSON phones document so that the path to the images is correct.
    So first grab the css from the app/css/app.css and paste it into Content/app.css. Then, create a new 'img' folder in the 'Content' folder of your .Net project. Within that create a 'phones' folder then copy the images from the Angular tutorial directory ('app\img\phones') into this new folder.

    If you try to run the application, no images will be rendered on the page because the paths don't match, so you'll need to update your JSON data file accordingly. Simply substitute img/ for Content/img/ in App_Data/phones.json. If you run the application now, you should see the same page as you do on the AngularJS tutorial live demo http://angular.github.io/angular-phonecat/step-6/app/
    If you click on any of the links, you'll soon realise that they don't work.

    Step7
    Onto step 7, which has much more of the meat of what AngularJS is all about, using Angular's routing capabilities in conjunction with different views and controllers. Again, if you're used to .Net MVC then everything here should be pretty easy to get your head around, but it's definitely the point for me at which I started thinking, "why am I using 2 sets of routing?" I'm not sure I have an answer yet, but I could imagine a hybrid app which has both .Net MVC and Angular MVC in it.

    use git checkout -f step7.

    Again, checkout the correct step of the AngularJS tutorial, then copy app/js/app.js into the 'Scripts' folder at the root of the .Net MVC project. This defines the routes and controllers for Angular's MVC structure.

    Next, update Views/Home/Index.cshtml so that it now has at the top and has a reference to after the reference to angular.js in the head (remember that Views/Home/Index.cshtml is pretty much exactly the same as app/index.html in the AngularJS tutorial). Finally, delete most of the content in the body of Index.cshtml and replace it with

    Now, create a new folder called 'AngularPartials' at the root of your .Net MVC project and add two HTML files to it, 'phone-list.html' and 'phone-detail.html', these should be exactly the same as the Angular app/partials/phone-detail.html and app/partials/phone-list.html files. Now you just need to update the Scripts/app.js file to reflect the paths to those partials, so it should look like this:
    angular.module('phonecat', []).
      config(['$routeProvider', function($routeProvider) {
      $routeProvider.
          when('/phones', {templateUrl: 'AngularPartials/phone-list.html',   controller: PhoneListCtrl}).
          when('/phones/:phoneId', { templateUrl: 'AngularPartials/phone-detail.html', controller: PhoneDetailCtrl }).
          otherwise({redirectTo: '/phones'});
    }]);
    


    Note that the only changes are to the 'templateUrl:' values. Amend 'Scripts/controllers.js' to include the definition for PhoneDetailCtrl
    function PhoneDetailCtrl($scope, $routeParams) {
    $scope.phoneId = $routeParams.phoneId;
    }

    The application should now be working, with links to the 'TBD' view for the phone details.