2

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
1
  • You can't with ForPath. Try flattening. Commented Apr 3, 2020 at 7:16

3 Answers 3

5

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();
      });
    
Sign up to request clarification or add additional context in comments.

5 Comments

I need detail property values as null.....i.e) details: null instead of an object type.
@NivithaGopalakrishnan I have updated comment pls see bellow
@NivithaGopalakrishnan pls let me know you need some additional details
If give like this means, .ForMember(o => o.Details, b => b.Condition(x => !String.IsNullOrEmpty(x.DetailName))) , only null values is assigning. If have value means, object type is not returning.
Changed MapFrom it was my fault now it must work fine. But you must to declare mapping C=> B
4

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());

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.