views:

470

answers:

3

FIXED: I'm leaving this in case some other Joe Schmo needs it.

In the controller factory you need to register the controller so that it can be found when called. container.Kernel.AddComponent("ExternalResources", typeof(InteSoft.Web.ExternalResourceLoader.ExternalResourceController), LifestyleType.Transient); Do it like so:

// Instantiate a container, taking configuration from web.config
        container = new WindsorContainer(
        new XmlInterpreter(new ConfigResource("castle"))
        );
        // Also register all the controller types as transient
        var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                              where typeof(IController).IsAssignableFrom(t)
                              select t;

        foreach (Type t in controllerTypes)
            container.AddComponentWithLifestyle(t.FullName, t,
            LifestyleType.Transient);

        // Register controllers in external assemblies
        container.Kernel.AddComponent("ExternalResources", typeof(InteSoft.Web.ExternalResourceLoader.ExternalResourceController), LifestyleType.Transient);

I am using the MVC Resource loader to compress and minify my CSS and JS. I am also using the WindsorControllerFactory for dependency injection. MVC REsource loader uses a controller that is located in the InteSoft.Web.ExternalResourceLoader namespace which is in a seperate assembly.

The problem seems to be that Castle can't find (and resolve) that controller because it is in a different assembly. I'm pretty new to DI and Castle so I'm not sure where to even start.

Castle Config File

<component id="MVCResourceLoader"
             service="System.Web.Mvc.ITempDataProvider, System.Web.Mvc"
             type="InteSoft.Web.ExternalResourceLoader.NullTempDataProvider, InteSoft.Web.ExternalResourceLoader"
             lifestyle="PerWebRequest">           
</component>

Windsor Controller Factory

public class WindsorControllerFactory : DefaultControllerFactory
{
    WindsorContainer container;
    // The constructor:
    // 1. Sets up a new IoC container
    // 2. Registers all components specified in web.config
    // 3. Registers all controller types as components
    public WindsorControllerFactory()
    {
        // Instantiate a container, taking configuration from web.config
        container = new WindsorContainer(
        new XmlInterpreter(new ConfigResource("castle"))
        );
        // Also register all the controller types as transient
        var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
                              where typeof(IController).IsAssignableFrom(t)
                              select t;

        foreach (Type t in controllerTypes)
            container.AddComponentWithLifestyle(t.FullName, t,
            LifestyleType.Transient);

    }
    // Constructs the controller instance needed to service each request
    protected override IController GetControllerInstance(Type controllerType)
    {
        return (IController)container.Resolve(controllerType);
    }
}

Error Page

    Server Error in '/' Application.
The type name InteSoft.Web.ExternalResourceLoader.NullTempDataProvider, InteSoft.Web.ExternalResourceLoader could not be located
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Configuration.ConfigurationErrorsException: The type name InteSoft.Web.ExternalResourceLoader.NullTempDataProvider, InteSoft.Web.ExternalResourceLoader could not be located

Source Error:

Line 23:         {
Line 24:             // Instantiate a container, taking configuration from web.config
Line 25:             container = new WindsorContainer(
Line 26:             new XmlInterpreter(new ConfigResource("castle"))
Line 27:             );


Source File: C:\Projects\CaseLogger Pro\CaseLogger.Website\WindsorControllerFactory.cs    Line: 25

Stack Trace:

[ConfigurationErrorsException: The type name InteSoft.Web.ExternalResourceLoader.NullTempDataProvider, InteSoft.Web.ExternalResourceLoader could not be located]
   Castle.Windsor.Installer.DefaultComponentInstaller.ObtainType(String typeName) +81
   Castle.Windsor.Installer.DefaultComponentInstaller.SetUpComponents(IConfiguration[] configurations, IWindsorContainer container) +132
   Castle.Windsor.Installer.DefaultComponentInstaller.SetUp(IWindsorContainer container, IConfigurationStore store) +66
   Castle.Windsor.WindsorContainer.RunInstaller() +35
   Castle.Windsor.WindsorContainer..ctor(IConfigurationInterpreter interpreter) +60
   CaseLogger.Website.WindsorControllerFactory..ctor() in C:\Projects\CaseLogger Pro\CaseLogger.Website\WindsorControllerFactory.cs:25
   CaseLogger.MvcApplication.Application_Start() in C:\Projects\CaseLogger Pro\CaseLogger.Website\Global.asax.cs:50


Version Information: Microsoft .NET Framework Version:2.0.50727.3082; ASP.NET Version:2.0.50727.3082

Please let me know if I need to provide more debug info.

UPDATE If I access the url directly it returns the compressed files e.g. http://localhost:3826/Shared/ExternalResource?name=MinScript&amp;version=20080811&amp;display=Show

A: 

Most likely the assembly where NullTempDataProvider lives is InteSoft.Web and not InteSoft.Web.ExternalResourceLoader. If that's the case the registration should be:

<component id="MVCResourceLoader"
             service="System.Web.Mvc.ITempDataProvider, System.Web.Mvc"
             type="InteSoft.Web.ExternalResourceLoader.NullTempDataProvider, InteSoft.Web"
             lifestyle="PerWebRequest">           
</component>
Mauricio Scheffer
A: 

I don't think you will be able to get services in external assebmly by calling Assembly.GetExecutingAssembly().GetTypes().

Try to use Assembly.LoadFrom("Assembly_Name") and then register the component with "ExternalResources"

Kaleem
A: 

Fyi, here's my ControllerFactory using Castle:

http://stackoverflow.com/questions/1598421/why-is-castle-windsor-trying-to-resolve-my-content-and-scripts-folder-as-a-co/1598479#1598479

Note that I am using Assembly.GetCallingAssembly().GetTypes(), since my custom ControllerFactory lives in a seperate assembly. If you are placing it in the main mvc project, change it to get GetExecutingAssembly().

eduncan911