andy-williams.net

Routing with Node.js Part Three – Methods

Part One
Part Two

A simple change we can make to our routing system is to allow users to filter by the request method used (GET, POST, PUT etc). There are four simple steps we can take to achieve this, first of all we must alter our _addRoute function to take a method as a parameter:

var _addRoute = function(url, method, action) {
	var item = {
		Url: url,
		Method: method,
		Action: action
	};
	_routes.push(item);
};

The function now simply adds the method to the route as well as the url and action.

The next step is optional, but makes for fewer mistakes, we can add two helper functions, _addGetRoute, and _addPostRoute to our module:

var _addGetRoute = function(url, action) {
	_addRoute(url, 'GET', action);
};

var _addPostRoute = function(url, action) {
	_addRoute(url, 'POST', action);
};

These methods simply make a call to _addRoute with the required method. We also need to expose these in the return method at the bottom of the module:

return {
	AddRoute: _addRoute,
	AddGetRoute: _addGetRoute,
	AddPostRoute: _addPostRoute,
	Process: _process
};

Finally, we need to test the method used in any request coming in to see if it matches the method we have stored for any given route. Again, this is very simple, all we need to do, is test for a match in the first line of the _isMatch function:

var _isMatch = function(urlArray, method, route) {
	if(route.Method !== method) { return false; }

Now we’re done! We can test this by adding the following routes to our example application:

function simple(req, res) {
	res.writeHead(200, {"content-type" : "text/plain"});
    res.end('Simple\n');
}

function simplePost(req, res) {
	res.writeHead(200, {"content-type" : "text/plain"});
    res.end('Simple Post\n');
}

m6.AddGetRoute('/simple', simple);
m6.AddPostRoute('/simplepost', simplePost);

If we make a GET request to '/simple' using the following curl command:

curl http://localhost:3333/simple

We get the response 'simple', as expected, but if we make a GET request to '/simplepost' using the following curl command:

curl http://localhost:3333/simplepost

we get the response 'Not Found', which we expect because we have specified that the route '/simplepost' should only match the action function 'simplePost' if the method of the request is POST.

We can test this works by making a POST request with the following command:

curl --data "val1=1" http://localhost:3333/simplepost

Which should result in the output 'Simple Post'

The code for this module can be found here and the module can be installed by running the command npm install m6


Routing with Node JS Part Two

Part One
Part Three

The code for this project can now be found here. the npm project can be found here, install into your node.js project with the following command:

npm install m6

In my previous post I showed how we might begin to build a routing module using Node.js. I have since published this project on npm with the title M6.

In this second post I’ll show how we can add to our module to allow us to pass parameters in the url so that the urls '/sites/get/1' and '/sites/get/2' resolve to the same action, but pass through a parameter with the value 1 or 2.

To add a simple route to our module we use the following code:

m6.AddRoute('/simple', simple);

To declare a route with a parameter we will prefix the url item with an @ character:

m6.AddRoute('/simpleparam/@value', simpleParameter);

This route will send the requests, '/simpleparam', '/simpleparam/69', and '/simpleparam/wolves' to the action simpleParameter.

We want the module to add a property 'params' to the 'req' variable that is passed through to the action. This property should contain all the parameters passed through in the url.

Here is the simpleParameter action:

function simpleParameter(req, res) {
	res.writeHead(200, {"content-type": "text/plain"});
	if(!req.params.value) {
		res.end('No parameter passed');
	} else {
		var response = 'Parameter value: ' + req.params.value;
		res.end(response);
	}
}

This action simply checks if a parameter has been passed through and returns a message back to the client informing them of the value of that parameter, or a message telling them that a parameter was not passed.

Lets now look at what changes we need to make to the M6 routing module to allow this behaviour.

Adding a route is the same as before, we just need to take the url and the action:

var _routes = [];
var _addRoute = function(url, action) {
	var route = {
		Url: url,
		Action: action
	};

	_routes.push(route);
};

The main change comes when we process a request, previously it was simply a case of testing the equality of the request coming in against the routes stored in an array, and executing an action if a match was found. Here is the updated version:

var _process = function(req, res) {
	var route = _getRoute(req);

	if(route) {
		var parameters = _getParameters(req, route);
		req.params = parameters;
		route.Action(req, res);
		return true;
	}

	return false;
};

First of all the function attempts to find a matching route, if one is found it then grabs and parameters, assigns them to the request object, and finally executes the route’s action.

Let’s look now at how we find a matching route, here’s the updated code:

var _getRoute = function(req) {
	var urlArray = req.url.split('/');
	for(var i = 0, length = _routes.length; i < length; i++) {
		if(_isMatch(urlArray, req.method, _routes[i])) {
			return _routes[i];
		}
	}
};

var _isMatch = function(urlArray, method, route) {
	var routeUrlArray = route.Url.split('/');

	var match = true;
	for(var i = 0, length = routeUrlArray.length; i < length; i++) {
		var item = urlArray[i];
			
		if(routeUrlArray[i] !== item && routeUrlArray[i][0] !== '@') { 
			match = false;
		}
	}
	return match;
};

First of all, the _getRoute function has changed. We now split the url into an array so '/simple/route' becomes ['simple', 'route']. The reason we do this is so we can pay attention to any parts of the route which begin with an '@' character as we know this denotes a url parameter. The _getRoute function then loops through all the routes stored and attempts to find a match by calling the _isMatch function.

The _isMatch function works by looking at each part of the url request and comparing it with the equivalent part of a given route url and tries to find any inequality. If the piece does not match but the route part of the url begins with an '@' character then a match is still recored as this denotes a parameter value being passed in.

Once a route has been found, the M6 module needs to extract any parameters passed in via the url request and add them to the request object. This means that in our earlier example, a request of '/simpleparam/69' will result in the module adding the following Javascript object to the params property of the request object:

{
    value: 69
};

The name of the object's property, value, comes from the route. Here is the _getParameters function:

var _getParameters = function(req, route) {
	var urlArray = req.url.split('/');
	var parameters = {};
	var routeUrlArray = route.Url.split('/');
	for(var i = 0, length = routeUrlArray.length; i < length; i++) {
		if(routeUrlArray[i][0] === '@') {
			var key = routeUrlArray[i].substring(1);
			var value = urlArray[i];
			parameters[key] = value;
		}
	}

	return parameters;
};

This function simply loops through the elements of the route url looking for elements beginning with an '@' character. If a parameter element is found, the function extracts the value of the parameter from the request and adds that value to the parameters object.

With this in place we can now start the server with the command 'node example' and make the following request from the terminal:

curl http://localhost:3333/simpleparam/69

This should result in the following output:

Parameter value: 69

Once again, the full code can be found here, and can be installed with the following command:

npm install m6


Routing with Node JS

Part Two
Part Three

The code for this project can now be found here. the npm project can be found here, install into your node.js project with the following:

npm install m6

I’ve recently been doing a lot of work in node js which I’m enjoying immensley. When developing with node I tend to have just Sublime Text 2 and a terminal window open, after years of working in Visual Studio with C# this feels very lightweight and liberating.

Recently I started writing a rest server in node, this is currently still in development, and I am still new with node, but I thought I’d share here how I went about it.

OK, to start off with lets build the classic simple node js server:


var http = require('http');

var server = http.createServer( function (req, res) {
    res.writeHead(200, {"content-type" : "text/plain"});
    res.end('Hello from Node JS');
  }
).listen(3333);

Type this code into a file named server.js then navigate to its directory in a terminal window and run the command “node server”, finally, open up a web browser and navigate to “http://localhost:3333″ to see the result. If you’re familiar with Node JS you’ll recognise this example, if not, check out the node js website.

To build our rest server we will need the ability to specify a url and the the resulting action which should be undertaken for that request. At the moment, if you navigate to any url, http://localhost:3333/test for example, you get the same result, “Hello from Node JS”. We need to build a routing module.

To build our routing module we want to create a new sub directory, ‘routing’, into which we place a new file ‘routing.js’. In this file, to begin with, we want to create an object and export it from the module for use:

var Routing = function() {}();

module.exports = Routing;

First of all we create a variable, routing. We do this using the JavaScript revealer pattern. Although nothing is defined in the function yet, we’re defining a function which we immediately call. Whatever is returned we store in the variable ‘Routing’. On the second line we decalre that the module should export this variable.

We can now require and use this in server.js

var routing = require('./routing/routing');

We now need to start adding functionality to our routing module. The first thing we’ll want to do is specify routes and the resulting actions for these routes.

var Routing = function() {
	var _routes = [];
	var _addRoute = function(url, action) {
		var route = {
			Url: url,
			Action: action
		};

		_routes.push(route);
	};

	return {
		AddRoute: _addRoute
	};
}();

module.exports = Routing;

This code snippet shows more clearly how the revealer pattern works. Here we declare two variables within our outer function; an empty array named _routes, and a function named _addRoute. At the end of the function we return a JavaScript object which allows the consumer to access the _addRoute function.

The AddRoute function is pretty simple, it takes a url and an action and builds a simple JavaScript object from these which it then adds to a private array.

We can now add a route from the server.js file.

function simple(req, res) {
    res.writeHead(200, {"content-type" : "text/plain"});
    res.end('Simple');
}

routing.AddRoute('/simple', simple);

We now need to do something with the route when a request is made to our webserver, lets start to write a function to process a web request. We want to let the caller know if we were able to process the request, in routing.js, lets start by dealing with the situation where we can’t.

var _process = function(req, res) {
	return false;
};

return {
	AddRoute: _addRoute,
	Process: _process
};

In server.js we can now attempt to proccess the incoming requests by sending them to our routing object and send a default response if that fails.

var server = http.createServer( function (req, res) {

	if(routing.Process(req, res) === false) {
    	res.writeHead(404, {"content-type" : "text/plain"});
    	res.end('Not found');
	}
  }
).listen(3333);

Now that is in place we should try to find if we are actually able to handle incoming requests in the routing module. Let’s start by printing out the url we get from the request.

var _process = function(req, res) {
	_getRoute(req);

	return false;
};

var _getRoute = function(req) {
	console.log(req.url);
};

If the server is currently running, go to the terminal window and press ctrl+c to quit, then restart the server by running the same command as earlier “node server”. Go to your web browser and navigate to “http://localhost:3333/simple”. When that is loaded take a look at the terminal window, you should see the following:

/simple
/favicon.ico

The second line is just the browser trying to find a favicon, we can ignore that, the first line is what we’re interested in. We need to test this value, ‘/simple’ against all the values in our “_routes” array. The simplest way to do this is to simply test if they’re equal.

var _process = function(req, res) {
	var route = _getRoute(req);

	if(route) {
		route.Action(req, res);
		return true;
	}

	return false;
};

var _getRoute = function(req) {
	for(var i = 0, length = _routes.length; i < length; i++) {
		if(req.url === _routes[i].Url) {
			return _routes[i];
		}
	}
};

Now if you restart the server and navigate to http://localhost:3333/simple the server should respond 'simple'. If you navigate to the route or any other address including something like http://localhost:3333/simple/test you should get the response 'Not found'.

Our routing module seems to work. In the next post I will discuss how we would add the functionality to handle parameters passed in the url so that the urls '/sites/get/1' and 'sites/get/2' resolve to the same action but also pass a parameter through to that action.

Comments welcome.


Massive micro ORM id after insert

I was working with the micro orm Massive earlier today and needed to get the id of a row I’d just inserted.

Turns out this was really easy.

First of all I created a private class inside the class I was working on which extends DynamicModel.

    public class SomeClass : IClientDispatcherService
    {
        private class MassiveAddresses : DynamicModel
        {
            public MassiveAddresses() : base("ConnectionName", tableName: "Addresses", primaryKeyField: "Id") { }

            public int NewId { get; set; }

            public override void Inserted(dynamic item)
            {
                NewId = (int)item.ID;
            }
        }

As you can see, this private class simply overrides the Inserted method, grabs the id, and places it in a public property.

We can now access this after an insert:

        private MassiveAddresses Addresses
        {
            get { return new MassiveAddresses(); }
        }

        public void SomeMethod()
        {
	    var addresses = Addresses;

            addresses.Insert(new
            {
                Line1 = "Line1",
                Line2 = "Line2",
                Line3 = "Line3",
                Town = "Town",
                County = "County",
                Country = "Country",
                Postcode = "Postcode"
            });

            var addressId = addresses.NewId;
}

Sorted.


ASP.NET MVC Localisation

Recently I needed to implement a multi-lingual web application using ASP.NET MVC. Turns out I was able to do it in three steps, here’s how I went about it.

Step One – Resource files

The first step was to create the resource files for the two languages I needed, for this example I’ll create a general resource in both english and german with the property ‘SomeText’.

We’ll display this text on our home page.

Step Two – Setting the users culture

The next step is to allow the user to set their prefered culture. We do this by creating a CultureController class with one action method, Set.


    public class CultureController : Controller
    {
        public ActionResult Set(string culture)
        {
            HttpCookie cookie = Request.Cookies["_culture"];
            if (cookie != null)
                cookie.Value = culture;
            else
            {

                cookie = new HttpCookie("_culture")
                             {
                                 HttpOnly = false,
                                 Value = culture,
                                 Expires = DateTime.Now.AddYears(1)
                             };
            }
            Response.Cookies.Add(cookie);

            return RedirectToAction("Index", "Home");
        }
    }

The Set method checks the current request to see if it has a cookie named “_culture”, if it doesn’t it creates it, the method sets the value of the cookie to the value passed into the method and then adds the cookie to the response to be stored by the user’s browser.

On our home page we can now add links to allow the user to choose either the english or german version of the site.

@Html.ActionLink("En", "Set", "Culture", new { culture = "en" }, null)
|
@Html.ActionLink("De", "Set", "Culture", new { culture = "de" }, null)

@Localisation.Resources.General.SomeText

Step Three – Set the culture per web request

For the final step we need to set the culture of the current thread to the culture stored in the user’s cookie. We can do this by writing an action filter.

    public class SetCulture : IActionFilter
    {
        public virtual void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpCookie cookie = filterContext.RequestContext.HttpContext.Request.Cookies["_culture"];

            var cultureString = cookie == null ? "en" : cookie.Value;

            var culture = CultureInfo.GetCultureInfo(cultureString);

            Thread.CurrentThread.CurrentUICulture = culture;
        }

        public virtual void OnActionExecuted(ActionExecutedContext filterContext) { }
        public virtual void OnResultExecuting(ResultExecutingContext filterContext) { }
        public virtual void OnResultExecuted(ResultExecutedContext filterContext) { }
    }

The action filter simply gets the value of the cookie if it exists (if not it defaults to english), gets the CultureInfo object it represents, then sets the current thread’s culture to this.

The final step is to register this action filter as a global filter, we can do this by adding it in the RegisterGlobalFilters method in Global.asax.cs


        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new SetCulture());
        }

