AgileMapper
AgileMapper copied to clipboard
Mapping from Optional fields to non optional fields
Hello
I am creating a graphql project where you often use a Optional keyword. Somehow it works with your mapper but not with datetime and other complex types
From these "records"
public record NewCustomerInput(Optional<string> AuthId, string FirstName, string LastName, string Email, Optional<DateTime?> BirthDate, Optional<List<NewCustomerAddress>> Addresses);
public record NewCustomerAddress(string StreetName, string StreetNumber, string Zipcode, Optional<string> City, Optional<string> Floor, Optional<string> Door);
To
public class Customer
{
public string AuthId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public DateTime? BirthDate { get; set; }
public List<Address> Addresses { get; set; }
}
Doing this will allways make the birthdate and address list null. The simple fields like string, ints works fine but not lists, objects and datetimes:
public Customer CreateCustomer(IResolverContext context, NewCustomerInput input)
{
var customer = Mapper.Map(input).ToANew<Customer>();
Removing the Optional from the birthdate and list input fields will populate the destination fields.
My current workaround is to populate those fields individually. The datetime will fail due to a nullreferenceException so I map that one manually. I can even remove mappings from optionals that does not have a value which is awesome.
public Customer CreateCustomer(IResolverContext context, NewCustomerInput input)
{
Mapper.WhenMapping.IgnoreSources(c => c.If<Optional<object>>(s => s.HasValue == false));
var customer = Mapper.Map(input).ToANew<Customer>();
customer.BirthDate = input.BirthDate;
customer.Addresses = Mapper.Map(input.Addresses.Value).ToANew<List<Address>>();
Is there anyway I can make your mapper support Optionals or do I maybe have to code my own mapper. Is there some setting I'm not aware of?
Hi,
Thanks for letting me know about this! It looks from your code like Optional<T>
is a GraphQL type, but I can't find anything on it - could you send me a link me to it?
Cheers,
Steve
Hello again!
I've got a working dotnetfiddle here, but I am having to tell the mapper to map each Optional.Value
property to its target, which is a shame.
This configuration (and an equivalent one for Addresses) should work, but doesn't:
Mapper.WhenMapping
.From<Optional<DateTime?>>().To<DateTime?>()
.Map((o, _) => o.Value).ToTargetInstead();
...so I'll look into that. Hopefully the work-around is good enough for now!
There arent an official implementation of "Optional" but all have the "value" and "hasValue" as you have in your fiddle.
I think this is an awesome workaround.
Is the optional something that could be implemented or is it out of scope of your mapper ? Let me know if you more info or help from me.
The ToTargetInstead()
configuration should work, and would be a better solution as you'd only have to configure it once per optional type. I'll leave this issue open to track the bug.
Thanks! Steve