Dependency Injection in ASP.NET MVC 2 – Part 1: Controllers

28 February 2010 - 11:30 PM / by Dominic Pettifer. 6 Comments

Technical Article - In the first part of three, I show you how to perform Dependency Injection in ASP.NET MVC 2 using the Castle Windsor IOC (Inversion of Control) Container. In part 1 we look at injecting dependencies into your Controllers.

Dependency Injection

Using the principle of Dependency Injection, we can inject a concrete implementation into our ASP.NET MVC Controllers, but where the Controller only references an Interface not the concrete class. The benefits of this approach in a nut shell is that it allows us to decouple our codebase to make it more maintainable, and unit testable. Note the following contrived example:

public class ProductsController : Controller
{
   protected IProductsRepository ProductsRepository = null;

   public ProductsController(IProductsRepository productsRepository)
   {
      ProductsRepository = productsRepository;
   }

   public ActionResult ListProducts()
   {
      IList<Products> products = ProductsRepository.ListAllProducts();
      return View(products);
   }
}

Note we're using an IProductsRepository interface, but the concrete implementation might be an NHibernateProductsRepository or a LinqToSqlProductsRepository. We can use the IOC container to very easily swap out the implementation if we ever needed to change data access technologies, without changing any of the code that relies on the data access layer.

In the real world, obviously it's rare to change data access technologies during product development, but if you follow the DIP (Dependency Injection Principle) throughout your codebase, you'll inevitably find somewhere where you need to swap out implementations. The ability to swap implementations isn't the main reason to use DIP though, other reasons include allowing a more decoupled and maintainable codebase, and to facilitate unit testing. You could easily unit test the above code for instance, by injecting in a mocked IProductsRepository implementation, instead of one that needs to hit a database.

In the above example we're injecting the dependencies into the constructor (Constructor Injection), and indeed this is the recommended approach in most cases, as you’re saying that this class in dependant on this interface. But it's also possible to use Property Injection, just ensure the property is public.

If you're still unsure of the benefits of Dependency Injection, read up on the SOLID principles.

IOC with Castle Windsor

If you were to run the above code, it would throw an exception, because the way ASP.NET MVC instantiates Controllers, it expects there to be a default no-arg constructor.

Thankfully, Microsoft made the ASP.NET MVC framework extensible enough that we can change the way it instantiates Controllers. What we need to do is to get our IOC container, Castle Windsor, to instantiate the Controller. Castle Windsor will then automatically resolve any dependencies the Controller (or whatever it’s instantiating) has, such as the IProductsRepository type. Even better the IOC container can resolve any dependencies the dependencies themselves have, all the way down the dependency tree.

First create an IocHelper class:

public static class IocHelper
{
    private static IWindsorContainer _container = null;
    private static object _syncObject = new object();

    public static IWindsorContainer Container()
    {
        if (_container == null)
        {
            lock (_syncObject)
            {
                if (_container == null)
                {
                    _container = new WindsorContainer(new XmlInterpreter("ioc.xml"));
                }
            }
        }

        return _container;
    }

    public static void DisposeContainer()
    {
        if (_container != null)
        {
            lock (_syncObject)
            {
                if (_container != null)
                {
                    _container.Dispose();
                    _container = null;
                }
            }
        }
    }
}

This class provides a static accessor to our IOC container. We only ever instantiate a single container for the entire application lifetime.

Now ASP.NET MVC instantiates controllers using its own DefaultControllerFactory, we need to create our own Controller Factory that derives from DefaultControllerFactory and overrides the default controller instantiation behaviour:

public class IocControllerFactory : DefaultControllerFactory
{
    public IocControllerFactory()
    {
        var controllerTypes = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())
                              where typeof(IController).IsAssignableFrom(t)
                              select t;

        foreach (Type type in controllerTypes)
        {
            IocHelper.Container().AddComponentLifeStyle(type.FullName, type, LifestyleType.Transient);
        }
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType != null)
        {
            return (IController)IocHelper.Container().Resolve(controllerType);
        }

        return base.GetControllerInstance(requestContext, controllerType);
    }
}

The controller factory works by looking through the types in all the currently loaded Assemblies, and gets any that implement the IController interface, so you're free to carve up your Visual Studio Solution into whatever Projects you like, the IocControllerFactory will find your controllers. Looping through all types in all loaded Assemblies is a slow operation (about 50 milliseconds in my app), but it only happens once on start-up. The GetControllerInstance is responsible for instantiating the Controller for each HTTP request, and is instantaneous.