and we’re done!


Web application keyboard navigation

I’m trying to improve my javascript/JQuery skills.

As a result, what follows might be child’s play to most, but it is mainly for my development, if there is anywhere you can see where any of this can be improved please let me know.

A recent post by Scott Hanselman got me thinking about about the way the users interact with the systems I build. I know that personally, when using Visual Studio I try to touch the mouse as little as possible, knowing that any task I can undertake with the keyboard is going to be faster and make me more productive, than if I have to use the mouse.

I should allow users of my systems to undertake tasks using just the keyboard.

The first task I set to allow keyboard access to was simple navigation through my web app, and in particular, drilling down into a table. In his post, Scott Hanselman talks about the emerging standard of using the 'j' and 'k' keys to move up and down items, examples of these being Gmail, Google Reader and Twitter, so I set out to see if I could put together some javascript to move up and down an html table and select a row to navigate to.

Imagine we have the following table contained within an ASP.NET MVC view.


<table>
    <thead>
        <tr>
            <th>Id</th>
            <th>Description</th>
            <th>Link</th>
        </tr>
    </thead>

    <tbody>
        <tr>
            <td>1</td>
            <td>Description of a widget</td>
            <td>@Html.ActionLink("View", "View", new { id = 1 })</td>
        </tr>

        <tr>
            <td>2</td>
            <td>Description of a widget</td>
            <td>@Html.ActionLink("View", "View", new { id = 2 })</td>
        </tr>

        <tr>
            <td>3</td>
            <td>Description of a widget</td>
            <td>@Html.ActionLink("View", "View", new { id = 3 })</td>
        </tr>
    </tbody>
