Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping from Optional fields to non optional fields #219

Open
larsbloch opened this issue Nov 20, 2021 · 4 comments
Open

Mapping from Optional fields to non optional fields #219

larsbloch opened this issue Nov 20, 2021 · 4 comments
Assignees
Labels

Comments

@larsbloch
Copy link

larsbloch commented Nov 20, 2021

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?

@SteveWilkes
Copy link
Member

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

@SteveWilkes
Copy link
Member

SteveWilkes commented Nov 21, 2021

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!

@SteveWilkes SteveWilkes self-assigned this Nov 21, 2021
@larsbloch
Copy link
Author

larsbloch commented Nov 21, 2021

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.

@SteveWilkes
Copy link
Member

SteveWilkes commented Nov 22, 2021

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants