7

What does UseDestinationValue do?

I am asking because I have a base and inherited class, and for the base class, I would love to have AutoMapper take existing values for me.

Will it do that? (I have looked and the only examples I can see for UseDestinationValue involve lists. Is it only for lists?

could I do this:

PersonContract personContract = new PersonContract {Name = 'Dan'};
Person person = new Person {Name = "Bob"};
Mapper.CreateMap<PersonContract, Person>()
      .ForMember(x=>x.Name, opt=>opt.UseDestinationValue());

person = Mapper.Map<PersonContract, Person>(personContract);

Console.WriteLine(person.Name);

and have the output be bob?

Michał Powaga
  • 22,561
  • 8
  • 51
  • 62
Vaccano
  • 78,325
  • 149
  • 468
  • 850

2 Answers2

3

I was brought here having a similar question, but in regards to nested classes and keeping the destination value. I tried above in any way I could, but it did not work for me, it turns out you have to use UseDestinationValue on parent object as well. I am leaving this here in case anyone else has the same issue I did. It took me some time to get it working. I kept thinking the issue lies within AddressViewModel => Address mapping.

In BidderViewModel class, BidderAddress is of type AddressViewModel. I needed the Address ID to be preserved in situations where it is not null.

Mapper.CreateMap<BidderViewModel, Bidder>()
    .ForMember(dest => dest.BidderAddress, opt=> opt.UseDestinationValue())
    .ForMember(dest => dest.ID, opt => opt.UseDestinationValue());
Mapper.CreateMap<AddressViewModel, Address>()
    .ForMember(dest => dest.ID, opt => { opt.UseDestinationValue(); opt.Ignore(); });

Use (where viewModel is of type BidderViewModel as returned by the View in MVC):

Bidder bidder = Mapper.Map<BidderViewModel, Bidder>(viewModel, currentBid.Bidder)
Michał Powaga
  • 22,561
  • 8
  • 51
  • 62
ZanderAdam
  • 434
  • 2
  • 13
  • 1
    Using both `{ opt.UseDestinationValue(); opt.Ignore(); }` together does not make sense for me. Could you explain it? – Mojtaba Apr 04 '19 at 15:15
  • @Mojtaba UseDestinationValue makes sure that the same Address record is used (to avoid creating new Address rows, leaving the old "orphan" in the Address store) and Ignore to ignore the fact that there is no exposed ID on the AddressViewModel – Johan Andersson Oct 15 '20 at 09:40
3

I wrote this whole question up and then thought, DUH! just run it and see.

It works as I had hoped.

This is the code I ended up with:

class Program
{
    static void Main(string[] args)
    {
        PersonContract personContract = new PersonContract {NickName = "Dan"};
        Person person = new Person {Name = "Robert", NickName = "Bob"};
        Mapper.CreateMap<PersonContract, Person>()
            .ForMember(x => x.Name, opt =>
                                        {
                                            opt.UseDestinationValue();
                                            opt.Ignore();
                                        });

        Mapper.AssertConfigurationIsValid();

        var personOut = 
            Mapper.Map<PersonContract, Person>(personContract, person);

        Console.WriteLine(person.Name);
        Console.WriteLine(person.NickName);

        Console.WriteLine(personOut.Name);
        Console.WriteLine(personOut.NickName);
        Console.ReadLine();
    }
}

internal class Person
{
    public string Name { get; set; }
    public string NickName { get; set; }
}

internal class PersonContract
{
    public string NickName { get; set; }
}

The output was:

Robert
Dan
Robert
Dan

Michał Powaga
  • 22,561
  • 8
  • 51
  • 62
Vaccano
  • 78,325
  • 149
  • 468
  • 850