Table of Contents

Configuring data mapping

You may need to map data between some API types and Model types, known as DTO design pattern. Apizr could handle it for you by providing an IMappingHandler interface implementation to it. Fortunately, there are some integration Nuget packages to do so. Of course, you can implement your own integration, but here we'll talk about the provided ones.

Please first install this integration package of your choice:

Project Current Upcoming
Apizr.Integrations.AutoMapper NuGet NuGet Pre Release
Apizr.Integrations.Mapster NuGet NuGet Pre Release

Where:

  • Apizr.Integrations.AutoMapper package brings an IMappingHandler implementation for AutoMapper
  • Apizr.Integrations.Mapster package brings an IMappingHandler implementation for Mapster

Defining

AutoMapper

As usually with AutoMapper, define your mapping profiles, like for example:

public class UserMinUserProfile : Profile
{
    public UserMinUserProfile()
    {
        CreateMap<User, MinUser>()
            .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.FirstName));
        CreateMap<MinUser, User>()
            .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.Name));
    }
}

Mapster

No need to write your own DTO classes. Mapster provides Mapster.Tool to help you generating models. And if you would like to have explicit mapping, Mapster also generates mapper class for you.

[AdaptTo("[name]Dto"), GenerateMapper]
public class Student {
    ...
}

Then Mapster will generate:

public class StudentDto {
    ...
}
public static class StudentMapper {
    public static StudentDto AdaptToDto(this Student poco) { ... }
    public static StudentDto AdaptTo(this Student poco, StudentDto dto) { ... }
    public static Expression<Func<Student, StudentDto>> ProjectToDto => ...
}

But you can also write your own mapping configuration, like for example:

TypeAdapterConfig<TSource, TDestination>
    .NewConfig()
    .Ignore(dest => dest.Age)
    .Map(dest => dest.FullName,
        src => string.Format("{0} {1}", src.FirstName, src.LastName));

Advanced

Warning

Data Mapping with MediatR and/or Optional

If you plan to use MediatR and/or Optional integrations, one more defining step has to be done.

Only for those of you planning to use data mapping with MediatR and/or Optional, Apizr provide a MappedWith attribute telling it to map api object with model object. You’ll find another MappedCrudEntity attribute dedicated to CRUD apis, coming with auto-registration capabilities, in case of access restricted to only local client model. We could get a model class mapped to an api one like:

[MappedWith(typeof(User))]
public class MinUser
{
    public int Id { get; set; }
    public string Name { get; set; }
}

Registering

AutoMapper

First create a MapperConfiguration with your profiles:

var mapperConfig = new MapperConfiguration(config =>
{
    config.AddProfile<UserMinUserProfile>();
    config.AddProfile<WhateverProfile>();
});

Then you'll be able to register with this option:

// direct short configuration
options => options.WithAutoMapperMappingHandler(mapperConfig)

// OR direct configuration
options => options.WithMappingHandler(new AutoMapperMappingHandler(mapperConfig.CreateMapper()))

// OR factory configuration
options => options.WithMappingHandler(() => new AutoMapperMappingHandler(mapperConfig.CreateMapper()))

Mapster

Register with one of the following options:

// direct short configuration
options => options.WithMapsterMappingHandler(new Mapper())

// OR direct configuration
options => options.WithMappingHandler(new MapsterMappingHandler(new Mapper()))

// OR factory configuration
options => options.WithMappingHandler(() => new MapsterMappingHandler(new Mapper()))

Using

You can tell Apizr to map data just by providing types when executing a request.

Something like:

var result = await reqResManager.ExecuteAsync<MinUser, User>((api, user) => 
    api.CreateUser(user, CancellationToken.None), minUser);

Here we give a MinUser typed object to Apizr, which will be mapped to User type just before sending it. Then Apizr will map the User typed result back to MinUser type just before returning it.

There are much more overloads so you can map objects the way you need. The same while using MediatR and/or Optional.