Unity 3 and Error "The type name or alias "xxxxx" could not be resolved. Please check your configuration file and verify this type name."
Asked Answered
A

6

10

Is there any way to resolve this problem with Unity 3 ?

I have made all that is possible to bypass this message error, but I can't resolve; I have already did everything I've seen in googles searches.

I am almost giving up and trying another DI solution.

My configuration file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <assembly name="Biblioteca" />
    <assembly name="Biblioteca.Contracts" />
    <assembly name="Biblioteca.Business" />
    <namespace name="Biblioteca" />
    <namespace name="Biblioteca.Contracts" />
    <namespace name="Biblioteca.Business" />
      <container>
        <register type="Biblioteca.Contracts.IManterCategoriaBO" mapTo="Biblioteca.Business.ManterCategoriaBO" />
      </container>
  </unity>
</configuration>

My interface:

using Biblioteca.Transport;
using System.Linq;

namespace Biblioteca.Contracts
{
    public interface IManterCategoriaBO
    {
        IQueryable<CategoriaDTO> GetAll();
        CategoriaDTO GetById(int id);
        void Insert(CategoriaDTO dto);
    }
}

My concrete class:

using Biblioteca.Contracts;
using Biblioteca.Transport;
using Biblioteca.Data;
using System;
using System.Linq;

namespace Biblioteca.Business
{
    public class ManterCategoriaBO : IManterCategoriaBO
    {
        public CategoriaDTO GetById(int id)
        {
            CategoriaDTO dto = new CategoriaDTO();
            ManterCategoriaDO categoriaDO = new ManterCategoriaDO();

            dto = categoriaDO.GetById(1);

            return dto;
        }

        public IQueryable<CategoriaDTO> GetAll()
        {
            throw new NotImplementedException();
        }

        public void Insert(CategoriaDTO dto)
        {
            throw new NotImplementedException();
        }
    }
}

My Global.asax:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Biblioteca.Dependency;

namespace Biblioteca
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //Below is a static variable to take the unity container
            //which is on a dependency project
            Global.Container = Bootstrapper.Initialise();
        }
    }
}

My Bootstrapper class:

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Configuration;
using System.Web.Mvc;
using Unity.Mvc4;

namespace Biblioteca
{
    public static class Bootstrapper
    {
        public static IUnityContainer Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            return container;
        }

        private static IUnityContainer BuildUnityContainer()
        {
            string path = ConfigurationManager.AppSettings["UnityConfigFilePath"].ToString();

            var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = path + "\\Unity.config" };

            System.Configuration.Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

            var unitySection = (UnityConfigurationSection)configuration.GetSection("unity");

            //*** this line is firing the error !!! ****
            var container = new UnityContainer().LoadConfiguration(unitySection);

            return container;
        }
    }
}

My Dependency project static class:

using Microsoft.Practices.Unity;

namespace Biblioteca.Dependency
{
    public static class Global
    {
        public static IUnityContainer Container = null;

        public static T Resolve<T>()
        {
            return Container.Resolve<T>();
        }
    }
}

My UI model class file on MVC 4 project. I am using 4.5 framework.

using Biblioteca.Contracts;
using Biblioteca.Dependency;

namespace Biblioteca.Models
{
    public class LivroModel
    {
        public void GetAll()
        {
            if (Global.Container != null)
            {
                var categoriaBO = Global.Resolve<IManterCategoriaBO>();
                categoriaBO.GetById(1);
            }
        }
    }
}

I think everything is in the right way. But, I can´t see this DI works cause I got an error just in the mapping process, in line below on my Bootstrapper class, BuildUnityContainer method:

var container = new UnityContainer().LoadConfiguration(unitySection);

The error is:

The type name or alias Biblioteca.Contracts.IManterCategoriaBO could not be resolved. Please check your configuration file and verify this type name.

I have double checked all my classes and for me, they are ok. Or is it missing anything ?

Ashliashlie answered 6/9, 2013 at 23:55 Comment(1)
Is your assembly strongly-named? I've found that sometimes I have to use a fully qualified type name (with the public key) to get it to load via Unity config. Even with non-strongly-typed assemblies, I have had to add the assembly portion to the type name.Gerhan
X
15

The problem is in you config file. You are mixing two concepts with some incorrect syntax.

The <assembly... /> and <namespace ... /> nodes provide an assembly and namespace search order when your <register ... /> node contains a type that cannot be found by itself. If a type cannot be found, it searches through all combinations of [namespace].Type, [assembly]. Here's where the error is: it does NOT search for Type, [assembly]. If any <namespace ... /> nodes are defined, it does NOT try appending only the assembly.

So your <register type="Biblioteca.Contracts.IManterCategoriaBO" mapTo="Biblioteca.Business.ManterCategoriaBO" /> node has the type Biblioteca.Contracts.IManterCategoriaBO which does not contain the assembly, so it cannot be found. Therefore, it needs to do a search. You did specify <namespace ... /> nodes, so it will first try Biblioteca.Biblioteca.Contracts.IManterCategoriaBO, Biblioteca. Notice the duplicate Biblioteca name.

Here's a corrected config file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
  </configSections>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <assembly name="Biblioteca" />
    <assembly name="Biblioteca.Contracts" />
    <assembly name="Biblioteca.Business" />
    <namespace name="Biblioteca" />
    <namespace name="Biblioteca.Contracts" />
    <namespace name="Biblioteca.Business" />
    <container>
      <register type="IManterCategoriaBO" mapTo="ManterCategoriaBO" />
      <!-- Or this works -->
      <!--<register type="Biblioteca.Contracts.IManterCategoriaBO, Biblioteca" mapTo="Biblioteca.Business.ManterCategoriaBO, Biblioteca" />-->
    </container>
  </unity>
