Cannot add Controllers to Castle.Windsor in ASP.NET MVC
Asked Answered
C

1

1

Given the following setup, I have three assemblies.

Web (ASP.NET MVC 3.0 RC1)

Models

Persistence (Fluent NHibernate, Castle.Windsor)

This is my ControllerInstaller.

using System;
using System.Web.Mvc;

using Castle;
using Castle.Windsor;

using Castle.MicroKernel;
using Castle.MicroKernel.SubSystems;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;

namespace Persistence.Installers
{
    public class ControllerInstaller : IWindsorInstaller
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(
            AllTypes
                .FromAssembly(System.Reflection.Assembly.GetExecutingAssembly())
                .BasedOn<IController>()
                .Configure(c => c.Named(
                    c.Implementation.Name.ToLowerInvariant()).LifeStyle.Transient));
        }
    }
}

This is my ControllerFactory...

    using System;
    using System.Web;
    using System.Web.Mvc;
    
    namespace Persistence.Containers
    {
        /// <summary>
        /// Utilize Castle.Windsor to provide Dependency Injection for the Controller Factory
        /// </summary>
        public class WindsorControllerFactory : DefaultControllerFactory
        {
            private readonly Castle.Windsor.IWindsorContainer container;
    
            public WindsorControllerFactory()
            {
                container = WindsorContainerFactory.Current();
            }
    
            protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
            {
                return (IController)container.Resolve(controllerType);
            }
        }
    }

This is my Application_Start in the global.asax file..

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

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        // Register the Windsor Container
        ControllerBuilder.Current
            .SetControllerFactory(typeof(Persistence.Containers.WindsorControllerFactory));
    }

I am getting the error

No component for supporting the service Project.Web.Controllers.HomeController was found

at the GetControllerInstance.

So , I'm not really sure what I am doing wrong, and why I cannot get the Controllers registered.

Chlorite answered 9/12, 2010 at 23:39 Comment(0)
A
1

Your Castle Windsor setup code all belongs in your Web project. It is nothing to do with Persistence.

This is causing the problem because your ControllerInstaller is trying to register the controllers in the Persistence assembly rather than the Web assembly with the following code:

System.Reflection.Assembly.GetExecutingAssembly().

So move the IoC code to the Web project and it will find your controllers.

Annuity answered 10/12, 2010 at 0:1 Comment(15)
So I couldn't say "FromAssemblyNamed('nameofWeb.dll')" and get the same result? Is there any specific reason for it to work that way?Chlorite
@Stacey: As I wrote here it really is the applications' responsibility to configure the IoC container. It has nothing to do with the persistence layer. The persistence layer is often shared between different applications but the persistence layer should not be aware of all of the other dependencies that your applications may have.Annuity
You could technically change your code to FromAssemblyNamed("Web") to get it working, but that wouldn't be helping you understanding of how best to lay out the code in your solutionAnnuity
I had hoped to avoid putting any castle libraries in the web assembly. I guess this won't be possible. I guess I'm still not understanding the full purpose, because I thought requiring it to have the Castle .dlls would just be more coupling.Chlorite
Hrnm. Adding reference to my Web.dll didn't fix it, actually, so I guess that really does rule that out.Chlorite
There is no problem with having your Castle assemblies referenced in your Web project. In fact, the MVC apps (and console apps) that I work on are only projects that reference Castle libraries.Annuity
Did you drop the .dll part, that's not needed?Annuity
Yeah. I tried just the name of the dll that the web app generates, and it didn't work. But moreover, if my ControllerFactory is in my Web Application, How do I get to it from my Persistence Layer, where I need to install it at?Chlorite
Literally all of the classes relating to Castle go in your Web project, that includes the WindsorControllerFactory, the ContainerFactory, the ControllerInstaller, and the other installers. I put them all in a folder/namespace called Web.IoC personally so they are all together and out of the way. Your persistence assembly knows nothing about Castle at all. You setup your container in the Web project.Annuity
But to have Fluent nHibernate, I have to have references to Castle in my Persistence layer anyway ...so the persistence assembly knows all about Castle anyway. But I think I understand what you are saying.Chlorite
I see what you are saying, don't worry about referencing Castle in both Web and Persistence. It's not actually causing you any coupling problems.Annuity
No but it is causing me OCD problems. I wouldn't be overly angered if Castle.Windsor was one .dll instead of 5. This is just something I'll have to learn to live with. I need to try this and see if it DOES fix the problem, if it does, I'll post the acceptance of the answer. If not, I'll give more information so we can try to find the problem.Chlorite
Placing it in my Web Assembly did NOT solve the problem. I receive the same error. However, if I look in the Container, it has the controllers registered, but I still get the error on the GetControllerInstance call. The same error as before.Chlorite
I discovered the problem. The problem is that since I am using areas, the code you had given me was truncating their names to just the controller names. However different areas have similar controllers, and this was causing conflicts. I removed that part of the code and it runs correctly now.Chlorite
That's great Stacey. Sorry I didn't get time to investigate myself yesterday. I hope you're well on the way now to understanding how IoC works with Castle.Annuity

© 2022 - 2024 — McMap. All rights reserved.