Next we need to register the new IocControllerFactory, do this in your web apps Global.asax.cs file:

public class MvcApplication : System.Web.HttpApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        // ... router registration code (snip) ... //
    }

    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory());
    }
}

Now we need to create an XML file where we tell the IOC container what the concrete implementations are, eg. what is the concrete type for IProductsController. You may have noticed that in the IocHelper class we created the Container itself with the line:

_container = new WindsorContainer(new XmlInterpreter("ioc.xml"));

ioc.xml is the file where we specify the dependencies, located in the root of the web app folder. People sometimes put these in the web.config file, but I prefer keeping them separate to keep your web.config file nice and clean, we can also swap dependencies while the app is still running (modifying the web.config resets the web AppDomain).

Create an ioc.xml file next to your web.config file, then place the following into it:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <components>
    
    <!-- Repositories -->
    <component id="ProductRepository"
      service="MyMvcApp.Repository.IProductRepository, MyMvcApp"
      type=" MyMvcApp.Repository.Impl.NHibernateProductRepository, MyMvcApp"
      lifestyle="PerWebRequest">
    </component>
    <!-- End of Repositories -->

  </components>
</configuration>

Make sure the Namespaces and Assemblies are set according to your project. The 'service' attribute specifies the Interface or Abstract class (IProductRepository), 'type' specifies the concrete implementation to be used (NHibernateProductRepository).

If your concrete type has its own dependencies, you can specify them as well:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <components>

    <component id="NHibernateDataContextProvider"
      service=" MyMvcApp.NHibernate.INHibernateDataContextProvider, MvcLibrary"
      type=" MyMvcApp.NHibernate.Impl.WebSessionProvider, MvcLibrary"
      lifestyle="PerWebRequest">
    </component>

    <!-- Repositories -->
    <component id="ProductRepository"
      service="MyMvcApp.Repository.IProductRepository, MyMvcApp"
      type=" MyMvcApp.Repository.Impl.NHibernateProductRepository, MyMvcApp"
      lifestyle="PerWebRequest">
     <parameters>
        <ProviderFactory>${NHibernateDataContextProvider}</ProviderFactory>
      </parameters>
    </component>
    <!-- End of Repositories -->

  </components>
</configuration>

The 'lifestyle' specifies how long the concrete type is kept alive for, options are Transient, Singleton, PerWebRequest, Gay, Straight, and Hedonist (OK I made the last three up). PerWebRequest keeps the instance alive for the currently executing HTTP request, and is removed at the end. For this to work we need add an HttpModule to your web.config file for Castle Windsor to clear the instance at the end of the HTTP request like so:

<httpModules>
   <!— other modules, snip -->
   <add name="PerRequestLifestyle"
      type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.MicroKernel"/>
</httpModules>

Also add this module to the IIS 7 HttpModule section for running under IIS 7 on Windows Server 2008/Vista/7.

Repository Pattern

Don't forget your Repository implementation:

public class NHibernateProductsRepository : IProductsRepository
{
   protected INHibernateDataContextProvider SessionProvider = null;

   public NHibernateProductsRepository(INHibernateDataContextProvider dataContextProvider)
   {
      SessionProvider = dataContextProvider;
    }

   public IList<Product> ListAllProducts()
   {
      ISession session = SessionProvider.GetSession();
      return session.CreateCriteria<Product>().List<Product>();
    }
}

And the interface:

public interface IProductRepository
{
   IList<Product> ListAllProducts();
}

The Repository Pattern, coined by Martin Fowler (I think) in his book Patterns of Enterprise Application Architecture, is a way of decoupling your entities (Customer, Product etc.) from any data access code, and abstracting away the actual data storage implementation. Read more about it here or here.

Conclusion

Castle Windsor is a very powerful IOC container with many options for wiring up dependencies. Read more about Castle Windsor here.

There are other IOC containers out there for the .NET framework, for instance Ninject lets you specify your dependencies in code instead of verbose XML configuration files. Unity is an official Microsoft IOC container. Indeed there is more to the Dependency Injection Principle than I've been able to cover here, I encourage you to explore this very powerful paradigm in software engineering and write more elegant, maintainable and unit testable code.

In the next blog post I hope to cover wiring up dependencies during ModelBinding.

6 Comments on "IOC in MVC – Controllers"

