AutoMapper Custom Collections - automapper

I am getting an AutoMapper Exception when i try to Map my DomainModel to ViewModel,
Here is my Domain Model Class,
public class Source{
public string Name {get;set;}
..............
public CustomCollection EmpDetails {get;set;}
}
public class CustomCollection:CollectionBase,IEnumerable<ClassA> {
public CustomCollection{}
public int Add(ClassA classA)
{
return List.Add(classA);
}
..........
}
public class ClassA{
public string EmpNumber {get;set;}
public string EmpName {get;set;}
public string Designation {get;set;}
}
Here is my ViewModel
public class SourceDTO{
public string Name {get;set;}
public IList<EmpDTO> EmpDetails {get;set;}
}
public class EmpDTO{
public string EmpNumber {get;set;}
public string EmpName {get;set;}
public string Designation {get;set;}
}
Here is my AutoMapper Code,
AutoMapper.Mapper.CreateMap<Source, SourceDTO>()
.ForMember(x => x.EmpDetails, y => y.MapFrom(src => src.EmpDetails));
I am getting error here, It doesn't say any detail inner exceptions,
I hope someone can help us out.

You need to include a mapping to go from ClassA to EmpDTO:
Mapper.CreateMap<ClassA, EmpDTO>();
And you should be all set.

Related

How to configure map of List attribute in AutoMapper?

I'm pretty newbie to AutoMapper. I have four classes:
public class Source
{
public int Id {get;set;}
public List<SourceItem> items {get;set;}
}
public class SourceItem
{
public int Id {get;set;}
public string firstName {get;set;}
public string lastName {get;set;}
}
public class Destination
{
public int Id {get;set;}
public List<SourceItemDestination> items {get;set;}
}
public class SourceItemDestination
{
public int Id {get;set;}
public string firstName {get;set;}
}
Is it possible to create a mapping profile to map Source to Destination allowing to bring the list of SourceItemDestination when performing mapper.Map?
Done! Here are my classes:
using AutoMapper;
using AutoMapper.EquivalencyExpression;
using Infrastructure.Data.Context;
using Microsoft.Extensions.DependencyInjection;
using System;
using WebAPI.AutoMapper;
namespace WebAPI.Configurations
{
public static class AutoMapperConfig
{
public static void AddAutoMapperConfiguration(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
services.AddAutoMapper((serviceProvider, automapper) =>
{
automapper.AddCollectionMappers();
automapper.UseEntityFrameworkCoreModel<CellLabDbContext>(serviceProvider);
}, typeof(MappingProfile).Assembly);
}
}
}
using ApplicationCore.Domain;
using AutoMapper;
namespace WebAPI.AutoMapper
{
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<SourceItem, SourceItemDestination>().ReverseMap();
CreateMap<Source, Destination>().ReverseMap();
}
}
}
Important tip: I had problems when mapping the lists because the property items of Source class were read only:
public class Source
{
public int Id {get;set;}
public List<SourceItem> items {get;}
}
By doing this the mapper does not map the list. However, it does not raise any error or warning.

why doesn't work correctly to fetch child data from parent(root) object in EFCore by DDD-aggregation pattern via customize DbContext and Repository

