-2

I have trouble to use Unity on this project.

The error is

The current type, Business.Interfaces.IPersonnelBusiness, is an interface and cannot be constructed. Are you missing a type mapping?

I've updated the Unity to thge latest version because of stackoverflow issueand I saw that RegisterComponents has changed to lazy loaded one here is the Global asax:

protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            // Unity settings
            //UnityConfig.RegisterComponents();

            // For logging
            //SetupSemanticLoggingApplicationBlock();
        }

Here is the UnityConfig file:

public static class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container =
          new Lazy<IUnityContainer>(() =>
          {
              var container = new UnityContainer();
              RegisterTypes(container);
              return container;
          });

        /// <summary>
        /// Configured Unity Container.
        /// </summary>
        public static IUnityContainer Container
        {
            get
            {
                return container.Value;
            }
        }
        #endregion

        /// <summary>
        /// Registers the type mappings with the Unity container.
        /// </summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>
        /// There is no need to register concrete types such as controllers or
        /// API controllers (unless you want to change the defaults), as Unity
        /// allows resolving a concrete type even if it was not previously
        /// registered.
        /// </remarks>
        public static void RegisterTypes(IUnityContainer container)
        {
            // NOTE: To load from web.config uncomment the line below.
            // Make sure to add a Unity.Configuration to the using statements.
            // container.LoadConfiguration();

            // TODO: Register your type's mappings here.
            // container.RegisterType<IProductRepository, ProductRepository>();
            container = new UnityContainer();

            // Identity managment
            container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
            container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
            container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());
            container.RegisterType<AccountController>(new InjectionConstructor());
            container.RegisterType<PersonnelController>(new InjectionConstructor());
            container.RegisterType<UsersAdminController>(new InjectionConstructor());

            // Business Layer
            container.RegisterType<ILogBusiness, LogBusiness>();
            container.RegisterType<IAnomalyBusiness, AnomalyBusiness>();
            container.RegisterType<ICockpitStatBusiness, CockpitStatsBusiness>();
            container.RegisterType<IDocumentBusiness, DocumentBusiness>();
            container.RegisterType<IEmailBusiness, EmailBusiness>();
            container.RegisterType<IMessageBusiness, MessageBusiness>();
            container.RegisterType<INatureBusiness, NatureBusiness>();
            container.RegisterType<IPersonnelBusiness, PersonnelBusiness>();
            container.RegisterType<ISAPBusiness, SAPBusiness>();

            // Set resolver
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        }
    }

Thanks folks

EDIT:

here is the stack and the code where it is thrown:

StackTrace:

[ResolutionFailedException: Resolution of the dependency failed, type = 'APPI.WEB.Controllers.HomeController', name = '(none)'.
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, APPI.Business.Interfaces.IPersonnelBusiness, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was: 
  Resolving APPI.WEB.Controllers.HomeController,(none)
  Resolving parameter 'personnelRepo' of constructor APPI.WEB.Controllers.HomeController(APPI.Business.Interfaces.IPersonnelBusiness personnelRepo, APPI.Business.Interfaces.IAnomalyBusiness anomalyRepo, APPI.Business.Interfaces.IDocumentBusiness docRepo, APPI.Business.Interfaces.IMessageBusiness msgRepo, APPI.Business.Interfaces.ICockpitStatBusiness cockpitStatRepo, APPI.Business.Interfaces.INatureBusiness natureRepo)
    Resolving APPI.Business.Interfaces.IPersonnelBusiness,(none)
]

Controller:

