2 months ago I have asked about this problem! and the problem still exists.
I am not going to copy/paste the same problem here because I found out that the error is not for a specific Entity-DTO mapping but for any Entity-DTO which is first in a controller.
I mean if the program flow hits to a Country-CountryDto, the error says:
Missing type map configuration or unsupported mapping.
Mapping types:
Country -> CountryDTO
MyApp.Domain.BoundedContext.Country -> MyApp.Application.BoundedContext.CountryDTO
Destination path:
List`1[0]
Source value:
MyApp.Domain.BoundedContext.Country
Or if there is an account check at first hand, the error says:
Missing type map configuration or unsupported mapping.
Mapping types:
Account -> AccountDTO
MyApp.Domain.BoundedContext.Account -> MyApp.Application.BoundedContext.AccountDTO
Destination path:
AccountDTO
Source value:
MyApp.Domain.BoundedContext.Account
I also found that the error is gone whenever I rebuild the presentation layer (in this case it is an MVC 3 project) of my N-Layer solution. And then, at a random time, it happens again.
If this problem happened only in development environment it wouldn't be a big deal but after publishing the problem was still there so I am in big trouble.
I have searched through Google, Stackoverflow, Automapper Forums/Groups with no success.
I have also tested the mappings with Mapper.AssertConfigurationIsValid() and everything was fine.
My project is an MVC 3 project with Automapper 2.2 and Unity IoC..
Again, I will appreciate any idea, advice or solution.
Edit: OK, now I have a clue.. I have a profile called ManagementProfile where all my mappings are done. In the AutomapperTypeAdapterFactory()
I have a code like:
public AutomapperTypeAdapterFactory()
{
//Scan all assemblies to find an Auto Mapper Profile
var profiles = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.BaseType == typeof(Profile));
Mapper.Initialize(cfg =>
{
foreach (var item in profiles)
{
if (item.FullName != "AutoMapper.SelfProfiler`2")
cfg.AddProfile(Activator.CreateInstance(item) as Profile);
}
});
}
I found that, normally, the profiles
variable holds ManagementProfile but sometimes it couldn't get the information and says "Enumeration yielded no results"
and I got the exception mentioned in this question.
With further investigation I see that when everything is fine the AppDomain.CurrentDomain.GetAssemblies()
loads 85 assemblies and on the other hand when I get the exception it has loaded only 41 assemblies and it was obvious that one of the missing assemblies was the one that holds the DTO mappings.
Ok, I finally figured it out. The:
AppDomain.CurrentDomain.GetAssemblies()
piece of my code sometimes does not get my mapping assembly so while it is missing I get an error. Replacing this code by forcing the app to find all assemblies solved my problem.
Thanks for your replies.
Edit: As Andrew Brown asked about the code of the solution, I realized that I have not included the source code snippet. Here is the AssemblyLocator:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Compilation;
public static class AssemblyLocator
{
private static readonly ReadOnlyCollection<Assembly> AllAssemblies;
private static readonly ReadOnlyCollection<Assembly> BinAssemblies;
static AssemblyLocator()
{
AllAssemblies = new ReadOnlyCollection<Assembly>(
BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList());
IList<Assembly> binAssemblies = new List<Assembly>();
string binFolder = HttpRuntime.AppDomainAppPath + "bin\\";
IList<string> dllFiles = Directory.GetFiles(binFolder, "*.dll",
SearchOption.TopDirectoryOnly).ToList();
foreach (string dllFile in dllFiles)
{
AssemblyName assemblyName = AssemblyName.GetAssemblyName(dllFile);
Assembly locatedAssembly = AllAssemblies.FirstOrDefault(a =>
AssemblyName.ReferenceMatchesDefinition(
a.GetName(), assemblyName));
if (locatedAssembly != null)
{
binAssemblies.Add(locatedAssembly);
}
}
BinAssemblies = new ReadOnlyCollection<Assembly>(binAssemblies);
}
public static ReadOnlyCollection<Assembly> GetAssemblies()
{
return AllAssemblies;
}
public static ReadOnlyCollection<Assembly> GetBinFolderAssemblies()
{
return BinAssemblies;
}
}
Hence, instead of using AppDomain.CurrentDomain.GetAssemblies(), I am calling the GetAssemblies() method of the provided helper class like:
//Scan all assemblies to find an Auto Mapper Profile
//var profiles = AppDomain.CurrentDomain.GetAssemblies()
// .SelectMany(a => a.GetTypes())
// .Where(t => t.BaseType == typeof(Profile));
var profiles = AssemblyLocator.GetAssemblies().
SelectMany(a => a.GetTypes()).
Where(t => t.BaseType == typeof(Profile));