Automapper over the converters - c#

I have the code, which use the userClass converters. I want to do the same thing using automapper. How to rewrite the code?
public static ClaimIdentityView ConvertToClaimIdentityView(this ClaimsIdentity Identity)
{
ClaimIdentityView result = new ClaimIdentityView()
{
Name = Identity.Name,
NameClaimType = Identity.NameClaimType,
AuthenticationType = (AuthenticationTypeEnum)EnumStringValue.Parse(typeof(AuthenticationTypeEnum), Identity.AuthenticationType),
RoleClaimType = Identity.RoleClaimType
};
foreach (Claim item in Identity.Claims)
result.ClaimViewList.Add(item.ConvertToClaimView());
return result;
}
public static ClaimView ConvertToClaimView(this Claim Claim)
{
return new ClaimView()
{
Type = Claim.Type,
Value = Claim.Value,
ValueType = Claim.ValueType
};
}
And the second class (the first one is from System.Security.Claims; namespace):
public class ClaimIdentityView
{
public ClaimIdentityView()
{
ClaimViewList = new List<ClaimView>();
}
public Guid UserId { get; set; }
public AuthenticationTypeEnum AuthenticationType { get; set; }
public IList<ClaimView> ClaimViewList { get; set; }
public string Name { get; set; }
public string NameClaimType { get; set; }
public string RoleClaimType { get; set; }
}

Your mappings would look like this:
AutoMapper.Mapper.CreateMap<ClaimsIdentity, ClaimIdentityView>()
.ForMember(dest => dest.ClaimViewList, opt => opt.MapFrom(src => src.Claims))
.ForMember(dest => dest.AuthenticationType,
opt => opt.MapFrom(src => (AuthenticationTypeEnum)
EnumStringValue.Parse(typeof (AuthenticationTypeEnum), src.AuthenticationType)));
AutoMapper.Mapper.CreateMap<Claim, ClaimView>();
Example mapping code:
var claimIdentity = new ClaimsIdentity(WindowsIdentity.GetCurrent());
var view = AutoMapper.Mapper.Map<ClaimsIdentity, ClaimIdentityView>(claimIdentity);
This test would then pass:
var claimIdentity = new ClaimsIdentity(WindowsIdentity.GetCurrent());
// realistically the current account will have claims, but..
claimIdentity.AddClaim(new Claim("Type", "Value"));
var view = AutoMapper.Mapper.Map<ClaimsIdentity, ClaimIdentityView>(claimIdentity);
Assert.IsTrue(view.ClaimViewList.Count > 0);

Related

How to map from flat object to list using Automapper c# .net6?

I'm trying to map a flat object to a list. The Id gets mapped properly, but the list is always empty. I have used reverse mapping for the ListItem in destination.
What is wrong with this code or missing please?
using AutoMapper;
MapperConfiguration config = new MapperConfiguration(x =>
{
x.CreateMap<Origin, Destination>();
x.CreateMap<Destination, NonListItem>()
.ReverseMap()
.ForPath(d => d.ListItem, o => o.MapFrom(s => new List<ListItem> {
new ListItem
{
ListInt = s.NonListInt,
ListStr = s.NonListStr
}
}));
});
var origin = new Origin();
origin.Id = 12345;
origin.NonListItem.NonListInt = 54321;
origin.NonListItem.NonListStr = "This is a test";
IMapper mapper = new Mapper(config);
var destination = mapper.Map<Destination>(origin);
Console.ReadKey();
//###############################################################+
public class Origin
{
public NonListItem NonListItem { get; set; } = new NonListItem();
public int Id { get; set; }
}
public class NonListItem
{
public int NonListInt { get; set; }
public string? NonListStr { get; set; }
}
public class Destination
{
public int Id { get; set; }
public List<ListItem> ListItem { get; set; } = new List<ListItem>();
}
public class ListItem
{
public int ListInt { get; set; }
public string? ListStr { get; set; }
}
Mapping from Destination to NonListItem is not needed. Just configure the Origin to Destination mapping.
MapperConfiguration config = new MapperConfiguration(x =>
{
x.CreateMap<Origin, Destination>()
.ForMember(dest => dest.ListItem, opt => opt.MapFrom(src => new List<ListItem>
{
new ListItem
{
ListInt = src.NonListItem.NonListInt,
ListStr = src.NonListItem.NonListStr
}
}));
});

