Sirisha Ancha Team : Web Development Tags : Web Development Tips & Tricks

Auto Mapping Objects in .Net

Sirisha Ancha Team : Web Development Tags : Web Development Tips & Tricks

Manually Mapping Objects

Mappings for any two objects are usually written where each field is mapped as per the requirements. Sometimes mappings need to be conditional as well. In most coding practices the naming convention is kept intact.

This seemingly easy code tends to get more complex as the objects change over time. Testing gets progressively less fun as the code grows in length and the burden of maintenance also increases rapidly. With technology advancing at it's current pace the questions remains:

Is this kind of repetitive code needed?

Automapper - Object - Object Mapper

It would be so cool if the objects could intelligently map themselves based on their field names and some custom conditions, thereby reducing the amount of development work required. This is where Automapper comes in.

AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that maps one object to another.

Lets map the following 2 classes:

public class MemberViewModel
{        
        public string MembershipNumber { get; set; }
        public Guid Id { get; set; }
        public string FullName { get; set; }
        public string PreferredName { get; set; }
        public string JobTitle { get; set; }
        public string Company { get; set; }
        public string PostalAddressCountry { get; set; }
        public string BillToSameAsPostal { get; set; }
        public string BillToAddressCountry { get; set; }
}
public class MemberModel
{        
        public string MembershipNumber { get; set; }
        public DateTime BirthDate { get; set; }
        public DateTime DateModified { get; set; }
        public Guid UniqueId { get; set; }
        public string FullName { get; set; }
        public string PreferredName { get; set; }
        public string JobTitle { get; set; }
        public string Company { get; set; }
        public string PostalAddressCountry { get; set; }
        public string BillToSameAsPostal { get; set; }
        public string BillToAddressCountry { get; set; }
}

This is a 2 step process of creating maps between objects and then actually mapping them to retrieve the mapped object.

Creating Maps

Ideally an Automapper.cs class is created to store all map creations in one place. The best place to put the configuration code is in application startup scripts, such as the Global.asax file for ASP.NET applications.

CreateMap(TSource, TDestination);

Creates a mapping configuration from the TSource type to the TDestination type

Where TSource: Source type, TDestination: Destination type

public static void CreateMaps()
{            
    Mapper.CreateMap<MemberModel, MemberViewModel>()
        .ForSourceMember(dest => dest.BirthDate, opt => opt.Ignore())
        .ForSourceMember(dest => dest.DateModified, opt => opt.Ignore())
        .ForMember(dest => dest.UniqueId, opt => opt.MapFrom(src => src.Id); 
    Mapper.CreateMap<MemberViewModel, MemberModel>()
        .ForMember(dest => dest.BillToSameAsPostal, opt => opt.MapFrom(src => src.BillToSameAsPostalBoolean ? "Yes" : "No"))
        .ForMember(dest => dest.BillToAddressCountry, opt => opt.MapFrom(src => src.BillToSameAsPostalBoolean ? src.PostalAddressCountry : src.BillToAddressCountry)
        .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.UniqueId);                                     
}


Automapper provides various options to customise the way the mappings are performed. In the above example the Birthdate and DateModified fields are meant to be ignored while mapping.

AutoMapper will ignore null reference exceptions when mapping your source to your target. This is by design. If you don't like this approach, you can combine AutoMapper's approach with Custom-value-resolvers if needed.

Getting Mapped objects

    var mappedDestinationObject =  Map<TDestination>(object source);

Executes a mapping from the source object to a new destination object.The sourcetype is inferred from the source object.

Where source: object to map from, TDestination: Destination type to create

Returns: Mapped destination object

public static ManageProfileViewModel GetMappedModelData(MemberModel member, ManageProfileViewModel model)
{
    return Mapper.Map<ManageProfileViewModel>(member);
}
public static MemberModel GetMappedModelData(ManageProfileViewModel model, MemberModel member)
{            
    return Mapper.Map<MemberModel>(model);                 
}

Mapper.Map could be used to retrieve the mapped source.

Other Options

The above is just an introduction to Automapper. There are various other options available to map as per the need. A few stated below.

Creating before and after maps

Mapper.Map<Source, Dest>(src, opt => {
    opt.BeforeMap((src, dest) => src.Value = src.Value + 70);
    opt.AfterMap((src, dest) => dest.Name = HttpContext.Current.Identity.Name);
});

Conditional Mapping

CreateMap<Foo,Bar>()
    .ForMember(dest => dest.baz, opt => opt.Condition(src => (src.baz >= 0)))

Using Automapper has saved me hours of writing monotonous code which needs to be updated all the time. When used the right way this could make code much cleaner and precise (and testable!)