2

I am getting this exception while debugging code:

Resolution of the dependency failed, type = "Aqueduct.Interfaces.IMasterDataClient", name = "MDS".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type,
Aqueduct.Interfaces.IMasterDataClient, is an interface and cannot be constructed. Are you missing a type mapping?

At the time of the exception, the container code was:

Resolving Aqueduct.Interfaces.IMasterDataClient,MDS

Unity.config:

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();
        IUnityContainer myContainer = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();
        myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
        myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}

Web Api controller:

using (var container = new UnityContainer())
{
       container.Resolve<IMasterDataClient>("MDS");
       container.Resolve<ILinksManager>("LDS");
}

MasterDataClient Interface Implementing class:

public class MasterDataClient : HalClient, IMasterDataClient, IHalClient, ICrestaClient
{
    public MasterDataClient(IApiClient apiClient, IUriDispenser dispenser);
}
Luka Kerr
  • 4,161
  • 7
  • 39
  • 50
Hima
  • 41
  • 5

1 Answers1

2

You have three problems here.

Problem 1. You're creating a new container:

using (var container = new UnityContainer())
{
       container.Resolve<IMasterDataClient>("MDS");
       container.Resolve<ILinksManager>("LDS");
}

This container will be empty and have 0 registrations. It's not the same container as you made your registrations to. There's a couple of ways to solve it:

Problem 1 - Solution 1: Don't inject the container. Inject the dependencies. Instead of using the container you should inject your dependencies directly to your controller:

public class MyApiController : ApiController
{
    IMasterDataClient _masterDataClient;
    ILinksManager _linksManager


    public MyApiController(IMasterDataClient masterDataClient, ILinksManager linksManager)
    {
        _masterDataClient = masterDataClient;
        _linksManagerlinksManager;
    }
}

This way you can avoid the service locator-pattern and your dependency to the container itself. If you're using named registrations you may need to use the Dependency-attribute.

With Unity how do I inject a named dependency into a constructor?

Problem 1 - Solution 2: Inject your container instead of creating a new one. If you really need your controller for some reason, then you should try to inject it instead. This way you will get the same container as you used for your registrations.

public class MyApiController : ApiController
{
    IUnityContainer _container;


    public MyApiController(IUnityContainer container)
    {
        _container = container;
    }
}

Problem 1 - Solution 3: Keep an static reference to your container. As a last resort you can keep your container as a static instance.

public static class IocContainer
{
    private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        return container;
    });

    public static IUnityContainer Instance
    {
        get { return Container.Value; }
    }
}

And in your registrations:

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = IocContainer.Instance;

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();
        myContainer.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
        myContainer.RegisterType<ILinksManager, LinksManager>("LDS");
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}

Usage:

IocContainer.Instance.Resolve<IMasterDataClient>("MDS");

Problem 2. You don't seem to register the dependencies for MasterDataClient.

It has dependencies for IApiClient and IUriDispenser. They need to be registered as well.

Problem 3. You assign your dependency resolver to the wrong container

You currently create two containers - myContainer and container. You make your registrations to one container, and then use another one as DependencyResolver. You can solve it by removing myContainer and only use container. Otherwise you will not be able to use your registrations in Web Api.

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();
        container.RegisterType<IMasterDataClient, MasterDataClient>("MDS");
        container.RegisterType<ILinksManager, LinksManager>("LDS");
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }
}

Update:

I don't know implementing classes for IApiClient and IUriDispenser as it is third party dll so how can I register it

Unity needs to know which implementation to use when you resolve an interface. So somehow you need to tell Unity what implementation to use. There's an excellent answer from Mark Seemann in the question below:

Unity IoC for resolving assemblies dynamically

It scans the assembly for implementations of your interface and then registers them/it.

Alternatively you can use registration by convention, which enables you to do several registrations at once:

container.RegisterTypes(
    AllClasses.FromLoadedAssemblies(),
    WithMapping.MatchingInterface,
    WithName.Default,
    WithLifetime.ContainerControlled);

Note that this will register all implementations, including your own. If you just want the third party implementations you should be able do do something like this:

// Get the assemblies where IApiClient exists.
IEnumerable<Assembly> assemblies = AppDomain.CurrentDomain.GetAssemblies()
    .Where(x => x.GetTypes().Contains(typeof (IApiClient)));

// Register all implementations based on convention.
container.RegisterTypes(AllClasses.FromAssemblies(assemblies), 
    WithMappings.FromMatchingInterface,
    WithName.Default,
    WithLifetime.ContainerControlled); // Maybe another lifetime manager?

Update 2:

Make sure that the controller has a parameterless public constructor.

The error above can have many causes, most of them are covered in these questions:

Unable to inject DBContext into my Web API 2 Controller with Unity

Make sure that the controller has a parameterless public constructor error

error: Make sure that the controller has a parameterless public constructor webapi

Mostly it's Unity telling you that you're trying to resolve something that you didn't register. Or that you haven't registered a DependencyResolver at all.

Community
  • 1
  • 1
smoksnes
  • 10,509
  • 4
  • 49
  • 74
  • Thanks..I have done all changes and applied solution 1 for problem 1..but I am getting 500 internal server error – Hima Sep 05 '16 at 11:46
  • [Stack trace error] An error occurred when trying to create a controller of type 'WPProjectsController'. Make sure that the controller has a parameterless public constructor. Type 'WebService.Controllers.WPProjectsController' does not have a default constructor – Hima Sep 05 '16 at 11:53
  • @smoksnes-Now I found those implementing classes so I have registered them also..thanks – Hima Sep 05 '16 at 11:56
  • Do I need to add something in UnityDependencyResolver class??..Currently I haven't changed anything in this..Am I missing some dependency setting? – Hima Sep 05 '16 at 12:09
  • You need to create a `UnityDependencyResolver`. Here's an excellent post regarding setting up Unity with Web Api - http://www.asp.net/web-api/overview/advanced/dependency-injection – smoksnes Sep 05 '16 at 12:13
  • UnityDependencyResolver is automatically created while adding Unity nuget package.It contains some code by default – Hima Sep 06 '16 at 04:26