AutoMapper - Map source list to a destination array

I am trying to map a source list to a destination array using AutoMapper.
Source classes
public class ReservationSource
{
public Travel TravelSource { get; set; }
public string SeqNo { get; set; }
}
public class Travel
{
public string TravelId { get; set; }
public ICollection<Trip> Trips { get; set; }
}
public class Trip
{
public string TrainNumber { get; set; }
public string Arrival { get; set; }
}
Destination classes
public class ReservationDestination
{
public Route[] TravelDest { get; set; }
public string SeqNumber { get; set; }
}
public class Route
{
public string SequNumber { get; set; }
public string RouteId { get; set; }
}
private static route[] GetRoutes(ICollection<Trip> trips)
{
List<route> routeList = new List<route>();
foreach (var trip trips)
{
var route = new route
{
SequNumber = trip.trainNumber
};
routeList.Add(route);
}
return routeList.ToArray();
}
Map configuration
cfg.CreateMap<ReservationSource, ReservationDestination>()
var config = new MapperConfiguration(cfg =>
{
cfg.AllowNullDestinationValues = true;
cfg.CreateMap<ReservationSource, ReservationDestination>()
.ForMember(dest => dest.SeqNumber, o => o.MapFrom(src => SeqNo))
.ForPath(dest => dest.TravelDest, o => o.MapFrom(src => GetRoutes(src)));
});
This is what I have tried, here I would like to eliminate the GetRoutes method where I will do a manual map using a foreach loop. Is it possible to use any other way without a loop?
Add mapping for Trip and Route classes.
cfg.CreateMap<Trip, Route>()
.ForMember(dest => dest.SequNumber, o => o.MapFrom(src => src.TrainNumber));
Complete Mapping Configuration
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Trip, Route>()
.ForMember(dest => dest.SequNumber, o => o.MapFrom(src => src.TrainNumber));
cfg.AllowNullDestinationValues = true;
cfg.CreateMap<ReservationSource, ReservationDestination>()
.ForMember(dest => dest.SeqNumber, o => o.MapFrom(src => src.SeqNo))
.ForPath(dest => dest.TravelDest, o => o.MapFrom(src => src.TravelSource.Trips));
});
IMapper mapper = config.CreateMapper();
var source = new ReservationSource
{
SeqNo = "Seq001",
TravelSource = new Travel
{
TravelId = "1",
Trips = new List<Trip>
{
new Trip { TrainNumber = "A0001" },
new Trip { TrainNumber = "B0001" }
}
}
};
var destination = mapper.Map<ReservationSource, ReservationDestination>(source);
Console.WriteLine(JsonConvert.SerializeObject(destination));
Sample Program
Output
{"TravelDest":[{"SequNumber":"A0001","RouteId":null},{"SequNumber":"B0001","RouteId":null}],"SeqNumber":"Seq001"}
References
Lists and Arrays - AutoMapper documentation

Automapper Serialize/Deserialize source string to list using resolver