I have Biller, BillerReference, BillerSetting DbSet.
BillerReference and BillerSetting has BillerId as foreign key relation.
This is Biller.cs
public class Biller : FullAuditedEntity
{
[Required]
public virtual string Name {get;set;}
public virtual decimal? Amount {get;set;}
public virtual List<BillerReference> BillerReferences {get;set;}
public virtual List<BillerSetting> BillerSettings {get;set;}
}
BillerReference.cs
public class BillerReference : FullAuditedEntity
{
[Required]
public virtual int? BillerId {get;set;}
[Required]
public virtual string Key {get;set;}
[Required]
public virtual string Value {get;set;}
}
BillerSetting.cs
public class BillerSetting : FullAuditedEntity
{
[Required]
public virtual int? BillerId {get;set;}
[Required]
public virtual string Name {get;set;}
[Required]
public virtual string URL {get;set;}
}
And then, I created BillerDbContext, which also include the BillerReference DbSet and BillerSetting DbSet.
And then, I created BillerRepository.
And then, I created BillerServiceAppService class in Application Layer.
When I call GetBiller(int Id) function as below
public async Task<BillerForEdit> GetBiller(int Id)
{
var biller = _billerRepo.GetAll()
.Include(x => x.BillerReferences)
.Include(x => x.BillerSettings)
.where(x => x.Id==Id);
//convert and assign data by ObjectMapper here !
//but, when got Biller object, BillerReferences and BillerSettings are Count=0!
In above function, I got Biller, but this is no BillerReferences and BillerSetting.
Please help me :D
It seems like your GetAll function gets all by using something like context.Billers.ToList(). The two list runs a select query and calls the data. Running include after this will not connect to the database to fetch your BillerReferences or BillerSetting.
Based on your usage, your easiest solution is implementing your GetAll class like this:
public IQueryable<Billing> GetAll() => context.Billers;

How to map an object to a another object with some properties in a child object

Can any one suggest to me where i made the mistake?
public class DataModelProduct
{
public int Id {get;set;}
public string Name {get;set;}
public string Price {get;set;};
public string Brand {get;set;}
public string Color {get;set;}
public string Dimentions {get;set;}
public string Type {get;set;}
public string Network {get;set;}
}
public class Product
{
public int Id {get;set;}
public string Name {get;set;}
public string Price {get;set;}
public Specification Spec {get;set;}
}
public class Specification
{
public string Brand {get;set;}
public string Color {get;set;}
public string Dimentions {get;set;}
public string Type {get;set;}
public string Network {get;set;}
}
AutoMapper.Mapper.CreateMap< DataModelProduct, Product>();
AutoMapper.Mapper.CreateMap< DataModelProduct, Specification>();
You can assume Product class is Core Model and DataModelProduct is a Database Model
The Product properties are mapped but the Specification property is null.
You need to give all your properties accessors for AutoMapper to function:
e.g.
public string Brand { get; set; }
public Specification Spec { get; set; }
And your mapping init code should be something like
var config = new MapperConfiguration(cfg => {
cfg.CreateMap< DataModelProduct, Product>();
cfg.CreateMap< DataModelProduct, Specification>();
});
And your runtime code like:
var product = Mapper.Map(dataModelProduct, new Product());
And the mapping to Specification:
var product = Mapper.Map(dataModelProduct, new Product());
product.Specification = new Specification();
Mapper.Map(dataModelProduct, product.Specification);

AutoMapper ignoring IsSourceValueNull when using ForAllMembers

I have the latest 3.1.1 version of AutoMapper. For some reason the IsSourceValueNull when using ForAllMemebers doesn't seem to work or I am expecting a different result:
Here is an example of what I am trying to do. Please refrain from commenting on the DTOs looking exactly like the Entities. This is just an example of what I am running into with a more complex model.
public class User{
public int Id {get;set;}
public string UserName {get;set;}
public virtual int? ContactId {get;set;} //Foreign Key to contact object
public virtual Contact Contact {get;set;}
}
public class Contact {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
public class UserDto {
public int Id {get;set;}
public string UserName {get;set;}
public int? ContactId {get;set;} //Foreign Key to contact object
public ContactDto Contact {get;set;}
}
public class ContactDto {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
The code for the mapping looks something like this:
AutoMapper.Mapper.CreateMap<User,UserDto>().ForAllMembers(u => u.Condition(s => !s.IsSourceValueNull));
AutoMapper.Mapper.CreateMap<Contact,ContactDto>();
I am getting an error that the Source Value cannot be null. Meaning, the Contact is null coming back from the DB, which is OK, but AutoMapper is not running the condition for the Cotnact or ContactId. Both can be null in the DB. I have had to resort to checking if the source is null inside a ForMember block.

Flat object to nested objects in Automapper

I use Automapper all the time, and for some reason the issue is escaping me. Below is an example of the code I'm using (names have been changed.)
Problem
All objects are mapped but the Keys object.
Code
I have a flat object coming from a WCF service.
public class FlatDTO
{
public string Key1 {get;set;}
public string Key2 {get;set;}
public string Name {get;set;}
public DateTime Date {get;set;}
}
This is the structure for my Business Object:
public class BaseModel
{
public Datetime Date{get;set;}
}
public class Keys
{
public string Key1 {get;set;}
public string Key2 {get;set;}
}
public class Summary : BaseModel
{
public Keys List {get;set;}
public string Name{get;set;}
public Summary ()
{
List = new Keys();
}
}
Below is my profile for Automapper (the init of the profile is done in the global.aspx page)
internal class MapDTO : Profile
{
protected override void configure()
{
Mapper.CreateMap<FlatDTO,BaseModel>().IgnoreAllNonExisting();
Mapper.CreateMap<FlatDTO,Role>().IgnoreAllNonExisting();
Mapper.CreateMap<FlatDTO,Summary>().IgnoreAllNonExisting();
}
Help with this 'simple' issue would be great.

Resources