I want to automap from a model to a viewmodel through. My viewmodel looks like this, the model (FooBarRecord
) has few extra attributes, the bar
attribute is the same:
public class FooBarVm
{
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public id barbaz_id { get; set; }
public string barbaz_name { get; set; }
}
public class FooBarRecord
{
public int id { get; set; }
public BarRecord bar { get; set; }
public string foo { get; set; }
public int foo2 { get; set; }
public BarBazRecord barbaz { get; set; }
}
public class BarRecord
{
public int id { get; set; }
public BarBazRecord baz { get; set; }
public string bar1 { get; set; }
public int bar2 { get; set; }
}
public class BarBazRecord
{
public int id { get; set; }
public string name { get; set; }
}
The problem is in the bar column. My automapper configuration looks like this:
Mapper.CreateMap<FooBarRecord, FooBarVm>()
.ForMember(s => s.bar, m => m.MapFrom(rec => rec.bar))
//other columns - those are OK
;
I also tried few other ways, like defining a mapping from BarRecord
to BarRecord
, or substitution of rec
for rec.bar
and mapping from FooBarRecord
to BarRecord
. The only solution I found to work is flattening the BarRecord
, adding all its attributes to the FooBarVm
instead of a single reference - but that's ugly and hard to maintain, definitely not what I want.
EDIT: the classes are just examples, real ones have more attributes, but I've checked they are OK. What might play some role is that among BarRecord
's attributes there is one object, so I added it as BarBazRecord
.
The error message is following:
The following 4 properties on Foo.Bar.ViewModels.FooBarVm are not mapped:
bar1
bar2
id
name
Those are all non-object attributes of BarRecord
and BarBazRecord
. I tried to resolve them like this:
.ForMember(s => s.bar.bar1, m => m.MapFrom(rec => rec.bar.bar1))
or even ignore them:
.ForMember(s => s.bar.bar1, opt => opt.Ignore())
but the error message just changed to "System.ArgumentException: Expression 's => s.poskytovatel.ulice' must resolve to top-level member." The only solution I confirmed to work is to add the whole list from the first error message (tens of attributes in my real situation) just to have to change code like from bar = vm.bar;
to bar = GetBar(vm.bar_id);
This is a workaround, but I would prefer to learn a proper solution.
EDIT2: even the workaround fails :-( No matter what I do, my first error is still there. I changed bar
to bar_id
add all the BarRecord
attributes to FooBarVm
. Then I tried to map the new attributes (m.MapFrom(rec => rec.bar.bar1)
) or to ignore them (opt => opt.Ignore()
), or even to remove any reference to BarRecord
from FooBarVm
and the automapper configuration. Nothing changed - all the attributes not directly present in FooBarRecord
are listed as not mapped, even if ignored or mapped from nested models. Adding dummy attributes to FooBarRecord
is clearly not the right way, though it's the only way that proved to affect the error message, except for overlaying it with other errors.
I updated the models - BarBazRecord
is referenced from FooBarRecord
as well, and FooBarVm
contains attributes mapped from BarBazRecord
. These attributes seem mapped properly, they are not contained in the list o unmapped properties. That's even weirder.