</table>

We know that when a row is selected by the user, we want them to be navigated to the same MVC action as is specified in the ActionLink in each row. Lets add an extra piece of data to each row which simply contains the url we wish to navigate to if the given row is selected. We will also set the class attribute of the td element to selectUrl so we can easily locate it later.

<tr>
  <td>4</td>
  <td>Description of a widget</td>
  <td>@Html.ActionLink("View", "View", new { id = 4 })</td>
  <td class="selectUrl">@Url.Action("View", new { id = 4 })</td>
</tr>

This leaves us with the following

Now we know those urls are there we can just hide them

<td class="selectUrl" style="visibility: hidden">@Url.Action("View", new { id = 4 })</td>

Right, now we have our table setup we need to write the script which allows us to navigate the table.
To do this, lets use the jquery.hotkeys library which was referenced in Scott Hanselman’s post. We first of all need to identify the table as one which allows this kind of selection, to do this, let’s set the class attribute on the tbody tag to selectable.

<tbody class="selectable">

Now to write the script. We know that we will want to listen for three keys; j, k, and return, so lets declare this in our script

$(document).bind('keyup', 'k', moveDown);
$(document).bind('keyup', 'j', moveUp);
$(document).bind('keyup', 'return', select);

Here we’re just declaring that when the j, k, or return keys are pressed, the moveDown, moveUp, and select functions should be called respectively (don’t worry, we haven’t written these yet :-) ).