I am trying to map source string to List<T> for member but the value of the mapped member list property is always null.
Here is my code.
//Source model
public class Claims
{
public int Id { get; set; }
public string ClaimType {get; set; }
public string ClaimValue { get; set; } // produce json string [{"Action":"read","Status":"active"}]
}
// Dest model
public class ClaimsDto
{
public int Id { get; set; }
public string ClaimType { get; set; }
public List<ResourceActions> ClaimValues { get; set; }
}
public class ResourceActions
{
public string Action { get; set; }
public string Status { get; set; }
}
CreateMap<ResourceActions, ResourceActions>();
CreateMap<Claims, ClaimsDto>()
.ForMember(dest => dest.ClaimValues,
opt => opt.MapFrom( src=> JsonConvert.DeserializeObject<List<ResourceActions>>(src.ClaimValue)))
.ReverseMap();
Also tried with resolver like this.
.ForMember(dto => dto.ClaimValues, opt => opt.ResolveUsing<CustomResolver,string>(src=>src.ClaimValue ))
The resolver:
public class CustomResolver : IMemberValueResolver<Claims, ClaimsDto, string, List<ResourceActions>>
{
public List<ResourceActions> Resolve(Claims source, ClaimsDto destination, string sourceMember, List<ResourceActions> destinationMember, ResolutionContext context)
{
var data = JsonConvert.DeserializeObject<List<ResourceActions>>(sourceMember);
return context.Mapper.Map<List<ResourceActions>>(data); // not working
return JsonConvert.DeserializeObject<List<ResourceActions>>(sourceMember); // not working
}
}
And the controller
var mapped = _mapper.Map<List<ClaimsDto>>(source); // success without exception but the list property is null.
Other properties are mapped except this string to List<T> property.
I think this profile should solve the issue:
public class MyMapperProfile : Profile
{
public MyMapperProfile()
{
CreateMap<Claims, ClaimsDto>()
.ForMember(dto => dto.ClaimValues, cfg => cfg.MapFrom((claim, _) =>
JsonSerializer.Deserialize<IReadOnlyCollection<ResourceActions>>(claim.ClaimValue)));
}
}
Here is an example:
var config = new MapperConfiguration(cfg => cfg.AddProfile<MyMapperProfile>());
var mapper = config.CreateMapper();
var someClaims = new List<Claims>
{
new Claims { Id = 5, ClaimType = "Foo", ClaimValue = #"[{""Action"":""read"",""Status"":""active""}]" },
new Claims { Id = 7, ClaimType = "Bar", ClaimValue = #"[{""Action"":""create"",""Status"":""disabled""}]" },
};
var result = mapper.Map<List<ClaimsDto>>(someClaims);
foreach (var item in result)
{
Console.WriteLine(JsonSerializer.Serialize(item));
}

automap List of complex type to List of complex type using automapper

public class SourceExamModel
{
public int ExamId { get; set; }
public List<SectionModel> Sections { get; set; }
}
public class DesiationExamModel
{
public in ExamId {get;set;}
public System.Collections.Generic.IEnumerable<SectionModel> DestSections
{
get
{
}
set
{
}
}
What I tried:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<CrmMapper.SourceExamModel, CrmMapper.DestiationExamModel>()
.ForMember(v => v.Id, opts => opts.MapFrom(src => src.Id))
.ForMember(v => v.DestSections, opts => opts.MapFrom(src => src.SourceSections));
});
IMapper mapper = config.CreateMapper();
var source = new ExamModel();
var dest = mapper.Map<SourceExamModel, CrmMapper.DestiationExamModel>(source);
Can ayone help me how to map list of comple objects o los of complex objects
Assuming half of your example code is simple spelling mistakes, you pretty much have it working.
If the properties on the source and destination are named the same, you don't have to explicitly map them.
Your source in your example doesn't make sense, it needs the correct object and data.
Here's my attempt at a working example you can copy past into a console application.
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg =>
cfg.CreateMap<SourceExamModel, DestinationExamModel>()
.ForMember(dest => dest.DestSections, c => c.MapFrom(src => src.Sections))
);
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
var source = new SourceExamModel
{
ExamId = 1,
Sections = new List<SectionModel> { new SectionModel { SectionId = 1 }, new SectionModel { SectionId = 2 } }
};
var destination = mapper.Map<SourceExamModel, DestinationExamModel>(source);
}
}
public class SourceExamModel
{
public int ExamId { get; set; }
public List<SectionModel> Sections { get; set; }
}
public class DestinationExamModel
{
public int ExamId { get; set; }
public List<SectionModel> DestSections { get; set; }
}
public class SectionModel
{
public int SectionId { get; set; }
}

How to map objects

