How I improved my fubuMVC redirection policy with a convention

In the previous post of this fubuMVC series, I showed how I had implemented permanent redirection for a url using fubuMVC. I had enriched the action call for the old route with a behaviour that issues a permanent redirection and this behaviour occurred after the action call.

In this post I’m going to illustrate how I gained more control over where the behaviour was added – to do this I wrote a convention that implements IConfigurationAction and hooked this into the fubuMVC registry.

    public class PermanentRedirectionConvention : IConfigurationAction
    {
        public void Configure(BehaviorGraph graph)
        {
            graph.Behaviors
                .Where(c => c.FirstCall().HandlerType == typeof (HomeController)
                            && c.FirstCall().Method.Name.ToLower() == "news")
                .Each(c => c.Prepend(new Wrapper(typeof (PermanentNewsRedirectionBehaviour))));

            graph.Behaviors
                .Where(c => c.FirstCall().HandlerType == typeof (HomeController)
                          && c.FirstCall().Method.Name.ToLower() == "about")
                .Each(c => c.Prepend(new Wrapper(typeof(PermanentAboutRedirectionBehaviour))));
        }
    }

When you implement a convention you are given the behaviour graph so that you can amend it as you see fit.
Here I am filtering the IEnumerable<BehaviorChain> on the graph, called “Behaviors”, and looking for the one that represents the HomeController and “news” method.
Once I have the behaviour chain that corresponds to this action I am going to ensure that this behaviour sits at the top using the Prepend method.
I’ve also done the same for another action that I am permanently redirecting.

In order to plug this into my fubu registry I am going to replace the policies enrichment with my convention instead:

    public class XercesFubuRegistry : FubuRegistry
    {
        public XercesFubuRegistry()
        {
            IncludeDiagnostics(true);

            Applies.ToThisAssembly();

            Actions.IncludeClassesSuffixedWithController();

            Routes.HomeIs<HomeController>(c => c.FrontPage())
                    .IgnoreControllerNamespaceEntirely()
                    .UrlPolicy<EnsureControllersCanHaveARootUrlPolicy>();

            ApplyConvention<PermanentRedirectionConvention>(); <-- new line

            this.UseSpark();

            Views.TryToAttachWithDefaultConventions();
        }
    }

This leaves me with a different behaviour graph from last time where my own behaviour is above the action call:

redirectchain2

This now enables me to amend my HomeController to better reflect the fact that the news and action methods should never be called:

    public class HomeController
    {
        public HomeViewModel FrontPage()
        {
            return new HomeViewModel();
        }

        public AutomaticRedirection News()
        {
            throw new Exception("Automatic redirection should have occurred 
                                                before reaching this method");
        }

        public AutomaticRedirection About()
        {
            throw new Exception("Automatic redirection should have occurred
                                                before reaching this method");
        }
    }

    public class HomeViewModel { }

    public class AutomaticRedirection { }

There’s my redirection policy implemented – there are a couple of things I would like to review though…

The first is that its a shame that I have to have “placeholder” actions in order to point to them in my conventions but by nature of the behaviour graph being built up front we no longer have the dynamic resolution of routes and actions (and that is a good thing for more deterministic and testable behaviour).
I did look at how we might add permanent redirection into fubuMVC itself, but it meant adding behaviour chains that have no action calls and outputs and was not a quick feat, so have not pursued that yet.

The second point is the “magic strings” I’m using in the convention itself for the method names – I don’t like magic strings.
In my next post I’ll show how I removed those and tightened the implementation.



0 comments: