Mapping multi-level nestingobjects using automapper - c#

I have dto object:
public class SwivelInfoToViewDTO
{
public ResponseValue Value { get; set; }
public List<ResponseDocument> Documents { get; set; }
public string Status { get; set; }
}
public class ResponseValue
{
public string SerialNumber { get; set; }
public string ProductCode { get; set; }
public string ProductName { get; set; }
}
public class ResponseDocument
{
public string Language { get; set; }
public int DocumentTypeId { get; set; }
public string DocumentType { get; set; }
}
And i have my sorce class:
public class SwivelInformationResponse
{
public ResponseValue Value { get; set; }
public string Status { get; set; }
}
public class ResponseValue
{
[JsonProperty("serial_number")]
public string SerialNumber { get; set; }
[JsonProperty("product_code")]
public string ProductCode { get; set; }
public List<ResponseDocument> Documents { get; set; }
}
public class ResponseDocument
{
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("document_type_id")]
public int DocumentTypeId { get; set; }
[JsonProperty("document_type")]
public string DocumentType { get; set; }
}
I use auto-mapper and my profile looks like this:
public MappingProfile()
{
CreateMap<SwivelInformationResponse, SwivelInfoToViewDTO>()
.ForMember(x => x.Value, s => s.MapFrom(src => src.Value))
.ForMember(x => x.Documents, s => s.MapFrom(src => src.Value.Documents));
}
But somehow I get an error:
Error mapping types.
Destination Member:
Value
How do I make bindings correctly?

You forgot to map your ResponseValue and ResponseDocument classes. It's not the same classes so you need to map them as well.
public MappingProfile()
{
CreateMap<SourceNamespace.ResponseValue, DtoNamespace.ResponseValue>();
CreateMap<SourceNamespace.ResponseDocument, DtoNamespace.ResponseDocument>();
}

Related

Querying Repository with inheritance

I am using code first approach with Entity Framework 6. Three of my model classes implements inheritance and each of these model has collection which also implement inheritance. I am using TPH inheritance strategy. Everything works fine and I can insert/update with no problem at all. However, I get when I try to read data from the repo. The I get is shown below.
I have include my models, entity configuration and the line that throws this exception:
The include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the select operator for collection navigation properties
Code:
public abstract class OrderSup
{
public OrderSup()
{
DetailOrderSups = new HashSet<DetailOrderSup>();
}
public int Id { get; set; }
public string Description { get; set; }
public decimal AmountPaid { get; set; }
public DateTime DateEntered { get; set; }
public string CusSupCode { get; set; }
public decimal NetAmount { get; set; }
public decimal TaxAmount { get; set; }
public string DespatchSatus { get; set; }
public string Reference { get; set; }
}
public abstract class DetailOrderSup
{
[Key, Column(Order = 0)]
public virtual int OrderId { get; set; }
[Key, Column(Order = 1)]
public virtual int ProductId { get; set; }
public virtual Product OrderedProducts { get; set; }
public InvoiceType InvoiceType { get; set; }
public virtual OrderSup OrderSup { get; set; }
}
public class Order : OrderSup
{
public int SalesOrderNumber { get; set; }
public InvoiceType InvoiceType { get; set; }
}
public class PurchaseOrder : OrderSup
{
public string OrderStatus { get; set; }
//public string AlocationStatus { get; set; }
public int InvoiceNumber { get; set; }
}
public class PurchaseOrderDetails : DetailOrderSup
{
public bool IsOrderPaid { get; set; }
public decimal Outstanding { get; set; }
public decimal AmountPaid { get; set; }
public bool IsDisputed { get; set; }
}
public class OrderDetails: DetailOrderSup
{
public bool IsOrderPaid { get; set; }
public decimal Outstanding { get; set; }
}
public IEnumerable<PurchaseOrder> GetPurchaseOrders()
{
// THIS IS LINE THAT THROWS EXCEPTION
return this.AppContext.Orders.OfType<PurchaseOrder>()
.Include(o => o.DetailOrderSups.OfType<PurchaseOrderDetails>());
}
class OrderSupConfiguration : EntityTypeConfiguration<OrderSup>
{
public OrderSupConfiguration()
{
HasMany(p => p.DetailOrderSups)
.WithRequired(o => o.OrderSup)
.HasForeignKey(o => o.OrderId);
}
}
Please what am I doing wrong?
Thanks in advance for your assistance