Post a Comment
  • RE: IOC in MVC – Controllers

    Everything is nice but the point of discussion may be whether to put
    "IocHelper.Container().AddComponentLifeStyle(type.FullName, type, LifestyleType.Transient);"
    to ControllerFactory or not.

    Developing similar mechanisms on top of ASP.NET MVC, I ended up using Common ServiceLocator while having own implementation of IServiceRegistrar which auto-registers (by scanning assemblies) anything (including controllers) outside of controller factory but during the MvcStarterTask initialization (which is IStarterTask implementation - or IBootstrapperTask in your case).

    The benefit is that my factory is completely agnistic of any kind of "service registrar" itself while my MvcStarterTask provides centralized MVC configuration in a way I need. Moreover, ASP.NET MVC 3 will try to hook up the registered "IController"s inside the DefaultControllerFactory using exactly that Common ServiceLocator.

    Posted on 1 October 2010 - 8:30 PM / by Vasilio

    • RE: RE: IOC in MVC – Controllers

      There have been some criticisms of the Common Service Locator pattern, namely from Mark Seemann's blog here http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

      It's not something I've researched enough myself to have an informed opinion on, but it's well worth reading his views on it.

      Posted on 2 October 2010 - 4:51 PM / by Dominic Pettifer (Administrator)

      • RE: RE: RE: IOC in MVC – Controllers

        Dominic,

        Thanks for the link, I read that but, heh, there is about another service locator :)

        Common ServiceLocator isn't just a classic "Service Locator" pattern. It provides interface - the IServiceLocator, just to make your application unaware of concrete IoC container technology.

        Your IoC Helper class is much more like that old good service locator, about which Mr. Seemann talks.

        My IServiceLocator implementation (which is StructureMap adapter) acts just like a wrapper around my StructureMap container. And I put it inside any class that wants to create some objects. In case we have no Common Service Locator, I'd just put an "IContainer container" as a constructor parameter of such a class. With CSL I put "IServiceLocator locator".

        It simple - I never use static service locators mentioned by Mark Seemann. And I never lose those "auto-wiring" DI capabilities of my container. With that said - I have clear testing scenarios - I can instantiate containers (IContainer) along with Service Locators (IServiceLocator). IServiceLocator itself, when created, takes an IContainer dependency as a constructor parameter.

        Moreover, CSL's IServiceLocator doesn't have anything about "service registration" (as in Mark Seemanns post) - it's just not a locator's option, it belongs to kinda IServiceRegistrar. It just resolves instances for you (which are anyway somehow registered in your container).

        To summarize use cases: I use IServiceLocator exactly when I whould use my IoC container AS a "service locator" while preferring constructor-DI in most cases (example is your ControllerFactory - you just can't inject controllers with factory's constructor - instead you use your container in "service-locator" style to resolve the controllers inside the factory).

        Posted on 5 October 2010 - 2:19 PM / by Vasilio

        • ugg bailey button

          In 1990, <b><a href="http://www.buyairjordans.net/">jordan shoes on sale</a></b> Li Moucheng her third husband. She <b><a href="http://www.buyairjordans.net/air-jordan-retro-8-C39.html">jordan 8 for sale</a></b> thought <b><a href="http://www.buyairjordans.net/air-jordan-retro-7-C38.html">Cheap Jordan 7</a></b> <b><a href="http://www.buyairjordans.net/air-jordan-retro-7-C38.html">Jordan 7 For Sale</a></b> that finally <b><a href="http://www.buyairjordans.net/air-jordan-retro-7-C38.html">Buy Jordan 7</a></b>

          Posted on 15 October 2011 - 2:02 AM / by ugg bailey button

      • SEO Company India

        Search engine optimization (SEO Company USA) can be defined as an activity that undertakes web promotion of websites/portals and web pages. The quality SEO services ensure ranking of a website in popular search engines such as Yahoo, Google, Bing and MSN.
        Search engine optimization (SEO Company USA) can be defined as an activity that undertakes web promotion of websites/portals and web pages. The quality SEO services ensure ranking of a website in popular search engines such as Yahoo, Google, Bing and MSN.

        [url=http://www.seosoftwareservices.com]SEO India[/url]

        Posted on 3 January 2012 - 12:47 PM / by WEB Development India

      • RE: RE: RE: IOC in MVC – Controllers

        This information seems to be useful for me, thanks for the publication!

        Posted on 25 January 2012 - 4:59 PM / by custom college essays

    • air jordan

      but <a title="nfl women jerseys baltimore ravens" href="http://www.jerseyswall.com/discount-guileless-nfl-women-jerseys-baltimore-ravens.htm" target="_blank">nfl women jerseys baltimore ravens</a> if you want to prevent being <a title="nike air max tailwind" href="http://www.www.nikewall.com/nike-air-max-tailwind-shoes-at-cut-price.htm" target="_blank">nike air max tailwind</a> taken from the scammers be sure <a title="christian louboutin point toe pumps" href="http://www.heelsforsale.com/christian-louboutin-point-toe-pumps-quick-ship.htm" target="_blank">christian louboutin point toe pumps</a> to find legitimate wholesale suppliers by <a title="jordan 11 fusion jordan 13" href="http://www.www.nikewall.com/better-compare-nike-air-jordan-11-fusion-jordan-13-shoes.htm" target="_blank">jordan 11 fusion jordan 13</a> purchasing a reputable wholesale product directory. <a title="nike air shox women shoes" href="http://www.nikewall.com/wholesale-nike-air-shox-women-shoes.htm" target="_blank">nike air shox women shoes</a> you won't be sorry.learn more <a title="detroit lions jerseys" href="http://www.westonsale.com/nfl-detroit-lions-jerseys.htm" target="_blank">detroit lions jerseys</a> about finding legitimate wholesale suppliers, drop <a title="air yeezy women" href="http://www.westonsale.com/air-yeezy-women-shoes.htm" target="_blank">air yeezy women</a> shipping, and selling through auctions.provide guidance. smart <a title="mbt wingu shoes women" href="http://www.shoeswall.com/mbt-wingu-shoes-women-manufacturer.htm" target="_blank">mbt wingu shoes women</a> wholesalers spend time educating their customers.

      Posted on 13 June 2011 - 9:28 AM / by air jordan

      • RE: air jordan

        air jordan says...
        but <a title="nfl women jerseys baltimore ravens" href="http://www.jerseyswall.com/discount-guileless-nfl-women-jerseys-baltimore-ravens.htm" target="_blank">nfl women jerseys baltimore ravens</a> if you want to prevent being <a title="nike air max tailwind" href="http://www.www.nikewall.com/nike-air-max-tailwind-shoes-at-cut-price.htm" target="_blank">nike air max tailwind</a> taken from the scammers be sure <a title="christian louboutin point toe pumps" href="http://www.heelsforsale.com/christian-louboutin-point-toe-pumps-quick-ship.htm" target="_blank">christian louboutin point toe pumps</a> to find legitimate wholesale suppliers by <a title="jordan 11 fusion jordan 13" href="http://www.www.nikewall.com/better-compare-nike-air-jordan-11-fusion-jordan-13-shoes.htm" target="_blank">jordan 11 fusion jordan 13</a> purchasing a reputable wholesale product directory. <a title="nike air shox women shoes" href="http://www.nikewall.com/wholesale-nike-air-shox-women-shoes.htm" target="_blank">nike air shox women shoes</a> you won't be sorry.learn more <a title="detroit lions jerseys" href="http://www.westonsale.com/nfl-detroit-lions-jerseys.htm" target="_blank">detroit lions jerseys</a> about finding legitimate wholesale suppliers, drop <a title="air yeezy women" href="http://www.westonsale.com/air-yeezy-women-shoes.htm" target="_blank">air yeezy women</a> shipping, and selling through auctions.provide guidance. smart <a title="mbt wingu shoes women" href="http://www.shoeswall.com/mbt-wingu-shoes-women-manufacturer.htm" target="_blank">mbt wingu shoes women</a> wholesalers spend time educating their customers.

        Posted on 27 September 2011 - 4:53 AM / by Anonymous

        • ugg uk

          Zhaojun motorcycle does not start, ugg australia uk

          Posted on 15 October 2011 - 2:14 AM / by ugg uk

        • ugg boots outlet

          <b><a href="http://www.uggboots--uk.co.uk/">uggs sale</a></b> will <b><a href="http://www.uggaustralia-ukshop.co.uk/">ugg boots for kids</a></b> quarrel. However, <b><a href="http://www.uggaustraliaboots.org.uk/">ugg australia uk</a></b> Chen <b><a href="http://www.uggaustraliaboots.org.uk/">ugg australia boots</a></b> <b><a href="http://www.uggboot-baileybutton.co.uk/">uggs boots sales</a></b> <b><a href="http://www.uggbaileybutton.me.uk/">uggs boots for women</a></b> Rooster read <b><a href="http://www.uggbaileybutton.me.uk/">ugg bailey button</a></b> private <b><a href="http://www.uggboots--uk.co.uk/">uggs girls</a></b> <b><a href="http://www.uggboots--uk.co.uk/">ugg boots uk</a></b> school still humility: Because <b><a href="http://www.uggboot-baileybutton.co.uk/">where to buy ugg boots</a></b> <b><a href="http://www.uggaustralia-ukshop.co.uk/">ugg kensington</a></b> one thing <b><a href="http://www.uggbaileybutton.me.uk/">ugg clearance boots</a></b> and <b><a href="http://www.uggaustraliaboots.org.uk/">boot ugg uk</a></b> noi... <b><a href="http://www.uggaustralia-ukshop.co.uk/">ugg australia uk shop</a></b> <b><a href="http://www.uggboot-baileybutton.co.uk/">ugg boot bailey button</a></b>

          Posted on 15 October 2011 - 5:08 AM / by ugg boots outlet

          • RE: ugg boots outlet

            louis vuitton outlet http://www.officialoutletlouisvuitton.com louis vuitton outlet http://www.lowlouisvuittonoutlets.com louis vuitton outlet http://www.officiallouisvuittonoutletu.com louis vuitton outlet http://www.louisvuittonoutletusas.com louis vuitton outlet http://www.louisvuittonluxuryoutlets.com ugg boots clearance http://www.officialuggsbootssclearance.com ugg outlet http://www.uggsbootofficialoutlets.com http://www.louisvuittonofficialoutletu.com louis vuitton outlet

            Posted on 5 January 2012 - 2:39 AM / by louis vuitton outlet

        • http://www.nikefreerun2dk.com/

          he <strong><a href="http://www.nikefreerun2dk.com/dame-nike-free-30-c-6.html" title="Billig Nike Free">Billig Nike Free</a></strong> emergence of these <strong><a href="http://www.nikefreerun2dk.com/dame-nike-free-2012-c-4.html" title="Nike Free Running">Nike Free Running</a></strong> things. This time hit, Needless to say, <strong><a href="http://www.nikefreerun2dk.com/dame-nike-free-30-c-6.html" title="Nike Free 3.0">Nike Free 3.0</a></strong> I can not let <strong><a href="http://www.nikefreerun2dk.com/dame-nike-free-2012-c-4.html" title="Nike Free Run 2">Nike Free Run 2</a></strong> it <strong><a href="http://www.nikefreerun2dk.com/" title="Nike Free Tilbud">Nike Free Tilbud</a></strong> gently. <strong><a href="http://www.nikefreerun2dk.com/dame-nike-free-2012-c-4.html" title="Nike Free Dame">Nike Free Dame</a></strong> I made <strong><a href="http://www.nikefreerun2dk.com/herre-nike-free-run-plus-c-9.html" title="nike free run">nike free run</a></strong> the...

          Posted on 30 January 2012 - 2:34 AM / by nike free run

    • http://www.barbour-jackets-uk.net

      The [url=http://www.juicybag.org/]juicy bag[/url] with abundant affection. These [url=http://www.uk-barbourjacket.net/]quilted jackets barbour[/url] with the artistic design. With these [url=http://www.uk-barbourjacket.net/]barbour jacket[/url] do attending actual timeless. Thus, these [url=http://www.juicybag.org/]juicy couture[/url] attending altered from the accustomed [url=http://www.juicybag.org/]Juicy outlet[/url] in market. Featuring the lining abounding with [url=http://www.uk-barbourjacket.net/barbour-mens-jacket-c-18.html]Barbour jackets for men[/url] online. You can get the [url=http://www.juicybag.org/juicy-backpack-c-6.html]juicy backpack[/url]. It adds abundant absorption to [url=http://www.uk-barbourjacket.net/]Barbour jackets[/url] sale.

      Posted on 22 December 2011 - 7:35 AM / by quilted jackets barbour

    • Screen printed t-shirts

      Wonderful post! I wish I had your insight on this topic and could write as well as you. I hope many people get the opportunity to enjoy this great content.

      Posted on 30 December 2011 - 5:56 AM / by Screen printed t-shirts

    • london marketing internship

      Thank you for this post. That’s all I can say. You clearly know what you are doing, you’ve covered so many bases.Thanks!

      Posted on 19 January 2012 - 7:37 AM / by london marketing internship

  • RE: IOC in MVC – Controllers

    "There are other IOC containers out there for the .NET framework, for instance Ninject lets you specify your dependencies in code instead of verbose XML configuration files."

    CastleWindsor also lets you do this. I used the following code for my own example:

    var container = new WindsorContainer();
    
    container.Register(Component.For<IRepository>()
                 .ImplementedBy<DefaultRepository>()
                 .LifeStyle.Singleton)
             .Register(Component.For<IValidator>()
                 .ImplementedBy<DefaultValidator>()
                 .LifeStyle.Singleton)
    
    ControllerBuilder.Current.SetControllerFactory(new IocControllerFactory(container));

    Posted on 1 June 2010 - 1:31 PM / by Alan

    • Jordan 12

      a total of 9 times NBA Defensive first team, this is the best Jordan 12 For Sale air jordan sale historical record.

      27, NBA player Michael Jordan has created the highest efficiency value of 27.9.

      28, Jordan 8 consecutive single-season scoring average over 30, better than Wilt Chamberlain, 7, ranked the history ...

      Posted on 19 May 2011 - 4:03 AM / by Jordan 12

    • http://www.nikejordanoutlet.net/

      rfume world, <a href="http://www.nikejordanoutlet.net/jordan-fusion-C56.html" title="Jordan Fusion">Jordan Fusion</a> its product lines <a href="http://www.nikejordanoutlet.net/" title="Cheap Air Jordan">Cheap Air Jordan</a> continue to follow the scent of three: Boss, Hugo, and BALDESSARINI, representing three brands in three different temperament and belief in life .
      <br> <br>
      <br> <br> 2000 years of BOSS perfume for women in the market, the introduction of the first female boss woman...

      Posted on 3 June 2011 - 3:24 AM / by Jordan Shoes

  • BD Connection

    I'm just wondering how do you manage your connection to a real time database. I am following other examples and I don't seem to get the database connection right for a real time example
    thank you
    (I hope my question es clear enough)

    Posted on 12 April 2010 - 1:23 AM / by Alvaro Romero Perez

    • RE: BD Connection

      Look in IOC.Data.RepositoryImpl.FakeCategoryRepository

      He's currently not using a database, but rather some factory to produce items.

      Like he mentioned, the implementation can easily be swapped out with one that work against a real database. That's the beauty of using a repository pattern and dependency injection.

      Posted on 2 May 2010 - 10:08 AM / by Krokonoster

    • 879927533@qq.com

      <b><a href="http://www.ugg-for-sale.co.uk/">ugg boots uk</a></b> quarter <b><a href="http://www.ugg-for-sale.co.uk/">ugg boots sale</a></b> of rural residents for the whole family, <b><a href="http://www.uggbootsaustralia.me.uk/">ugg australia sale uk</a></b> guaranteeing <b><a href="http://www.ugg-for-sale.co.uk/">ugg boots sale uk</a></b> payment on $ <b><a href="http://www.uggbootsaustralia.me.uk/">ugg australia</a></b> 240...

      Posted on 16 November 2011 - 5:54 AM / by cheap uggs

Leave a Comment

Comment Details
*
* BBCode: [b]bold[/b], [i]italics[/i], [code]code[/code], [li]bullet point[/li], [h]Heading[/h], [url="http://www.example.com"]link[/url], [quote author="John Smith"]quote[/quote]

Random Image

Hamster standing next to a tiny hard drive.

Tiny hard drive or GIANT hamster? You decide! (from the blog And So It Begins )

Quick Poll

What is your DIP/IOC Container of choice?

Poll Vote
(see results)
View Comments (625) (See previous polls)

Latest Tweets

  • And YouTube still auto-fucking-plays videos!! This is TWO-THOUSAND-AND-FUCKING-TWELVE FFS!!!

    about 20 hours ago from web
  • On a side-note, YouTube's commenting system is god-awful atrocious dreadful horrible horrible horrible!! Constant meaningless error messages

    about 20 hours ago from web
  • JavaScript is slow mmmkay http://t.co/NbB4eQjw - Actually, no, it's not http://t.co/kpGEIoPO #nodejs

    about 20 hours ago from web
  • TFS: It's super expensive, so it must be brilliant, right? Like Sharepoint #tekpubtfstitlesuggestion

    5:22 PM February 3rd from web

View Dominic Pettifer's Twitter page.