Next lets declare the variables we will be using, we need one to keep track of the currently selected index, and two to store the minimum and maximum possible indexes. We also set the max index to be the number of tr tags in our table’s tbody tag.

var selectIndex = 0;
var minIndex = 0;
var maxIndex = 1;

$(function () {
    maxIndex = $('.selectable tr').length;
});

Right, in order to show that a row is selected, we’re going to set its background colour to Highlight, when we do this, we’ll first need to reset each row to the default background colour, let’s write a function to achieve this.

function unselectAll() {
    $(".selectable tr").css("background-color", "#efeeef");
}

Now we can start to do some work. Here’s the function to move the selected index down

function moveDown() {
    unselectAll();

    selectIndex++;
    if (selectIndex > maxIndex) {
        selectIndex = maxIndex;
    }

    var selector = ".selectable tr:nth-child(" + selectIndex + ")";

    $(selector).css("background-color", "Highlight");
}

All we are doing here is clearing the highlights by calling our unselectAll() function, incrementing the selectIndex variable, selecting the row we need to highlight, and then applying the highlight. Simple.

To move the index back up, we just do the opposite

function moveUp() {
    unselectAll();

    selectIndex--;
    if (selectIndex < minIndex) {
        selectIndex = minIndex;
    }

    var selector = ".selectable tr:nth-child(" + selectIndex + ")";

    $(selector).css("background-color", "Highlight");
}

