Monday, April 29, 2013

Getting Started with Castle Windsor Interceptors in ASP.NET MVC

Don’t you hate when writing code you have to think about generic exception handling, logging of method calls, caching of methods, authorization, etc...  Well suppose there was a tool/technique you could use that you could write the above items once and make sure they get implemented on existing code along with any new code added in the future.  Castle Windsor and its Interceptors support just that.

In the example below we will create a interceptor and do the necessary wiring up to make it work.  We will be using an ASP.NET MVC4 application based on the initial Windsor setup done in my last blog post.
http://blog.devdave.com/2013/04/castle-windsor-in-aspnet-mvc-4.html

Create a manager class to do some work.  We will call methods of this class in our controller class. later in this blog post  In the Infrastructure folder create a new folder called Managers.  Inside the Managers folder create a new folder called Interfaces.  Create an interface called IExampleManager in the interface folder.

public interface IExampleManager
{
    void ExampleMethod();
}

Creating the concrete implementation of the manager, create a class called ExampleManager in the Managers folder.

public class ExampleManager : IExampleManager
{
    public void ExampleMethod()
    {
        Debug.WriteLine("Doing Work...");
    }
}

Now we need to register our new manager in Windsor.  In the Infrastructure\Installers folder add a new class called ManagerInstaller.

public class ManagerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
            .Where(type => type.Name.EndsWith("Manager"))
            .WithServiceDefaultInterfaces()
            .Configure(c => c.LifestyleTransient()));
    }
}

Now that Windsor knows how to handle the manager we can modify our controllers constructor like so

private IExampleManager exampleManager;

public HomeController(IExampleManager exampleManager)
{
    this.exampleManager = exampleManager;
}

Since Windsor knows how to turn an IExampleManager into ExampleManager it will handle this for us when Windsor instantiates the controller.

Modify the controller action method to call a method on the example manager.

public ActionResult Index()
{
    this.exampleManager.ExampleMethod();
    return new ContentResult(){Content = "test"};
}

Running the site and calling the Index action, note the output window.
image

Now lets say we wanted to intercept the call to any public method of the ExampleManager class.  We can do this by adding in an interceptor. To do this we will need to create the interceptor.  Create a new folder inside the infrastructure folder called Interceptors.  Create a new class in this folder called ExampleInterceptor.

public class ExampleInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Debug.WriteLine(string.Format("Before method: {0}", invocation.Method.Name));
        invocation.Proceed();
        Debug.WriteLine(string.Format("After method: {0}", invocation.Method.Name));
    }
}

Now we need to tell Windsor about the interceptor.  In the Infrastructure\Installers folder lets add a new class called InterceptorInstaller.

public class InterceptorInstaller : IWindsorInstaller
{
    public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
    {
        container.Register(Component.For<ExampleInterceptor>()
                               .LifestyleTransient());
    }
}

Now lets go back to our manager installer and add in the interceptor to all managers.

public class ManagerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
            .Where(type => type.Name.EndsWith("Manager"))
            .WithServiceDefaultInterfaces()
            .Configure(c => c.LifestyleTransient().Interceptors<ExampleInterceptor>()));
    }
}

Running the site and calling the Index action, note the output window now.
image

As you can see the interceptor intercepted the call to the method on our ExampleManager.   Adding new public methods to our manager call will automatically get intercepted also.  This means that adding code in the future required no thought about the interceptor.  This opens up all kinds of ideas for interceptors like:

  • Exception Handling
  • Logging
  • Performance Counters
  • Authorization
  • Caching
  • Timing
  • etc...

Note there is a different way to implement interceptors.  You can use an attribute on a class that is already under the control of Windsor.  More information about this can be found here: http://docs.castleproject.org/Windsor.Interceptors.ashx.

Monday, April 15, 2013

Castle Windsor in Asp.Net MVC 4

The project I am using at work currently uses Castle Windsor as its IOC container.  My colleague did the initial setup so I decided to do this blog post based on a new MVC project to explain the setup and get more familiar with the steps needed to make MVC and Castle Windsor work together.

First thing, create a new MVC 4 website (which template you use is up to you).  After that I updated all the existing NuGet packages and added this one Castle Windsor.

