Automapper - How to map object to list - automapper

ValueList model is
public class ValueList
{
[Key]
public int Id { get; set; }
public List<string> Values { get; set; }
}
Value Model is >
public Value();
[JsonProperty(PropertyName = "id")]
[Key]
public int Id { get; set; }
[JsonProperty(PropertyName = "value")]
public decimal Value { get; set; } }
CreateMap<Value, ValuesList>()
.ForMember( ???? )
I want >
ValueList [{ id, Value }, { id, Value }, { id, Value }]

CreateMap<Value,ValuesList>.ConvertUsing<ValueConverter>()
then create:
public class ValueConverter: ITypeConverter<Value,ValuesList>
{
public ValuesList Convert(Value source, ValuesList destination, ResolutionContext context)
{
// Create destination object here
return destination;
}
}

Related

EF Core with AutoMapper

I have a DTO containing properties and a Model, eg student can have more than one module and a module can be associated with more than one student. the properties are mapping fine but the Model doesn't map.
public class GetStudentByIdMapping : Profile
{
public GetStudentByIdMapping()
{
CreateMap<Student,StudentDetails>();
CreateMap<Module, StudentDetails>()
.ForPath(dest => dest.StudentModules.ModuleName, opt => opt.MapFrom(m => m.ModuleName))
.ForPath(dest => dest.StudentModules.ModuleCode, opt => opt.MapFrom(m => m.ModuleCode))
.ForPath(dest => dest.StudentModules.Description, opt => opt.MapFrom(m => m.Description))
.ReverseMap();
}
}
public async Task<StudentDetails> GetStudent(int studentId)
{
var student = context.Student
.Where(s => s.StudentId == studentId)
.FirstOrDefault();
var module = await context.Order
.Include(m => m.Module)
.Where(o => o.StudentId == studentId)
.Select(m => m.Module).ToListAsync();
var studMap = Mapper.Map<StudentDetails>(student);
Mapper.Map<StudentDetails>(module);
return studMap;
}
These are the ViewModels I want to map to the Models Model in the StudentDetails ViewModel
public class StudentDetails
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public StudentModule StudentModules { get; set; }
}
public class StudentModule
{
public string ModuleName { get; set; }
public string ModuleCode { get; set; }
public string Description { get; set; }
}
These are my Entities generated by EF Core
public partial class Student
{
public Student()
{
Order = new HashSet<Order>();
}
public int StudentId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
public partial class Module
{
public Module()
{
Order = new HashSet<Order>();
}
public int ModuleId { get; set; }
public int? LectureId { get; set; }
public string ModuleName { get; set; }
public string ModuleCode { get; set; }
public string Description { get; set; }
public string ModulePath { get; set; }
public virtual Lecture Lecture { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
You only need to pass the created destination to the second map call:
Just try the following code when mapping:
var studMap = Mapper.Map<Student,StudentDetails>(student);
Mapper.Map<Module,StudentDetails>(module,studMap);
Then the studMap will receive all mapped fields value.

Sending different entity types to same Blazor component

I have a blazor component that I want to pass data retreived from a backend. Each set of data has a different entity name so I'm having trouble converting the entity to a generic type when it gets to the component. Where is my error? Thanks
Getting the following error on ChildData=#sysList in the parent:
Argument1: Cannot convert from Test2.Shared.Models.MeasurementSystem[] to System.Collections.Generic.IReadOnlyList[]
Parent
<ChildComponent ChildData=#sysList TItem=#Test2.Shared.Models.MeasurementSystem</ChildComponent>
<ChildComponent ChildData=#unitList TItem=#Test2.Shared.Models.MeasurementUnit</ChildComponent>
<ChildComponent ChildData=#groupList TItem=#Test2.Shared.Models.MeasurementGroup</ChildComponent>
#functions {
private Test2.Shared.Models.MeasurementSystem[] sysList { get; set; }
private Test2.Shared.Models.MeasurementUnit[] unitList { get; set; }
private Test2.Shared.Models.MeasurementGroup[] groupList { get; set; }
protected override async Task OnInitAsync()
{
sysList = await Http.GetJsonAsync<Test2.Shared.Models.MeasurementSystem[]>("/api/System/Index");
unitList = await Http.GetJsonAsync<Test2.Shared.Models.MeasurementUnit[]>("/api/Unit/Index");
groupList = await Http.GetJsonAsync<Test2.Shared.Models.MeasurementGroup[]>("/api/Group/Index");
}
}
Child
#typeparam TItem
#foreach (var data in ChildData)
{
<p #data.Name>
}
#functions {
[Parameter] private IReadOnlyList<TItem>[] ChildData { get; set; }
}
Classes
public class MeasurementSystem
{
public int SystemId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
public class MeasurementUnit
{
public int UnitId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Factor { get; set; }
public int Magnitude { get; set; }
}
}
public class MeasurementGroup
{
public int GroupId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}

Automapper Object with inside list of object to primitive mapping

I'm trying to create map for automapper to let me map those entity
Entities
public class Entity
{
...
public List<NavigationEntity> Navs { get; set; }
}
public class NavigationEntity
{
public int Id { get; set; }
}
DTO that need to be create with entities
public class EntityDto
{
...
public List<int> NavIds { get; set; }
}
This doesnt seem's to do the job! What could do the job ?
CreateMap<Entity, EntityDto>().ReverseMap();
CreateMap<NavigationEntity, int>().ConstructUsing(x => x.Id);
EDIT
Tried to add
CreateMap< List < SystemsTags >, List< int >>();
but still it doesnt map
First of all, you should rename public List<NavigationEntity> Navs { get; set; } and public List<int> NavIds { get; set; } to the same name. If it is still not working try to also change ConstructUsing to ConvertUsing. And if you need the reverseMap of Entity to EntityDTO you should also add
CreateMap<int, NavigationEntity>().ConvertUsing(x => new NavigationEntity { Id = x });
final code
public class Entity
{
...
public List<NavigationEntity> Navs { get; set; }
}
public class NavigationEntity
{
public int Id { get; set; }
}
public class EntityDto
{
...
public List<int> Navs { get; set; }
}
...
CreateMap<Entity, EntityDto>().ReverseMap();
CreateMap<NavigationEntity, int>().ConvertUsing(x => x.Id);
CreateMap<int, NavigationEntity>().ConvertUsing(x => new NavigationEntity { Id = x });

Automapper fails for objects with collections where items use ConvertUsing<>()

My example:
class BoxVM {
int BoxId {get;set;}
List<ItemVM> Items {get;set;}
}
class Box {
int BoxId {get;set;}
List<Item> Items {get;set;}
}
With mapping config:
CreateMap<BoxVM, Box>();
CreateMap<ItemVM, Item>().ConvertUsing<ItemTypeConverter>();
When converting BoxVM will Items, the ItemTypeConverter is not called. Leaving an empty Items collection in Box.
The BoxId is being mapped correctly.
Am I missing a step?
Looks like it does work.
using System.Collections.Generic;
using AutoMapper;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<BoxVM, Box>();
cfg.CreateMap<ItemVM, Item>().ConvertUsing<ItemTypeConverter>();
});
Mapper.AssertConfigurationIsValid();
var boxVm = new BoxVM()
{
Value1 = "5",
Items = new List<ItemVM> { new ItemVM { Name = "Item1" } }
};
var result = Mapper.Map<BoxVM, Box>(boxVm);
Assert.AreEqual(1, result.Items.Count);
}
}
public class Box
{
public string Value1 { get; set; }
public List<Item> Items { get; set; }
}
public class Item
{
public string Name { get; set; }
}
public class BoxVM
{
public string Value1 { get; set; }
public List<ItemVM> Items { get; set; }
}
public class ItemVM
{
public string Name { get; set; }
}
public class ItemTypeConverter : ITypeConverter<ItemVM, Item>
{
public Item Convert(ItemVM source, Item destination, ResolutionContext context)
{
return new Item { Name = source.Name };
}
}