Automapper missing type map configuration

I can't seem to figure out what is going wrong here, I have configured AutoMapper as follows
services.AddAutoMapper(typeof(MetingenView), typeof(Meting));
And in the controller like this:
public MetingenController(IMapper mapper)
{
this._mapper = mapper;
}
After, I use it like this:
var entity = await this.Context.MetingenView.AsNoTracking().FirstOrDefaultAsync(g =>g.IdMeting == key);
if (entity == null)
{
return NotFound();
}
data.Patch(entity);
var meting = await this.Context.Meting.FirstOrDefaultAsync(m => m.IdMeting == key);
this._mapper.Map(entity, meting);
Then the error rolls out:
AutoMapper.AutoMapperMappingException: Missing type map configuration
or unsupported mapping.
EDIT:
Here are the Meting, and MetingenView classes:
public partial class Meting
{
public int IdMeting { get; set; }
public int IdKoeling { get; set; }
public int IdWerknemer { get; set; }
public int IdGebouw { get; set; }
public int Temperatuur { get; set; }
public DateTime AfgenomenTijd { get; set; }
public string ProductNaam { get; set; }
public string Actie { get; set; }
public DateTime? DatumOntstaan { get; set; }
public DateTime? DatumMutatie { get; set; }
public int IndVerwijderd { get; set; }
public DateTime? DatumVerwijderd { get; set; }
public virtual Gebouw IdGebouwNavigation { get; set; }
public virtual Koeling IdKoelingNavigation { get; set; }
public virtual Werknemer IdWerknemerNavigation { get; set; }
}
public partial class MetingenView
{
[Key]
public int IdKlant { get; set; }
public string Locatie { get; set; }
public string SoortKoeling { get; set; }
public int IdMeting { get; set; }
public int IdKoeling { get; set; }
public int IdWerknemer { get; set; }
public int IdGebouw { get; set; }
public int Temperatuur { get; set; }
public string Actie { get; set; }
public string ProductNaam { get; set; }
public DateTime AfgenomenTijd { get; set; }
}
I think the mapping between Meting and MetingenView is not configured in AutoMapper. If you use Asp.Net Core, you could create a profile.
public class MetingProfile : Profile
{
public MetingProfile()
{
CreateMap<MetingenView, Meting>();
}
}
This would create a default mapping that two types have the same property. If you want to config property mapping manually, Function ForMember() would be used.
For example, if you wish that the property MetingenView.IdGebouw maps Meting.IndVerwijderd, you can code this:
CreateMap<MetingenView, Meting>()
.ForMember(dest=>dest.IdGebouw, opt=>opt.MapFrom(src=>src.IndVerwijderd));

Entity Framework Core - Mapping many-to-many with AutoMapper

