Nivitha Gopalakrishnan
Nivitha Gopalakrishnan

Reputation: 659

How to assign null for the object if object members have no value - automapper c#

I am using automapper in c#.

class A 
{
   public int Value { get; set; }
   public string Code { get; set; }
   public B? Details { get; set; }
}

 class B 
 {
   public int Id { get; set;}
   public string Name { get; set; }
 } 

 class C
 {
   public int Value { get; set; }
   public string Code { get; set; }
   public int? DetailId { get; set; }
   public string? DetailName { get; set; }
 }

And in automapper I used like below:

CreateMap<C, A>()
.ForPath(o => o.Details.Id, b => b.MapFrom(z => z.DetailId))
.ForPath(o => o.Details.Name, b => b.MapFrom(z => z.DetailName))
.ReverseMap();

When I using like the above mapping, I get like output as

  "details ": {
        "id": 0,
        "name": ""
   }

I need to get Details value as null instead of an object type if it's members have no value. i.e) DetailId and DetailName have no value. How to get this?

  "details" : null

Upvotes: 2

Views: 1753

Answers (3)

Support Ukraine
Support Ukraine

Reputation: 1024

You can user Conditional Mapping

    var config = new MapperConfiguration(cfg =>
      {
         cfg.CreateMap<C, B>()
            .ForMember(o => o.Id, b => b.MapFrom(z => z.DetailId))
            .ForMember(o => o.Name, b => b.MapFrom(z => z.DetailName));

          cfg.CreateMap<C, A>()
             .ForMember(o => o.Details, b => b.MapFrom((c, a, obj, context) => !string.IsNullOrEmpty(c.DetailName) ? context.Mapper.Map<B>(c) : null))
             .ReverseMap();
      });
    

Upvotes: 5

duskjet
duskjet

Reputation: 1

You can use IValueResolver interface to achieve what you require. Documentation: http://docs.automapper.org/en/stable/Custom-value-resolvers.html

Also there's a similar question: Automapper Mapping Multiple Properties to Single Property

Configuration:

CreateMap<C, A>()
.ForMember(o => o.Details, b => b.MapFrom<DetailsValueResolver>())
.ReverseMap();

Implementation:

// Note: this does not cover ReverseMap() when you would try to convert A to C
public class DetailsValueResolver : IValueResolver<C, A, B>
{
    // Runs every time you map C to A
    public B Resolve(C source, A destination, B destMember, ResolutionContext context)
    {
        // Covers cases where you can get null or empty DetailName, as well as null or zero DetailId
        if (!string.IsNullOrEmpty(source.DetailName) && source.DetailId > 0)
        {
            return new B { Id = (int)source.DetailId, Name = source.DetailName };
        }

        return null;
    }
}

You also can omit explicitly setting strings and classes as nullable types with ? as you do here:

public B? Details { get; set; }
public string? DetailName { get; set; }

Because string type and any class is null by default.

Upvotes: 0

simon-pearson
simon-pearson

Reputation: 1970

You could do this with an AutoMapper after map action.

Something like this:

CreateMap<C, A>()
    .ForPath(o => o.Details.Id, b => b.MapFrom(z => z.DetailId))
    .ForPath(o => o.Details.Name, b => b.MapFrom(z => z.DetailName))
    .AfterMap((src, dest) =>
    {
        dest.Details = src.DetailId.HasValue && src.DetailName != null
            ? dest.Details
            : null;
    })
    .ReverseMap());

Upvotes: 4

Related Questions