All that's left to do now is the actual selection of a row. To achieve this, all we need to do is grab the data marked with the selectUrl class attribute we declared earlier and navigate to the url contained within.

function select() {

    if(selectIndex > 0) {

        var selector = ".selectable tr:nth-child(" + selectIndex + ")";

        var url = $(selector).find(".selectUrl").html();

        window.location.href = url;
    }
}

And that's it we're done, simple! :)

kick it on DotNetKicks.com


Castle Windsor Dynamic Parameters

While working on a project for a client recently I began to implement some search functionality for the project’s website. I started off by defining the interface.

public interface ISearchService
{
  List<Widget> Search(string term);
}

I then wrote a few implementations of this interface which each searched for something slightly different. I then decided I wanted an implementation of ISearchService which would take a list of ISearchService objects and when searched, would return the results of calling Search(string term) on each search stratergy passed in.

The code to do this was simple.

public class CompositeSearchService : ISearchService
{
  private readonly List<ISearchService> _searchStratergies;

  public CompositeSearchService(IEnumerable<ISearchService> searchStratergies)
  {
    _searchStratergies = searchStratergies.ToList();
  }

  public List<Widget> Search(string term)
  {
    return _searchStratergies
      .SelectMany(x => x.Search(term))
      .Distinct()
      .ToList();
  }
}

