2
votes

I am in the process of integrating StructureMap into my MVC3 application. I am running into a problem where my custom ControllerFactory is throwing an exception when attempting to create a controller:

StructureMap Exception Code: 200 Could not find an Instance named "contentpage" for PluginType System.Web.Mvc.IController

Here’s what I have in the container:

Controller (System.Web.Mvc.Controller)
Scoped as: Transient

AuctionCMS.Web.Controllers.HomeController, AuctionCMS.Web, Version=1.0.0.0, Culture=neutral,

AuctionCMS.Web.Controllers.ContentPageController, AuctionCMS.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null Configured Instance of AuctionCMS.Web.Controllers.ContentPageController, AuctionCMS.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

I did notice that the controller factory is requesting “contentpage” instead of “contentpagecontroller.” Is this correct behavior? What is going wrong?

Here’s my code:

    private void InitStructureMap()
    {
        var container = new StructureMap.Container();

        DependencyResolver.SetResolver(new StructureMapContainer(container));
        ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory(container));

        PerformRuntimeDepdendencyConfiguration(container);
    }



    private void PerformRuntimeDepdendencyConfiguration(IContainer container)
    {
        container.Configure(x => x.Scan(y =>
        {
            y.TheCallingAssembly();
            y.WithDefaultConventions();
            y.LookForRegistries();
            y.AddAllTypesOf<Controller>();
        }));
    }



public class StructureMapContainer : IDependencyResolver
{
    static IContainer _container;

    public StructureMapContainer(IContainer container)
    {
        _container = container;
    }

    public object GetService(Type serviceType)
    {
        if (serviceType.IsAbstract || serviceType.IsInterface)
        {
            return _container.TryGetInstance(serviceType);
        }
        else
        {
            return _container.GetInstance(serviceType);
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
    }
}


    public class StructureMapControllerFactory : IControllerFactory
    {
        private readonly IContainer _container;

        public StructureMapControllerFactory(IContainer container)
        {
            _container = container;
        }

        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            System.Diagnostics.Debug.WriteLine(_container.WhatDoIHave()); 

            return _container.GetInstance<IController>(controllerName.ToLowerInvariant());
        }

        public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
        {
            return SessionStateBehavior.Default;
        }

        public void ReleaseController(IController controller)
        {
            return;
        }
    }

public class ApplicationRegistry : Registry
{
    public ApplicationRegistry()
    {
        ... register some types ...
    }
}
1
Have you confirmed that your controllers are picked up properly by the scan? - AlexCuse
You can see that above in the dump of the container - rboarman
Ah sorry I missed that. I don't see the name in your output but I suspect you just need to append "controller" to your controller name - could be the convention you are using isn't trimming that off. - AlexCuse
I tried that too, no go. I don't think the container is configured to look up instances by name. - rboarman
I think that using nameby should work. There's also a method on ControllerFactory that takes a type IIRC, you aren't really doing any special naming so that probably could've worked here too. - AlexCuse

1 Answers

1
votes

Like you noted in comments, your controllers aren't registered by name. Try this:

container.Configure(x => x.Scan(y =>
{
    y.TheCallingAssembly();
    y.WithDefaultConventions();
    y.LookForRegistries();
    y.AddAllTypesOf<Controller>()
         .NameBy(type => type.Name.Replace("Controller", "")
         .ToLowerInvariant());
}));