Ninjecting ASP.NET MVC 4 Web Api

Injecting dependencies into ASP.NET MVC controllers is straightforward with Ninject. Just install Ninject and Ninject.MVC3 via nuget. It will create a file “NinjectWebCommon.cs” under App_Start folder. And you add your service bindings in RegisterServices method like this.

///
/// Load your modules or register your services here!
///
///The kernel.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IDocumentRepository>().To<DocumentRepository>();
}

Yet, out of the box, it doesn’t support web api controller dependency resolution. You need to create your own resolver class. An example is filips’s ninject resolver.

After you create the resolver, add it to CreateKernel() method.

/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
    kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
            
    RegisterServices(kernel);
    GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);

    return kernel;
}

Now it’s all ready for both MVC controller and Web Api controller.

Ninjecting ASP.NET MVC 4 Web Api

About Castle Windsor Container

Since I moved to Huddle, I am using Castle Windsor. This post is the summary of what I would learn while using Castle Windsor.

the source code

I don’t know why, but I found it difficult to find where the code is. It is here at https://github.com/castleproject. Even there is a stackoverflow question about where the code is.

Very descriptive error message

I often struggled with StructureMap error message, as it doesn’t tell you what went wrong. I like Windor’s, as it clearly states where it is screwed.

Can’t create component ‘LondonUbf.Installers.LoggerInterceptor’ as it has dependencies to be satisfied.

‘LondonUbf.Installers.LoggerInterceptor’ is waiting for the following dependencies:
– Service ‘LondonUbf.Domain.ExceptionLogger’ which was not registered.

Tutorials

There are a few tutorials. The link was in readme file of the project.

Use of Predicate

By the way, an example code in the tutorial uses Predicate, and it is interesting. I knew they exists, but didn’t really use it in my day-to-day coding.

[Test]
public void All_Controllers_Are_Registered()
{
    var allControllers = GetPublicClassesFromAssembly(c => c.Is<IController>());
    var registeredControllers = GetImplementaionTypesFor(typeof (IController), _containerWithControllers);
 Assert.That(allControllers, Is.EqualTo(registeredControllers));
}
private Type[] GetPublicClassesFromAssembly(Predicate<Type> where)
{
    return typeof (HomeController).Assembly.GetExportedTypes()
        .Where(t => t.IsClass)
        .Where(t => t.IsAbstract == false)
        .Where(where.Invoke)
        .OrderBy(t => t.Name)
        .ToArray();
}

By accepting Predicate parameter, you can make the method to accept lamda filter. This is the source of Predicate. It is delegate that returns boolean value.

namespace System
{
    /// <summary>
    /// Represents the method that defines a set of criteria and determines whether the specified object meets those criteria.
    /// </summary>
    ///
    /// <returns>
    /// true if <paramref name="obj"/> meets the criteria defined within the method represented by this delegate; otherwise, false.
    /// </returns>
    /// <param name="obj">The object to compare against the criteria defined within the method represented by this delegate.</param><typeparam name="T">The type of the object to compare.This type parameter is contravariant. That is, you can use either the type you specified or any type that is less derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</typeparam><filterpriority>2</filterpriority>
    public delegate bool Predicate<in T>(T obj);
}

Registering interfaces

Not much different from other IoC containers like Ninject and StructureMap.

public class RepositoriesInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Component.For<FileNameParser, IMessageParser>());
        container.Register(
            Component.For<MessageRepository, IMessageRepository>()
            .DependsOn(new { messageDirectory = HostingEnvironment.MapPath("/Content/messages")})
            );
    }
}

If your class depends on any other variable, you can use .DependsOn to resolve it. In the above example, I used HostingEnvironment.MapPath to find out the directory of “messages”. It doesn’t require HttpContext, unlike Server.MapPath(…).

cf) The difference betweeen Server.MapPath and HostingEnvironment.MapPath(…): http://stackoverflow.com/questions/944219/what-is-the-difference-between-server-mappath-and-hostingenvironment-mappath

Dynamic Proxy

where T: class, new()

It is a constraint on the generic parameter that T must be a class and have an parameterless default constructor. (from Stackoverflow)

The DP tutorial example used this syntax.

public static TFreezable MakeFreezable<TFreezable>() where TFreezable : class, new()
{
    var freezableInterceptor = new FreezableInterceptor();
    var proxy = _generator.CreateClassProxy<TFreezable>(new CallLoggingInterceptor(), freezableInterceptor);
    _freezables.Add(proxy, freezableInterceptor);
    return proxy;
}

It is surprisingly simple to intercept a call to method. Just add .Interceptors() to the component registration.

container.Register(
    Component.For<MessageRepository, IMessageRepository>()
    .DependsOn(new { messageDirectory = HostingEnvironment.MapPath("/Content/messages")})
    .Interceptors<MessageRepositoryInterceptor>()
    );

The interceptor is a simple class.

public class MessageRepositoryInterceptor : IInterceptor
{
    private readonly ExceptionLogger _logger;

    public MessageRepositoryInterceptor(ExceptionLogger logger)
    {
        _logger = logger;
    }

    public void Intercept(IInvocation invocation)
    {
        try
        {
            _logger.Log(string.Format("{0}.{1},  Message: {2} ", invocation.TargetType.Name, invocation.Method.Name, invocation.Arguments[0]));
            invocation.Proceed();
        }
        catch(Exception ex)
        {
            _logger.Log(ex);
            throw;
        }
    }
}

the Life cycle of objects

Quite bluntly saying, if you inject your dependencies into constructor of a class, those dependent objects are disposed together when the class gets disposed. However, if you use resolve a dependency manually, using .Resolve(), you have to release it manually.

About Castle Windsor Container