Create a Infrastructure folder at the root of the MVC application.  Inside the Infrastructure folder create a WindsorControllerFactory class.  This will inherit MVC’s DefaultControllerFactory and override the GetControllerInstance and ReleaseController methods. We will use this class in a later step to tell MVC to use this controller factory instead of its default one.

public class WindsorControllerFactory : DefaultControllerFactory
    {
        private readonly IKernel kernel;

        public WindsorControllerFactory(IKernel kernel)
        {
            this.kernel = kernel;
        }

        public override void ReleaseController(IController controller)
        {
            kernel.ReleaseComponent(controller);
        }

        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType == null)
            {
                throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
            }
            return (IController)kernel.Resolve(controllerType);
        }
    }

Next create a folder in the Infrastructure called Installers.  This is where all of the installers used by Windsor will go.  Our first installer will be a class named ControllersInstaller.  This inherits the IWindowsInstaller interface which requires the implementation of the Install method.  The code below basically says all classes in the assembly that are based on the IController interface should be created using LifestyleTransient which basically means instantiate an instance every time.

public class ControllersInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Classes.FromThisAssembly()
                                .BasedOn<IController>()
                                .LifestyleTransient());
        }
    }

The last step needed to get things running is the modifications needed in the global.asax.cs file.  There are several things going on the code below.  Note the static field used to store the container, the value of the field is set in the static method BootstrapContainer.  This method does two things.

  1. Set the value of the container by instantiating an instance of the WindsorContainer and telling it to Install all the installers in the assembly (basically any class that inherits form the IWindsorInstaller interface).
  2. Tell MVC to use our WindsorControllerFactory instead of the default MVC controller factory implementation.

The BootstrapContainer method is called on application start after the other MVC registration code.  The last change is to dispose the container on application end.

public class MvcApplication : System.Web.HttpApplication
{
    private static IWindsorContainer container;

    private static void BootstrapContainer()
    {
        container = new WindsorContainer().Install(FromAssembly.This());

        var controllerFactory = new WindsorControllerFactory(container.Kernel);
        ControllerBuilder.Current.SetControllerFactory(controllerFactory);
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        MvcApplication.BootstrapContainer();
    }

    protected void Application_End()
    {
        container.Dispose();
    }
}

At this point adding a controller and view should work correctly.  All these changes to make MVC work the way it would have before doing all this.  So what is the big deal, what if in my Home controller I wanted to do something like this:

private IContactManager contactManager;

public HomeController(IContactManager contactManager)
{
    this.contactManager = contactManager;
}

Using the code we have now this would not work since the container at this point would not know how to resolve IContactManager into its concrete implementation.  To get this to work we would need to add a new installer to our installer folder.  For example:

public class ManagerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
            .Where(type => type.Name.EndsWith("Manager"))
            .WithServiceDefaultInterfaces()
            .Configure(c => c.LifestyleTransient()));
    }
}

This installer’s install method would get called by the instantiation of the container in the global.asax.cs application start event.  This installer says to register all the classes in the assembly that end in Manager and follow the default interface pattern (info) and instantiate them on a per use basis.

So now lets say the CustomerManager had a dependency on the CustomerRepository.  This would require a new installer.  I prefer to use a separate installer for each convention I am going to use.  This way if a specific convention needs to have a different lifestyle (per call, singleton, etc…) it easier to setup.  No need to show this installer since it would be just like the one above with a separate lambda in the where clause.

Wednesday, January 23, 2013

Mocking an internal interface with Moq

The other day I was trying to write some unit tests on a public class with an internal constructor.  In order for the test project to get access to the internal constructor (primarily used for testing) I had to add the assembly: InternalsVisibleTo to the AssemblyInfo.cs file and specify the class library I was testing would expose its internals to the test class library, for example:

[assembly: InternalsVisibleTo("SomeApi.Test")]

This got me close, next issue was the parameter of the internal constructor was an internal interface referencing a dependency of the class under test.  No big deal.  I figured I would use Moq to mock out the dependency and I got the following error when trying to run the test:

Test method SomeNamespace.SomeClass.SomeTestMethod threw exception:
Castle.DynamicProxy.Generators.GeneratorException: Type SomeNamespace.SomeInterface is not public. Can not create proxy for types that are not accessible.

Hmm, it seems like Moq does not have access to the internals.  Adding the following to the class libraries AssemblyInfo.cs file solved the problem

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

Next time I ran the test Moq was able to access the internal interface and my test passed.