I'm unable to create correct mappings between DAO and DTO objects with many-to-many relations using AutoMapper.
Now I could map these many-to-many properties but the other ones were null.
What is the correct mapping? I see that models' attributes have the same name and type.
Also I'm trying to create the mapping between the parent models "ClaseFabricante" and "ClaseConstructor". Should I make it with the child ones which are many-to-many related "ReferenciaFabricante" and "ReferenciaConstructor" with ForMember()?
Entities:
[Table("ReferenciasFabricante", Schema = "public")]
public class ReferenciaFabricante
{
public string NombreFabricante { get; set; }
public string RefFabricanteIA { get; set; }
[InverseProperty("ReferenciaFabricante")]
public virtual ClaseFabricante Clase { get; set; }
[InverseProperty("ReferenciaFabricante")]
public virtual IList<ReferenciaFabricanteTieneReferenciaConstructor> MontaReferenciasConstructor { get; set; }
}
[Table("ReferenciasConstructor", Schema = "public")]
public class ReferenciaConstructor
{
public string Referencia { get; set; }
public string NombreConstructor { get; set; }
[InverseProperty("ReferenciaConstructor")]
public virtual ClaseConstructor Clase { get; set; }
[InverseProperty("ReferenciaConstructor")]
public virtual IList<ReferenciaFabricanteTieneReferenciaConstructor> MontadaPorReferenciasFabricante { get; set; }
}
[Table("ReferenciaFabricanteTieneReferenciaConstructor", Schema = "public")]
public class ReferenciaFabricanteTieneReferenciaConstructor {
[Key]
public int IdReferenciaFabricante { get; set; }
[ForeignKey("IdReferenciaFabricante")]
public ReferenciaFabricante ReferenciaFabricante { get; set; }
[Key]
public int IdReferenciaConstructor { get; set; }
[ForeignKey("IdReferenciaConstructor")]
public ReferenciaConstructor ReferenciaConstructor { get; set; }
}
[Table("ClasesFabricante", Schema = "public")]
public class ClaseFabricante
{
public int? IdReferenciaFabricante { get; set; }
[ForeignKey("IdReferenciaFabricante")]
public ReferenciaFabricante ReferenciaFabricante { get; set; }
}
[Table("ClasesConstructor", Schema = "public")]
public class ClaseConstructor
{
public int? IdReferenciaConstructor { get; set; }
[ForeignKey("IdReferenciaConstructor")]
public ReferenciaConstructor ReferenciaConstructor { get; set; }
}
ViewModels:
public class ReferenciaFabricante {
public string NombreFabricante { get; set; }
public string RefFabricanteIA { get; set; }
public virtual ClaseFabricante Clase { get; set; }
public virtual IList<ReferenciaConstructor> ReferenciasConstructor { get; set; }
}
public class ReferenciaConstructor {
public string Referencia { get; set; }
public string NombreConstructor { get; set; }
public virtual ClaseConstructor Clase { get; set; }
public virtual IList<ReferenciaFabricante> ReferenciasFabricante { get; set; }
}
public class ClaseFabricante {
public ReferenciaFabricante ReferenciaFabricante { get; set; }
}
public class ClaseConstructor {
public ReferenciaConstructor ReferenciaConstructor { get; set; }
}
Mapper initialization:
Mapper.Initialize((config) => {
config.CreateMap<ApplicationCore.Entities.ReferenciaFabricante, ApplicationCore.ViewModels.ReferenciaFabricante>()
;
config.CreateMap<ApplicationCore.Entities.ReferenciaConstructor, ApplicationCore.ViewModels.ReferenciaConstructor>()
;
config.CreateMap<ApplicationCore.Entities.ClaseFabricante, ApplicationCore.ViewModels.ClaseFabricante>()
.ForPath(dto => dto.ReferenciaFabricante.ReferenciasConstructor, opt => opt.MapFrom(x => x.ReferenciaFabricante.MontaReferenciasConstructor.Select(y => y.ReferenciaConstructor).ToList()))
.ForPath(dto => dto.ReferenciaFabricante.VersionesVehiculo, opt => opt.MapFrom(x => x.ReferenciaFabricante.MontaVersionesVehiculo.Select(y => y.VersionVehiculo).ToList()))
;
config.CreateMap<ApplicationCore.Entities.ClaseConstructor, ApplicationCore.ViewModels.ClaseConstructor>()
.ForPath(dto => dto.ReferenciaConstructor.ReferenciasFabricante, opt => opt.MapFrom(x => x.ReferenciaConstructor.MontadaPorReferenciasFabricante.Select(y => y.ReferenciaFabricante).ToList()))
;
});
Code:
foreach (ApplicationCore.Entities.ClaseFabricante cfDAO in vClasesFabricante) {
result.Add(AutoMapper.Mapper.Map<ApplicationCore.ViewModels.ClaseFabricante>(cfDAO));
}

Automapper: Error mapping types. Mapping types: IEnumerable`1 -> IEnumerable`1

