Data transfer objects and mapping in asp net core

Data transfer objects and mapping in asp net core
Photo by Dariusz Sankowski / Unsplash

Hello guys, I’m so glad to be back after a short rest. I took some time for myself to plan what’s coming next for my personal and professional life and to be honest, I’m still thinking about that but definitely, I feel more energic and enthusiastic about the future and feel that is time for me to come back to my writing schedule and prepare more cool projects for you guys! 💪🏾😁

Today we will have a double topic article as we will talk about data transfer objects and mapping using auto mapper. We will see what are data transfer objects and why they are important and the same for data mapping. After this, I will show you how to implement it on our Blog web API to enhance the process of data transfer in our project and to return only the properties that we want from our model and not the entire entity. So without further ado let’s begin.

What are Data Transfer Objects

A Data Transfer Object (DTO) is a design pattern used to transfer data between different layers of your application. DTOs are lightweight objects that contain only the data necessary to be transferred between layers, without any business logic or other unnecessary information. DTOs are commonly used in web-based systems to transfer data between the client and server or between different services within the same system.

Why are Data Transfer Objects Important

DTOs are important because they simplify the process of transferring data between different layers of your application. By using DTOs, you can ensure that only the necessary data is transferred, which can improve the performance of your system. DTOs also help to decouple different layers of your application, which can make your code more maintainable and easier to test.

But DTOs aren't just about improving performance and maintainability. They also help to prevent security vulnerabilities in your system. By only transferring the necessary data, you can reduce the risk of exposing sensitive information to unauthorized users.

What is Automapper ?

Automapper is an open-source library that simplifies the process of mapping data between different classes in your application. With Automapper, you can easily configure how data should be mapped from one class to another, and then let the library do the rest of the work for you.

Why is it Useful ?

Automapper saves you time and effort by automating the mapping process. With Automapper, you no longer have to write tedious and error-prone mapping code by hand. Instead, you can configure how data should be mapped between classes using simple and intuitive configuration files.

But Automapper isn't just about saving you time. It also helps to prevent common mapping errors and makes your code more maintainable. With Automapper, you can be confident that your data is being mapped correctly, and that any changes you make to your classes will be automatically reflected in your mappings.

Clone the GitHub repo

Before starting make sure you clone the GitHub repo if you want to code along with me and make sure you clone the “RepositoryPattern” branch which contains the changes we make in our last post.

GitHub - Osempu/BlogAPI at RepositoryPattern
Contribute to Osempu/BlogAPI development by creating an account on GitHub.

Let’s modify our Post model

Our model it’s pretty simple and actually, the properties that we have are the properties that we want to return in our API endpoints therefore let’s add some other properties that we don’t want to display. We are going to add two date properties, one for when the post was created and another one for the last time our post was updated.

