Hi have a problem with auomapper where i try to use the Automapper.Mapper(src, dest) without loosing the values in the dest after doing the mapping.
I have a class which has a list of objects like below
public class UpdateShipmentDetailDto
{
public bool IsDocument { get; set; }
public List<UpdateItemDetailDto> ItemDetails { get; set; } = new();
}
which i want to map to
public class SCS_OUT_Manifest
{
public Guid ManifestId { get; set; }
public ICollection<SCS_OUT_ManifestItem> SCS_OUT_ManifestItems { get; set; } = new List<SCS_OUT_ManifestItem>();
}
The UpdateItemDetailDto class looks like this
public class UpdateItemDetailDto
{
public Guid ItemId { get; set; }
public string ItemDescription { get; set; }
public int Qty { get; set; }
public Guid UnitsId { get; set; }
public decimal ItemValue { get; set; }
}
And the SCS_OUT_ManifestItem class looke like
public class SCS_OUT_ManifestItem
{
public Guid ItemId { get; set; }
public Guid ManifestId { get; set; }
public string ItemDescription { get; set; }
public int Qty { get; set; }
public Guid UnitsId { get; set; }
public decimal ItemValue { get; set; }
}
Im performing a maaping like below, which map from ItemDetails (which is a list) to SCS_OUT_ManifestItems (which is also a ICollection).
_mapper.Map(updateShipmentDetailDto.ItemDetails, manifest.SCS_OUT_ManifestItems);
The problem after mapping is done the properties which in the destination collection are set to the default values.
for example the ManifestId inthe SCS_OUT_ManifestItem manifest.SCS_OUT_ManifestItems which is not in updateShipmentDetailDto.ItemDetails is set to its default Guid value 00000000-0000-0000-0000-000000000000.
But if i run this in a loop like below it works.
foreach (var item in manifest.SCS_OUT_ManifestItems)
{
_mapper.Map(updateShipmentDetailDto.ItemDetails.Single(s => s.ItemId == item.ItemId), item);
}
Please help! thanks in advance
Try map your lists and your itens and use the same name ÏtemDetails" in both lists.
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<UpdateItemDetailDto, SCS_OUT_ManifestItem>();
cfg.CreateMap<UpdateShipmentDetailDto, SCS_OUT_Manifest>();
});
var _mapper = config.CreateMapper();
var updateShipmentDetailDto = new UpdateShipmentDetailDto();
var updateItemDetailDto = new UpdateItemDetailDto();
var manifest = new SCS_OUT_Manifest();
updateItemDetailDto.ItemId = Guid.NewGuid();
updateItemDetailDto.UnitsId = Guid.NewGuid();
manifest.ManifestId = Guid.NewGuid();
updateItemDetailDto.ItemDescription = "test";
updateItemDetailDto.Qty = 10;
updateItemDetailDto.ItemValue = 25.50M;
updateShipmentDetailDto.ItemDetails = new List<UpdateItemDetailDto>();
updateShipmentDetailDto.ItemDetails.Add(updateItemDetailDto);
_mapper.Map(updateShipmentDetailDto.ItemDetails, manifest.ItemDetails);
Console.WriteLine($"DTO Guid: {updateShipmentDetailDto.ItemDetails[0].ItemId}, Desc: {updateShipmentDetailDto.ItemDetails[0].ItemDescription}");
foreach (var item in manifest.ItemDetails)
{
Console.WriteLine($"Guid: {item.ItemId}, Desc: {item.ItemDescription}");
}
Console.WriteLine($"Guid Manifest: {manifest.ManifestId}");
I wonder whether there is a shortcut to make a flat view model from entity framework. The user table has a list of addresses. When I populate the view model I use FirstOrDefault for both streetline1 and streetline2. Is there a shortcut to populate the two strings from a list?
static void Main(string[] args)
{
//EF Data
User EFUser = new User();
EFUser.UserId = 1;
EFUser.Username = "Data";
List<Address> ListOfAddress = new List<Address>();
ListOfAddress.Add(new Address() { UserId=1, StreetLine1="address 1",StreetLine2="address line2 1" });
EFUser.Address = ListOfAddress;
ViewModelUserFlat vm = new ViewModelUserFlat();
vm.UserId = EFUser.UserId;
vm.UserName = EFUser.Username;
vm.StreetLine1 = ListOfAddress.Select(a => a.StreetLine1).FirstOrDefault();
vm.StreetLine2 = ListOfAddress.Select(a => a.StreetLine2).FirstOrDefault();
}
class Address
{
public int AddressId { get; set; }
public int UserId { get; set; }
public string StreetLine1 { get; set; }
public string StreetLine2{ get; set; }
}
class User
{
public int UserId { get; set; }
public string Username { get; set; }
public List<Address> Address { get; set; }
}
class ViewModelUserFlat
{
public int UserId { get; set; }
public string UserName { get; set; }
public string StreetLine1 { get; set; }
public string StreetLine2 { get; set; }
}
There are multiple ways to assign StreetLine1 and StreetLine2. As yours Address is a list type you need to use FirstOrDefault or the index
var address = ListOfAddress.FirstOrDefault();
vm.StreetLine1 = address?.StreetLine1;
vm.StreetLine2 = address?.StreetLine2;
vm.StreetLine1 = address.FirstOrDefault().StreetLine1;
vm.StreetLine2 = address.FirstOrDefault().StreetLine2;
vm.StreetLine1 = ListOfAddress[0].StreetLine1;
vm.StreetLine2 = ListOfAddress[0].StreetLine2;
I am creating a web api that returns Json. My out put looks like this:
[
{
"NodeID":1252,
"CASNumber":"1333-86-4",
"EINECSCode":"215-609-9",
"EUIndex":"215-609-9",
"Duty":"No",
"Prohibited":"No",
"Unwanted":"No",
"IsReach":"No",
"SubstanceName":"Carbon black",
"GroupName":"Renault Complete",
"Portion":0.100000
},
{
"NodeID":1252,
"CASNumber":"1333-86-4",
"EINECSCode":"215-609-9",
"EUIndex":"215-609-9",
"Duty":"No",
"Prohibited":"No",
"Unwanted":"No",
"IsReach":"No",
"SubstanceName":"Carbon black",
"GroupName":"Renault Orange",
"Portion":0.100000
}
]
I Am trying to create nested Json with an ouptut like this:
{
"NodeID":1252,
"CASNumber":"1333-86-4",
"EINECSCode":"215-609-9",
"EUIndex":"215-609-9",
"Duty":"No",
"Prohibited":"No",
"Unwanted":"No",
"IsReach":"No",
"SubstanceName":"Carbon black",
"GroupName":[
{
"name":"Renault Complete"
},
{
"name":"Renault Orange"
}
],
"Portion":0.100000
}
This is my class:
public class BasicSubstances
{
public int NodeID { get; set; }
public string CASNumber { get; set; }
public string EINECSCode { get; set; }
public string EUIndex { get; set; }
public string Duty { get; set; }
public string Prohibited { get; set; }
public string Unwanted { get; set; }
public string IsReach { get; set; }
public string SubstanceName { get; set; }
public string GroupName { get; set; }
public decimal ?Portion { get; set; }
}
And this is my controller:
public List<BasicSubstances> GetBasicSubstance(string partNumber, string version, int nodeID, int parentID )
{
IMDSDataContext dc = new IMDSDataContext();
List<BasicSubstances> results = new List<BasicSubstances>();
foreach (spGetBasicSubstanceResult part in dc.spGetBasicSubstance( partNumber, version, nodeID, parentID))
{
results.Add(new BasicSubstances()
{
NodeID = part.NodeID,
CASNumber = part.CASNumber,
EINECSCode = part.EINECSCode,
EUIndex = part.EINECSCode,
Duty = part.Duty,
Prohibited = part.Prohibited,
Unwanted = part.Unwanted,
IsReach = part.ISReach,
SubstanceName = part.SynonymName,
GroupName = part.GroupName,
Portion = part.Portion
});
}
return results;
}
My Json looks like the first output, I need it to look like the second output.
I totally lost, any help would be appreciated.
Well, you can try the following:
Your models:
public class BasicSubstanceViewModel
{
public int NodeID { get; set; }
public string CASNumber { get; set; }
public string EINECSCode { get; set; }
public string EUIndex { get; set; }
public string Duty { get; set; }
public string Prohibited { get; set; }
public string Unwanted { get; set; }
public string IsReach { get; set; }
public string SubstanceName { get; set; }
public List<GroupName> GroupName { get; set; }
public decimal ?Portion { get; set; }
}
public class GroupName
{
public string Name { get; set; }
}
Your method:
public BasicSubstanceViewModel GetBasicSubstance(string partNumber, string version, int nodeID, int parentID )
{
IMDSDataContext dc = new IMDSDataContext();
var spResult = dc.spGetBasicSubstance( partNumber, version, nodeID, parentID).ToList();
if(!spResult.Any())
{
return null;
}
var firstPart = spResult[0];
var result = new BasicSubstanceViewModel
{
NodeID = firstPart.NodeID,
CASNumber = firstPart.CASNumber,
EINECSCode = firstPart.EINECSCode,
EUIndex = firstPart.EINECSCode,
Duty = firstPart.Duty,
Prohibited = firstPart.Prohibited,
Unwanted = firstPart.Unwanted,
IsReach = firstPart.ISReach,
SubstanceName = firstPart.SynonymName,
GroupName = spResult.Select(p => new GroupName { Name = p.GroupName }).ToList(),
Portion = firstPart.Portion
};
return result;
}
Hope it will help.
I have this code:
public class TopTen
{
public int Id { get; set; }
public string ShortDesc { get; set; }
public string LongDesc { get; set; }
public Image Photo { get; set; }
}
public class Image
{
public string ImgUrl { get; set; }
public string AlterText { get; set; }
}
I can do like this to assign values:
new topten()
{
/*
here I can access and give values to my properties. BUT i cant
access and give values to the properties in my `Image` class.
This is a problem because I would like to upload the new object as a json-file.
So how do I access the properties in `Image`?
*/
}
var x = new TopTen
{
Id = 1,
Photo = new Image
{
ImgUrl = "pic.jpg",
AlterText = "This is a picture"
}
};
I'm using EF4.1 code first to create a simple database app with SQL CE 4 backend. I have a Product class and a CallItem class defined as so:
class CallItem
{
public int id { get; set; }
public float discount { get; set; }
public virtual Product Product { get; set; }
}
class Product
{
public int id { get; set; }
public decimal BaseCost { get; set; }
public int UnitSize { get; set; }
public bool isWasteOil { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
}
edit - When I am creating a collection of CallItems using a LINQ query, I cannot access the attributes of the Product attached to each CallItem, eg
var callItems = from ci in context.CallItems select ci;
foreach(CallItem callItem in callItems)
{
RunSheet nrs = new RunSheet();
nrs.prodCode = callitem.Product.Code;
}
Interrogating the database shows that Productid in CallItems is being populated. However, the following line generates a NullReferenceException during run time:
nrs.prodCode = callitem.Product.Code;
Because callitem.Product is evaluating to null. Is this something to do with lazy loading and if so how can I resolve the issue?
RunSheet is another class, nrs is an instance whose attribute 'prodCode' I want to populate with the CallItem's Product's code.
Thanks!
From that code what you've showed it should work. Have you tried explicit loading?
var callItems = from ci in context.CallItems.Include(c => c.Product) select ci;
foreach(CallItem callItem in callItems)
{
RunSheet nrs = new RunSheet();
nrs.prodCode = callitem.Product.Code;
}
public class CallItem
{
public int Id { get; set; }
public float Discount { get; set; }
public virtual Product Product { get; set; }
}
public class Product
{
public int Id { get; set; }
public decimal BaseCost { get; set; }
public int UnitSize { get; set; }
public bool IsWasteOil { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Ingredients { get; set; }
}
using (var context = new StackOverFlowContext())
{
var p = new Product
{
Id = 1,
BaseCost = 200,
Code = "Hola",
Description = "Soe description",
Ingredients = "Some ingredients",
IsWasteOil = true,
Name = "My Product",
UnitSize = 10
};
var item = new CallItem
{
Id = 101,
Discount = 10,
Product = p
};
context.CallItems.Add(item);
context.SaveChanges();
var result = from temp in context.CallItems
select temp;
Console.WriteLine("CallItem Id"+result.First().Id);
Console.WriteLine("ProductId"+result.First().Product.Id);
}
I wrote the above code with the following output
CallItemId 1
ProductId 1
The sql Profiler showed this
SELECT TOP (1)
[c].[Id] AS [Id],
[c].[Discount] AS [Discount],
[c].[Product_Id] AS [Product_Id]
FROM [dbo].[CallItems] AS [c]
It was too long for a comment ,so i put it here .