Fluentsecurity without an ioc container

Published on den 28 September 2012

I just started using FluentSecurity for the first time but on a small project without an IOC container. Here is how you make that work.

In FluentSecurity by @kristofferahl you register your authorization policies using a fluent interface. If an policy is not violated because someone tries to access a page they don't have access to and exception will be thrown. If you want to handle this by redirecting to the loginpage you need to register your policy violation handler for that policy.

To get Fluent Security to use your custom violation handlers you need to register them. At this time, the only way to do this is by using an IoC-container.

From the documentation at: http://www.fluentsecurity.net/wiki/Policy-violation-handlers

This project does not use an IoC container though (motivation found at the end of the post) and I wasn't keen on adding one only to get FluentSecurity working. Luckily the documentationen here is a bit missleading. Look at the code used to register the IoC container:

configuration.ResolveServicesUsing(type => ObjectFactory.GetAllInstances(type).Cast<object>());

If you think about what's really expected here it's a Func<Type, IEnumerable<object>>. In other words something that takes a type and returns a list of intances implementing that type. We don't need a fullblown IoC Container for that! Let's just do it manually.

In the simplest(but maybe not the most elegant) form we can do like this:

configuration.ResolveServicesUsing(type =>
{
    if (type == typeof(IPolicyViolationHandler))
    {
        return new List<IPolicyViolationHandler>() { 
            new DenyNonAdminViolationHandler(),
            new DenyAnonymousAccessPolicyViolationHandler(),
            new DenyAuthenticatedAccessPolicyViolationHandler(),
        };
    }
    return Enumerable.Empty<object>();
});

Now you might want more types and this will soon get a bit ugly because of all those ifs. In my case this is not a problem yet so I'll leave it like this but if it were to become a problem I would create a Dictionary<Type, IEnumerable> and do the lookups against that. You could also do the registration using reflection but then I will argue that maybe using a full IoC is simpler anyway.

Why I don't want to use an IoC container in this project (asp.net mvc)

  1. I think an IoC adds complexity. I hope to involve some people with very little programming experience in this project and want to keep it simple. You know that feeling when you want to throw the computer out the window because the IoC container can't resolve your class and you can't figure out why? This is not something I want and I certainly wouldn't want a beginner to face that problem. People will stop coding for less..

  2. I think IoC containers promote abstraction hell. Throw in a service here, a view model builder there and do not forget about all those repositories! Some people will argue that this is good design. I will argue that it's overengineeringin many cases. Don't build you system based on what COULD happend in the future. If you keep it simple refactoring will be easy when you need it.

So what about testing? I mean spending a lot of time mocking away my services and repositories so I can test the almost non existant logic in my controller is soooo much fun, very important and catch all errors in my application Sarcasm!

IMO the idea of unit testing CRUD is BS and a waste of time. Unit testing is great for logic but the best way to handle this is to remove the logic from your CRUD chain. Need to run calculations on an entity and test that? Put it in a static method, extension method or a separate class and test that. This will keep the tests for the logic simpler as the setup will be smaller and easier. Then run integrations tests on the controllers for things like sorting, validation and other "simple" stuff.

Doing this you will actually have tested the whole system from the db to the controllers (GUI still remains though). You have also created an architecture that is much easier to refactor because you don't care about the internal implementation. Your tests are less fragile to refactoring.

So pure logic -> unit test, the rest -> integration test.

When this breaks down is where you start talking to external webservices and similar. You will want to inject a proxy for these, so you can test using a known(stored) response. So it depends my project if use an IoC container but the point is that I don't add it before I need it (or KNOW I will need it). Keep it simple!    

Then feel free to it or if you have any comments or questions mention @MikaelEliasson on Twitter.

CTO and co-founder at Bokio with a background as an elite athlete. Still doing a lot of sports but more for fun.

#development, #web, #orienteering, #running, #cycling, #boardgames, #personaldevelopment