Here is my how my bindings currently look:
MerchantAccountRequest request = new MerchantAccountRequest
{
Individual = new IndividualRequest
{
FirstName = merchant.MerchantIndividual.FirstName,
LastName = merchant.MerchantIndividual.LastName,
Email = merchant.MerchantIndividual.Email,
Phone = merchant.MerchantIndividual.Phone,
DateOfBirth = merchant.MerchantIndividual.DateOfBirth,
Ssn = merchant.MerchantIndividual.Ssn,
Address = new AddressRequest
{
StreetAddress = merchant.MerchantIndividual.StreetAddress,
Locality = merchant.MerchantIndividual.Locality,
Region = merchant.MerchantIndividual.Region,
PostalCode = merchant.MerchantIndividual.PostalCode
}
},
Business = new BusinessRequest
{
LegalName = merchant.MerchantBusiness.LegalName,
DbaName = merchant.MerchantBusiness.DbaName,
TaxId = merchant.MerchantBusiness.TaxId,
Address = new AddressRequest
{
StreetAddress = merchant.MerchantBusiness.StreetAddress,
Locality = merchant.MerchantBusiness.Locality,
Region = merchant.MerchantBusiness.Region,
PostalCode = merchant.MerchantBusiness.PostalCode
}
},
Funding = new FundingRequest
{
Descriptor = merchant.MerchantFunding.Descriptor,
Destination = FundingDestination.BANK,
Email = merchant.MerchantFunding.Email,
MobilePhone = merchant.MerchantFunding.MobilePhone,
AccountNumber = merchant.MerchantFunding.AccountNumber,
RoutingNumber = merchant.MerchantFunding.RoutingNumber
},
TosAccepted = merchant.TosAccepted,
MasterMerchantAccountId = merchant.MasterMerchantAccountId,
Id = merchant.MerchantId
};
And I need to use AutoMapper to achieve the above.
This is what I've tried:
CreateMapperProfile
EDIT:
CreateMap<Classes.Merchant, MerchantAccountRequest>()
.ForMember(dest => dest.Individual, source => source.MapFrom(s => s.MerchantIndividual))
.ForMember(dest => dest.Business, source => source.MapFrom(s => s.MerchantBusiness))
.ForMember(dest => dest.Funding, source => source.MapFrom(s => s.MerchantFunding))
.ForMember(dest => dest.Id, source => source.MapFrom(s => s.MerchantId));
Here is the Merchant class:
public partial class Merchant :
{
public int Id { get; set; }
public string MerchantId { get; set; }
public virtual MerchantIndividual MerchantIndividual { get; set; }
public virtual MerchantBusiness MerchantBusiness { get; set; }
public virtual MerchantFunding MerchantFunding { get; set; }
public bool TosAccepted { get; set; }
public string MasterMerchantAccountId { get; set; }
public bool isSubMerchant { get; set; }
}
And the mappings;
EDIT:
MerchantAccountRequest request = _mapper.Map<MerchantAccountRequest>(merchant);
request.Individual = _mapper.Map<IndividualRequest>(merchant.MerchantIndividual);
request.Business = _mapper.Map<BusinessRequest>(merchant.MerchantBusiness);
request.Funding = _mapper.Map<FundingRequest>(merchant.MerchantFunding);
Can the first line of code MerchantAccountRequest request = _mapper.Map<MerchantAccountRequest>(merchant); above do all the mapings?
..
..
..
..
How can I create the correct mappings?
You don't need to call _mapper.Map on the properties of the request.
Just call MerchantAccountRequest request = _mapper.Map<MerchantAccountRequest>(merchant); and assuming you have a map for each type you should be fine.
I think something along the lines of the following should get you going down the right path.
class Program
{
static void Main(string[] args)
{
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<Merchant, MerchantAccountRequest>()
.ForMember(dest => dest.Individual, c => c.MapFrom(source => source.MerchantIndividual));
cfg.CreateMap<MerchantIndividual, IndividualRequest>();
});
config.AssertConfigurationIsValid();
var mapper = config.CreateMapper();
var merchant = new Merchant
{
Id = 1,
MerchantIndividual = new MerchantIndividual { FirstName = "John Doe" }
};
var merchantAccountRequest = mapper.Map<Merchant, MerchantAccountRequest>(merchant);
}
}
public class Merchant
{
public int Id { get; set; }
public MerchantIndividual MerchantIndividual { get; set; }
}
public class MerchantIndividual
{
public string FirstName { get; set; }
}
public class MerchantAccountRequest
{
public int Id { get; set; }
public IndividualRequest Individual { get; set; }
}
public class IndividualRequest
{
public string FirstName { get; set; }
}

Categories

Resources