3
votes

I have a Web Api with owin and Windsor.

Get next error:

An error has occurred.An error occurred when trying to create a controller of type 'DBManagerController'. Make sure that the controller has a parameterless public constructor.System.InvalidOperationException at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()An error has occurred.Type 'Swissphone.SolutionKit.Utilities.DbInit.DataManager.WebHost.Controllers.DBManagerController' does not have a default constructorSystem.ArgumentException at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)

It is strange, because I registrate all dependencies.

Here my startup class:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var httpContext = HttpContext.Current;
        var hibernateConfigFileName = string.Empty;
        if (httpContext != null)
        {
            hibernateConfigFileName = httpContext.Server.MapPath(Properties.Settings.Default.HibernateConfigFile);
        }
        else
        {
            throw new InvalidOperationException("When using IIS hosting, HttpContext.Current must not be NULL");
        }
                    var windsorContainer = new WindsorContainer();

        windsorContainer.Install(new ContextInstaller(), new DbInitInstaller());

        var configuration = new HttpConfiguration() { DependencyResolver = new WindsorResolver(windsorContainer) };


        configuration.Routes.MapHttpRoute("DBManager",
            "api/{controller}/{action}/{id}",
            new { id = RouteParameter.Optional });


        app.UseWebApi(configuration);
    }
}

Installers:

public class ContextInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<IUserContext>().ImplementedBy<UserContext>(),
            Component.For<ITenantContext>().ImplementedBy<TenantContext>());

    }
}


public class DbInitInstaller : IDbInitInstaller
{

    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<IDbInitManager>().ImplementedBy<DbInitManager>());
    }
}

Controller:

public class DBManagerController : ApiController
{
    private IDbInitManager _manager;

    public DBManagerController(IDbInitManager manager)
    {
       _manager = manager;
    }

    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}

Class that I cant resolve:

public class DbInitManager : IDbInitManager
{
    public DbInitManager()
    {}
}

I get error during get request to controller. Can't resolve IDbInitManager.

Does anybody have idea that is wrong and why registered dependency not resolved?

1

1 Answers

5
votes

No, you didn't register all the dependencies.

Basically, what happened is that you didn't register your controllers explicitly in your container. Windsor tries to resolve unregistered concrete types for you, but because it can't resolve it (caused by an error in your configuration), it return null. It is forced to return null, because Web API forces it to do so due to the IDependencyResolver contract. Since Windsor returns null, Web API will try to create the controller itself, but since it doesn't have a default constructor it will throw the "Make sure that the controller has a parameterless public constructor" exception. This exception message is misleading and doesn't explain the real cause.

You can add another installer for your controllers :

public class ControllersInstallers : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly()
                            .BasedOn<IHttpController>()
                            .LifestylePerWebRequest());
    }
}

Every dependency that has to be resolved from Windsor has to be explicitly registered.