</configuration>
Xanthous answered 7/9, 2013 at 8:14 Comment(6)
Documentation on this feature can be found in this help file under Configuring Unity -> Design-Time Configuration -> Specifying Types in the Configuration File -> Automatic Type Lookup.Xanthous
Hi Tyler, no way... I did what you´ve said. But the problem persists.Ashliashlie
I was able to reproduce the error and fix it with what I've said here. Not sure why it wouldnt work for you. It doesn't work with the assembly qualified name either? <register type="Biblioteca.Contracts.IManterCategoriaBO, Biblioteca" mapTo="Biblioteca.Business.ManterCategoriaBO, Biblioteca" />Xanthous
Thank you. Also, i found Biblioteca can be dropped if everything is within the structure Bibioteca.[anything]. Do you think it would be better to use the Register Type over adding the assemblies? I feel like i would take a "hit" by scanning all those assemblies.Svensen
It's going to depend on your specific situation. If you need granular control over each type's lifetime, then registering individual types would be better. If you have a monolithic assembly that has thousands of types and you only use Unity for a few, then registering individual types would be better.Xanthous
As for the performance hit, you can measure it with Stopwatch, but I would be surprised if it amounted to much. If you can get away with registering all types, then I would. Less granular configuration will save you maintenance issues.Xanthous
A
4

A little information that nobody nowhere says is that I need to make reference to all the projects that will be used by unity.

So, in my solution, inside my Biblioteca web project, it was necessary to reference Biblioteca.Business and Biblioteca.Contracts to be able to pass throught the unity register without any error. I was referencing only the last one.

It´s is incredible, but that was my problem !!! I´ve thought the unity was able to make some kind of refletion using all the paths included inside my unity.config file. But I was wrong. To make Unity works, its necessary to reference all the projects that are inside the unity.config file. If I point to some namespace, the related project need to be referenced.

I have already resolved the problem, but I do not agree with this approach to make unity works. But, anyway, its working now !!!

Thanks any way Tyler, for your support.

Ashliashlie answered 10/9, 2013 at 15:20 Comment(2)
You don't need a hard reference to your other assemblies. They just need to be loaded in the current app domain. If you want it to be more dynamic, you could write your own code that uses reflection to load your required assemblies into the app domain with a call to Assembly.Load("Biblioteca.Business") and Assembly.Load("Biblioteca.Contracts") before you call to UnityContainer.LoadConfiguration(...).Xanthous
Referencing isn't required, if you manually copy the DLLs into the bin folder that will work too. An example is I have one generic app that polls using whatever implementation I give it, that is, I stick the right DLL in the bin directory and configure the app to use that DLL. There's no need to load the DLL in code, the Unity config (assembly) section does that. The only code required is to create a new UnityContainer, call LoadConfiguration then Resolve the interface.Orelie
X
2

As stated in the previous comment, you could do the reflection assembly load yourself before calling UnityContainer.LoadConfiguration(...). Here's a generic way to do so.

Just be sure your assemblies can be found by name. This can be done by placing the assembly in your application's bin directory. Or add a <probing> path to your app config. Or add them to the Global Assembly Cache (GAC), but I don't recommend this.

private static void LoadDependencyAssemblies() 
{
    UnityConfigurationSection section = ConfigurationManager.GetSection(UnityConfigurationSection.SectionName) as UnityConfigurationSection;
    if (section == null)
    {
        throw new ConfigurationErrorsException("Unable to locate Unity configuration section.");
    }

    foreach (string assemblyName in section.Assemblies.Select(element => element.Name))
    {
        try
        {
            Assembly.Load(assemblyName);
        }
        catch (Exception ex)
        {
            throw new ConfigurationErrorsException("Unable to load required assembly specified in Unity configuration section.  Assembly: " + assembly, ex);
        }
    }
}
Xanthous answered 19/9, 2013 at 2:46 Comment(2)
I need to load assembly of project in my solution, that placed in folder <SolutionDir>/Main/Libraries from code of another solution project, placed in <SolutionDir>/Shop? Can you describe in your answer how to use <probing> for it?Keldah
I'm assuming you mean <BinDir> instead of <SolutionDir>. I should be able to use something like this: <probing privatePath="bin;..\main\libraries"/>Xanthous
J
2

If you're here from google, the simplest way to get it working is to remove the <alias> and <namespace> stuff and do the following.

<container>
  <register type="MyApp.Repositories.IUserRepository, MyApp" mapTo="MyApp.Repositories.UserRepository, MyApp" />
</container>

...where MyApp is your Assembly Name from project Properties -> Application.

Jessen answered 23/5, 2016 at 15:31 Comment(0)
S
1

I just spend a good portion of my day troubleshooting this error.

In my case there was no error in the configuration, but it turned out that one of the assemblies holding the concrete types was depending on another assembly that it could not find.

Unfortunately, Unity did not hint at any issues loading the assembly. In fact, the assembly showed up in the Modules window in the Visual Studio Debugger. Still the type could not be loaded.

Snapper answered 3/6, 2015 at 21:57 Comment(0)
W
1

I was receiving this error message as well but found another set of causes :

  1. I am using a WiX installer which was not properly deploying some of the dlls required for the target assembly (In this example it would be dependencies of the Biblioteca.Business). So double check that.
  2. I was then getting the error message only when running in release mode, debug mode worked fine. Turns out the target mapTo class was not marked with "public" attribute. For some reason this did not matter in debug mode but is a blocker in release mode.

Hope that helps someone since it blocked me for two days.

Wiley answered 29/11, 2016 at 20:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.