I now needed to tell Castle Windsor that I wished to use CompositeSearchService as the implementation of the ISearchService interface, and to tell Castle Windsor to inject an IEnumerable of ISearchService objects into the constructor of CompositeSearchService.

To do this I used Castle Windsor’s DynamicParameters method.

container.Register(
  Component.For<ISearchService>()
  .ImplementedBy<CompositeSearchService>()
  .DynamicParameters((kernal, parameters) => 
  {
    var session = kernal.Resolve<ISession>();
    parameters["searchStratergies"] = new List<ISearchService> 
    { 
      new SearchServiceA(session), 
      new SearchServiceB(session),
      new SearchServiceC(session)
    };
  }).LifeStyle.PerWebRequest)

The DynamicParameters method takes a parameter which allows us to specify exactly what parameters we need to be injected into the implementation’s constructor. Neat!


ASP.NET Web API with RavenDB and Castle.Windsor

I had an idea for a project and decided I wanted to give RavenDB and the new ASP.NET Web API a try.
The following is a description on how I hooked up RavenDB to Castle Windsor to inject new IDocumentSession objects into ApiController objects per web request. ASP.NET Web API and RavenDB are both new to me, so if you see anywhere this can be improved on, or if I’m just doing it wrong, please let me know.

First of all we need to initalise RavenDB, this is really pretty simple, we just need to create a DocumentStore object and call Initialize on it once for the entire application, this DocumentStore object must be made available so that we can use it to open sessions to the database.

var documentStore = new DocumentStore { Url = "http://localhost:8080/" };
documentStore.Initialize();

var session = documentStore.OpenSession();

We now need to register the DocumentStore object we create with Castle Windsor so we can access it once per web request to open a session. To do this we’ll build a class which derives from IWindsorInstaller. This class will be responsible for all the dependency injection relating to RavenDB. I personally like using installer classes as it separates our code relating to DI away from other initialisation code.

To start with we need to implement the interface by writing an Install method. When this method is called, Castle Windsor passes in an IWindsorContainer object which we will use to register our RavenDB related dependencies. To start with, we’ll register the IDocumentStore object.

public void Install(IWindsorContainer container, IConfigurationStore store)
{
  container.Register(
    Component.For<IDocumentStore>()
      .Instance(CreateDocumentStore())
      .LifeStyle.Singleton);
}

private static IDocumentStore CreateDocumentStore()
{
  var documentStore = new DocumentStore { Url = "http://localhost:8080/" };
  documentStore.Initialize();

  return documentStore;
}

Here we create a DocumentStore object and register it with Windsor, we register the object with a singleton lifestyle type as we only need one of these objects for the application.

Next we need to register the IDocumentSession type.

public void Install(IWindsorContainer container, IConfigurationStore store)
{
  container.Register(
    Component.For<IDocumentStore>()
      .Instance(CreateDocumentStore())
      .LifeStyle.Singleton,
    Component.For<IDocumentSession>()
      .UsingFactoryMethod(GetSession)
      .LifeStyle.PerWebRequest);
}

private static IDocumentSession GetSession(IKernel kernel)
{
  var documentStore = kernel.Resolve<IDocumentStore>();
  return documentStore.OpenSession();
}

Here we define a factory method which uses an IKernal object to resolve the IDocumentStore singleton which we registered previously and use it to open a new session. In the Install method we specify that a new IDocumentSession should be created for each web request.

Okay, so now whenever we need a database session, we can just ask Castle Windsor to give us one any we’re ready to go.

The next thing we need to think about is how we’re going to do this. Our aim is to have access to new database sessions per web request in our ApiControllers. I don’t want the controllers to be responsible for resolving their dependencies, so we need to inject them.