Complex collections with Automapper

Here is what I have where I hope someone can help us out:
class Source
{
string name { get; set; }
Inner { get; set; }
}
class Inner
{
Col A { get; set; }
Col B { get; set; }
}
class Col : IList<ClassX>, IEnunmerable<ClassX>
I need to map class Source to a destination type which has:
class Dest
{
string name { get; set; }
IList<ClassY> A { get; set;}
IList<ClassY> B { get; set;}
}
Now, ClassX and class ClassY share the same properties. ClassY class has a subset of the ClassX primitive properties with the exact same names and types.
Tried all kinds of mappings. Just the ClassX to ClassY map, with the collections, without and with any mapping get no mapping found between or missing configuration between Source and Dest
AutoMapper.Mapper.Map<Source, Dest>(src);
Can someone help me out with the mapping? Thanks in advance.
This question is a few months old, but if you're still looking for an answer, this is what I tried that worked:
class Source
{
public string Name { get; set; }
public Inner Inner { get; set; }
}
class Inner
{
public Col A { get; set; }
public Col B { get; set; }
}
class Col : List<ClassX> { }
class ClassX
{
public int Index { get; set; }
public string Name { get; set; }
public ClassX() : this(0, "") { }
public ClassX(int index, string name)
{
this.Index = index;
this.Name = name;
}
}
class ClassY
{
public int Index { get; set; }
public string Name { get; set; }
public ClassY() : this(0, "") { }
public ClassY(int index, string name)
{
this.Index = index;
this.Name = name;
}
}
class Dest
{
public string Name { get; set; }
public List<ClassY> A { get; set; }
public List<ClassY> B { get; set; }
}
[TestMethod]
public void ComplexTest()
{
Mapper.CreateMap<Source, Dest>()
.ForMember(dest => dest.A, config => config.MapFrom(src => src.Inner.A))
.ForMember(dest => dest.B, config => config.MapFrom(src => src.Inner.B));
Mapper.CreateMap<ClassX, ClassY>();
Source source = new Source
{
Name = "Source",
Inner = new Inner
{
A = new Col
{
new ClassX(1, "First"),
new ClassX(2, "Second"),
new ClassX(3, "Third"),
new ClassX(4, "Fourth"),
},
B = new Col
{
new ClassX(5, "Fifth"),
new ClassX(6, "Sixth"),
new ClassX(7, "Seventh"),
new ClassX(8, "Eighth"),
},
}
};
Dest destination = Mapper.Map<Source, Dest>(source);
Assert.AreEqual(source.Name, destination.Name);
Assert.AreEqual(source.Inner.A.Count, destination.A.Count);
Assert.AreEqual(source.Inner.B.Count, destination.B.Count);
Assert.AreEqual(source.Inner.A[0].Name, destination.A[0].Name);
Assert.AreEqual(source.Inner.B[0].Name, destination.B[0].Name);
}
I didn't go too in-depth with my Asserts, so there may be something I missed, but they appear to be mapped properly.

Resources