I am trying to map a model to a view, but I receive the error above when I am trying to display all my elements, since Automapper doesn't recognize the IEnumerable I think. I receive the error when I am trying to map FixedAssets to FixedAssetsView and FixedAssetsView to FixedAssets.
Here are the objects I am trying to map:
FixedAssets
public class FixedAssets : IEntityBase
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<Category> category { get; set; }
public string serialNo { get; set; }
public string provider { get; set;
public DateTime acquisitionDate { get; set; }
public DateTime warrantyEnd { get; set; }
public int inventoryNo { get; set; }
public string allocationStatus { get; set; }
public string owner { get; set; }
public DateTime allocationDate { get; set; }
public string serviceStatus { get; set; }
public string serviceResolution { get; set; }
public FixedAssets()
{
this.category = new HashSet<Category>();
}
}
FixedAssetsView
public class FixedAssetsView
{
public int ID { get; set; }
public string name { get; set; }
public virtual ICollection<CategoryView> category { get; set; }
public string serialNo { get; set; }
public string provider { get; set; }
public DateTime acquisitionDate { get; set; }
public DateTime warrantyEnd { get; set; }
public int inventoryNo { get; set; }
public string allocationStatus { get; set; }
public string owner { get; set; }
public DateTime allocationDate { get; set; }
public string serviceStatus { get; set; }
public string serviceResolution { get; set; }
}
Category
public class Category : IEntityBase
{
public int ID { get; set; }
public string categoryName { get; set; }
public virtual ICollection<FixedAssets> fixedasset { get; set; }
public Category()
{
this.fixedasset = new HashSet<FixedAssets>();
}
}
CategoryView
public class CategoryView
{
public int ID { get; set; }
public string categoryName { get; set; }
public virtual ICollection<FixedAssetsView> fixedasset { get; set; }
}
Automapper configuration
Mapper.Initialize(x =>
{
x.CreateMap<FixedAssets, FixedAssetsView>();
x.CreateMap<FixedAssetsView, FixedAssets>();
x.CreateMap<Category, CategoryView>();
x.CreateMap<CategoryView, Category>();
});
I believe you need a .ForMember in your Mapper initialization.
eg:
Mapper.CreateMap<IEnumerable<Source>, IEnumerable<Target>>()
.ForMember(f => f, mp => mp.MapFrom(
mfrom => mfrom.Select(s => AutoMapper.Mapper.Map(s, new Target())
)
);

AutoMapper Map nested ICollection

I want to map one call to another, but I got exception all the time /An exception of type 'AutoMapper.AutoMapperMappingException' occurred in AutoMapper.dll but was not handled in user code/
Here are my Source Classes:
public class Snippet
{
public Snippet()
{
this.Labels = new HashSet<Label>();
this.Commennts = new HashSet<Comment>();
}
public int Id { get; set; }
[Required]
public string Title { get; set; }
public string Description { get; set; }
[Required]
public string Code { get; set; }
public int LanguageId { get; set; }
public string UserId { get; set; }
public DateTime CreatedOn { get; set; }
public ICollection<Label> Labels { get; set; }
public ICollection<Comment> Commennts { get; set; }
public virtual Language Language { get; set; }
public virtual ApplicationUser User { get; set; }
}
public class Label
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Snippet> Snippets { get; set; }
}
Here are my Destination classes:
public class SnippetModels
{
public class Output
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreatedOn { get; set; }
public string Code { get; set; }
public string LanguageName { get; set; }
public string UserUsername { get; set; }
public IEnumerable<LabelModels.Output> Labels { get; set; }
//TODO Comments Labels
}
}
public class LabelModels
{
public class Output
{
public int Id { get; set; }
public string Name { get; set; }
}
}
public class HomeViewModel
{
public IEnumerable<SnippetModels.Output> Snippets { get; set; }
public IEnumerable<LabelModels.Output> Labels { get; set; }
}
And finally I tied everything that pop up in my mind but no success:
Mapper.CreateMap<Snippy.Models.Label, LabelModels.Output>();
Mapper.CreateMap<IEnumerable<Snippy.Models.Label>, IEnumerable<LabelModels.Output>>();
Mapper.CreateMap<Snippy.Models.Snippet, SnippetModels.Output>()
.ForMember(dest => dest.Labels, opt => opt.MapFrom(src => src.Labels));
Mapper.CreateMap<IEnumerable<Snippy.Models.Snippet>, IEnumerable<SnippetModels.Output>>();
var newestSnippetsDatabase = this.Data.Snippets
.All()
.OrderByDescending(s => s.CreatedOn)
.Take(HomeVisibleItemsCount)
.Select(s => s)
.ToList();
var homeScreenView = new HomeViewModel
{
Snippets = Mapper.Map<IEnumerable<SnippetModels.Output>>(newestSnippetsDatabase)
};

Categories

Resources