To do this, we’re going to get Castle Windsor to build our ApiController objects for us.

First of all we need to tell Castle Windsor about our controllers, so that when one is requested, Windsor is able to resolve all dependencies and provide the required controller.

public class ControllersInstaller : IWindsorInstaller
{
  public void Install(IWindsorContainer container, IConfigurationStore store)
  {
    container.Register(
      AllTypes
        .FromThisAssembly()
        .BasedOn<IHttpController>()
        .Configure(c => c.LifeStyle.Transient
        .Named(c.Implementation.FullName))
      );
  }
}

Like before we’re using an installer class to register our types. The ApiController classes we write to build our web api all implement the IHttpController interface, and this is the type that’s required when a request comes in, so this is the type we need to register with Windsor. In this method, we’re asking Windsor to look for and register all types in the current assembly, that implement IHttpController.

Now that Castle Windsor knows about our data access classes and controllers, we need to replace the Default Http Controller Factory with a custom controller factory which will use Castle Windsor to build our IHttpController objects.

To do this, we need to write a class that implements the IHttpControllerFactory interface.

The IHttpControllerFactory interface is pretty simple, it just requires us to implement methods to create and release controllers. The CreateController method passes in a context and name of the controller which is required, we must take this name and use it to resolve the required controller type from Windsor. Before we do this, we need an IKernal object from Windsor, this is a dependency of the class we’re building, and we required it to be injected into our constructor.

public class WindsorHttpControllerFactory : IHttpControllerFactory
{
  private readonly IKernel _kernel;

  public WindsorHttpControllerFactory(IKernel kernel)
  {
    _kernel = kernel;
  }

Now we have our IKernal object, we can use it to get at the controllers we registered earlier.

Right, lets build out controllers, to do this, we must complete two steps, first of all we must get the required IHttpController object.

public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
{
  var controller = _kernel.Resolve<IHttpController>(String.Format("Web.Api.Controllers.{0}Controller", controllerName));

The controllerName string which is passed in is not the fully qualified name, so we build up the full name and resolve the controller from Windsor, and we now have our controller to return!

The next step is not obvious, we need to create a controller descriptor, which is part of the controllerContext which is passed into the method. This is discussed further in this thread. Fortunately, we don’t have to do too much work, here is the full method.

public IHttpController CreateController(HttpControllerContext controllerContext, string controllerName)
{
  var controller = _kernel.Resolve<IHttpController>(String.Format("Web.Api.Controllers.{0}Controller", controllerName));

  controllerContext.Controller = controller;
  controllerContext.ControllerDescriptor = new HttpControllerDescriptor(GlobalConfiguration.Configuration, controllerName, controller.GetType());
  return controllerContext.Controller;
}

Right, now we have our new http controller factory we need to register it with Windsor so that our dependency on IKernal can be resolved and injected when we come to use it. We’ll do this in the ControllersIntaller class we wrote earlier, we just need to simply register it as a singleton.

public void Install(IWindsorContainer container, IConfigurationStore store)
{
  Component.For<IHttpControllerFactory>()
    .ImplementedBy<WindsorHttpControllerFactory>()
      .LifeStyle.Singleton

Now we’ve setup Windsor as we require, all we need to do is create our IWindsorContainer object and tell ASP.NET to use our WindsorHttpControllerFactory. We do this in the Global.asax.cs file.

protected void Application_Start()
{

  //Code removed

  InitialiseWindsor();

  var configuration = GlobalConfiguration.Configuration;
  
  configuration.ServiceResolver.SetService(
    typeof(IHttpControllerFactory),
    _container.Resolve<IHttpControllerFactory>());
}

protected void InitialiseWindsor()
{
  _container = new WindsorContainer()
    .Install(FromAssembly.This());
}

With all this in place, when writing a new ApiController we can simply request a IDocumentSession object in our constuctor as use it as we wish.

public class SuperController : ApiController
{
  private readonly IDocumentSession _documentSession;

  public SuperController(IDocumentSession documentSession)
  {
    _documentSession = documentSession;
  }

Hope that helps!

kick it on DotNetKicks.com