public class Post
{
    public int Id { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime LastUpdated { get; set; }
}

Now as we modified our model we have to update our database so let’s add a migration and update the database using the dotnet cli.

dotnet ef migrations add "name-of-your-migration"

dotnet ef database update

Now our database is updated to hold both date fields.

Create a new DTO

To create a DTO properly we have to think about what properties of our model we don’t need or don’t want to expose. Remember that the benefits of dtos are that we can limit the payload size that we are sending to the client only the relevant fields he will need and that we can hide sensitive information behind our dto.

Therefore let’s hide our date time properties as we don’t need the client to know when was the post updated also remember that not all blogs display the date when the article was created to give the viewer the sense that he is looking to a recent post.

public class PostDTO
{
    public int Id { get; set; }
    public string Author { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

So our PostDTO ended up looking like our Post model was before adding the date properties.

Now you may be thinking how is this going to work? well, the thing is that whenever you would return the Post model with all its properties you would perform a manual mapping to return a PostDTO exposing only the desired properties. The following is an example of performing a manual mapping in the GetPost endpoint of our PostController.

[HttpGet]
public IActionResult GetPost()
{
    var postsDto = repository.GetPost()
                            .Select( x => new PostDTO{
                                Id = x.Id,
                                Author = x.Author,
                                Body = x.Body,
                                Title = x.Title
                            });

    logger.LogDebug($"Get method called, got {postsDto.Count()} results");
    return Ok(postsDto);
}

But imagine you have a more complex model and you need to perform properties conversions, in that case, doing this mapping manually can led to errors due to performing this process manually, that’s where auto mapper comes in.

Object mapping with AutoMapper

Let’s begin installing the AutoMapper package using the dotnet cli.

dotnet add  package AutoMapper.Extensions.Microsoft.DependencyInjection

Go to the Prorgram file and add AutoMapper a new service.

builder.Services.AddAutoMapper(typeof(Program).Assembly);

After this create a new folder called AutoMapperProfiles and inside it, we will create a new class called PostProfiles that will inherit from Profile and put the configuration in the constructor of the PostProfiles class.

public class PostProfiles : Profile
{
    public PostProfiles()
    {
        CreateMap<Post, PostDTO>();
    }
}

We call the Createmap method and inside the angle brackets on the left side we put the source class which is our entity and on the right side, we have the destination class which is our DTO. This way auto mapper will now that we want to convert from Post to a PostDTO every time we call it.

Using the DTOs in our controller

Everything has been setup so we can use our dto in our PostController. So let’s inject the IMapper interface in the controller constructor.

private readonly ILogger<PostsController> logger;
private readonly IPostRepository repository;
private readonly IMapper mapper;

public PostsController(IPostRepository repository, ILogger<PostsController> logger,
 IMapper mapper)
{
    this.mapper = mapper;
    this.logger = logger;
    this.repository = repository;
}

This is how the constructor should look after adding the IMapper interface and now we can call it from our endpoints to see the magic.

Updating the Get endpoints

[HttpGet]
public IActionResult GetPost()
{
    var posts = repository.GetPost();
    var postsDto = mapper.Map<IEnumerable<PostDTO>>(posts);

    logger.LogDebug($"Get method called, got {postsDto.Count()} results");
    return Ok(postsDto);
}

[HttpGet("{id:int}")]
public IActionResult GetPost(int id)
{
    try
    {
        var post = repository.GetPost(id);
        var postDto = mapper.Map<PostDTO>(post);

        return Ok(postDto);
    }
    catch (Exception ex)
    {
        logger.LogError(ex, $"Error getting post with id {id}");
        throw;
    }
}

We only need to update both get methods as these are the only ones that return the Post entity conversely to the edit, post and delete methods that return Http methods like no content or created at.

As you see the mapping implementation it’s pretty straightforward, we only need to call the mapper.Map<T>() method and then pass the Post to parse it into the PostDTO.

Give it a test

Now you are ready to test both get endpoints in our web API and you will notice no change in fact it will work as before but we know that our DTO it’s hiding some properties that we don’t want to display to the client and could also be hiding sensitive information if that was the case.

Remember that all the code that was shown on this post will be available on GitHub.

Conclusion

DTOs can be really helpful as we have said through the article to reduce the payload size and enhance the user experience by displaying only relevant data and also to protect sensitive information that our main entity could contain and that it’s better not to expose from our endpoints.

Mapping helps us to map our entities to plain DTOs without us doing it manually and avoiding potential errors on the way but it is worth noting that some programmers prefer to implement their own manual mapping because some libraries like AutoMapper use reflection to work and that can slow our application.

Support me if you enjoyed this article!

Thanks for taking the time to read my article if you consider it has helped you or it has added some value to your knowledge please support me by following me and follow my job on my blog Unit Coding and also on my youtube channel I have not been uploading anything to my channel recently but I’m planning on doing it soon. I hope you continue learning and growing on your programming journey and I hope to have the honor to go along with you. Thanks and see you on my next post 😁