public class HomeController : BaseController
    {

        private readonly IPersonnelBusiness _IPersonnelBusinessRepo;
        private readonly IAnomalyBusiness _IAnomalyBusinessRepo;
        private readonly IDocumentBusiness _IDocumentBusinessRepo;
        private readonly IMessageBusiness _IMessageBusinessRepo;
        private readonly ICockpitStatBusiness _ICockpitStatBusinessRepo;
        private readonly INatureBusiness _INatureBusinessRepo;

        // Unity inject references
        public HomeController(IPersonnelBusiness personnelRepo, IAnomalyBusiness anomalyRepo, IDocumentBusiness docRepo, 
            IMessageBusiness msgRepo, ICockpitStatBusiness cockpitStatRepo, INatureBusiness natureRepo)
        {
            _IPersonnelBusinessRepo = personnelRepo;
            _IAnomalyBusinessRepo = anomalyRepo;
            _IDocumentBusinessRepo = docRepo;
            _IMessageBusinessRepo = msgRepo;
            _ICockpitStatBusinessRepo = cockpitStatRepo;
            _INatureBusinessRepo = natureRepo;
        }
        public HomeController()
        {

        }

        public ActionResult Index()
        {
            return RedirectToActionPermanent("Cockpit", "Home");
        }

There is also the UnityActivator that is called before starting app thanks to

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(APPI.WEB.UnityMvcActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(APPI.WEB.UnityMvcActivator), "Shutdown")]

UnityActivator:

public static class UnityMvcActivator
{
    /// <summary>
    /// Integrates Unity when the application starts.
    /// </summary>
    public static void Start() 
    {
        FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));

        DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));

        // TODO: Uncomment if you want to use PerRequestLifetimeManager
        // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>
    /// Disposes the Unity container when the application is shut down.
    /// </summary>
    public static void Shutdown()
    {
        UnityConfig.Container.Dispose();
    }
}
clement
  • 4,204
  • 10
  • 65
  • 133
  • Show the code that throws that exception. – CodeCaster Jan 24 '18 at 15:24
  • @CodeCaster: I've updated the question in order to provide more details - sorry – clement Jan 25 '18 at 08:06
  • This probably means that `RegisterTypes()` is never called. Why did you change a working formula to `Lazy`? What happens if you call `var container = UnityConfig.Container` in your `App_Start()`, to trigger initialization? – CodeCaster Jan 25 '18 at 08:11
  • @CodeCaster thanks. I've updated the Unity package and there is no more RegisterComponents(), it uses a Lazy in UnityConfig so I just comment the call from AppStart() .When I use your code, I get the exact same error. – clement Jan 25 '18 at 08:32
  • @CodeCaster : UnityMvcActivator already calls the UnityConfig and is launched before Application_Start() (see edit) – clement Jan 25 '18 at 12:56
  • Maybe related to the fact you overwrite container passed to RegisterTypes (via `container = new UnityContainer();`) and so all types are registered in that new container, not in container that were passed to RegisterTypes. – Evk Jan 26 '18 at 15:33
  • @Evk thanks. Nope, Lazy is created as static and then it is the public Container that uses it, so it changes nothing :-/ – clement Jan 26 '18 at 16:10
  • No, you overwrite local variable named 'container', in RegisterTypes. So container returned from Lazy has no registrations in it. Try to remove first line in RegisterTypes and see if that helps. – Evk Jan 26 '18 at 16:13
  • @Evk you're rigth! – clement Jan 29 '18 at 07:53

1 Answers1

3

As pointed out in the comments, the issue is that you are instantiating 2 different containers, once in your initializer:

    private static Lazy<IUnityContainer> container =
      new Lazy<IUnityContainer>(() =>
      {
          var container = new UnityContainer(); // <-- new container here
          RegisterTypes(container);
          return container;
      });

And once in your RegisterTypes method:

    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below.
        // Make sure to add a Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your type's mappings here.
        // container.RegisterType<IProductRepository, ProductRepository>();
        container = new UnityContainer(); // <-- new container here

    ...

The type mappings are added in the RegisterTypes method to a different instance than the container you are passing in as an argument.

To make it work right, you should remove the instantiation of the container in RegisterTypes so it can use the instance that is passed in the parameter.

    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below.
        // Make sure to add a Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your type's mappings here.
        // container.RegisterType<IProductRepository, ProductRepository>();
        // container = new UnityContainer(); // <-- Remove this

    ...
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • thank you. Now I've a stackoverflow exception from Unity.Abstractions.dll but I suppose I'm moving forward – clement Jan 29 '18 at 07:53