Объекты передачи данных и отображение в ядре asp net

Привет, ребята, я так рад вернуться после короткого отдыха. Я потратил некоторое время на то, чтобы спланировать, что будет дальше в моей личной и профессиональной жизни, и, честно говоря, я все еще думаю об этом, но определенно чувствую себя более энергичным и с энтузиазмом смотрю в будущее и чувствую, что пришло время для меня. вернуться к моему писательскому графику и подготовить для вас побольше крутых проектов! 💪🏾😁

Сегодня у нас будет двойная тематическая статья, так как мы поговорим об объектах передачи данных и отображении с помощью автомаппера. Мы увидим, что такое объекты передачи данных и почему они важны и одинаковы для отображения данных. После этого я покажу вам, как реализовать его в нашем веб-API блога, чтобы улучшить процесс передачи данных в нашем проекте и вернуть только те свойства, которые мы хотим от нашей модели, а не весь объект. Итак, без лишних слов начнем.

Что такое объекты передачи данных ❓

Объект передачи данных (DTO) — это шаблон проектирования, используемый для передачи данных между различными уровнями вашего приложения. DTO — это легковесные объекты, которые содержат только данные, необходимые для передачи между уровнями, без какой-либо бизнес-логики или другой ненужной информации. DTO обычно используются в веб-системах для передачи данных между клиентом и сервером или между различными службами в одной системе.

Почему важны объекты передачи данных 🔎

DTO важны, потому что они упрощают процесс передачи данных между различными уровнями вашего приложения. Используя DTO, вы можете гарантировать, что передаются только необходимые данные, что может повысить производительность вашей системы. DTO также помогают разделить различные уровни вашего приложения, что может сделать ваш код более удобным для сопровождения и более простым для тестирования.

Но DTO предназначены не только для повышения производительности и удобства обслуживания. Они также помогают предотвратить уязвимости системы безопасности. Передавая только необходимые данные, вы можете снизить риск раскрытия конфиденциальной информации неавторизованным пользователям.

Что такое Automapper ❓

Automapper — это библиотека с открытым исходным кодом, которая упрощает процесс сопоставления данных между различными классами в вашем приложении. С Automapper вы можете легко настроить, как данные должны отображаться из одного класса в другой, а затем позволить библиотеке сделать остальную работу за вас.

Почему это полезно 🔎

Automapper экономит ваше время и усилия, автоматизируя процесс сопоставления. С Automapper вам больше не нужно вручную писать утомительный и подверженный ошибкам код сопоставления. Вместо этого вы можете настроить способ сопоставления данных между классами, используя простые и интуитивно понятные файлы конфигурации.

Но Automapper не только экономит ваше время. Это также помогает предотвратить распространенные ошибки сопоставления и делает ваш код более удобным для сопровождения. С Automapper вы можете быть уверены, что ваши данные отображаются правильно и что любые изменения, которые вы вносите в свои классы, будут автоматически отражены в ваших сопоставлениях.

Клонируйте репозиторий GitHub 🐙

Прежде чем начать, убедитесь, что вы клонируете репозиторий GitHub, если вы хотите писать код вместе со мной, и убедитесь, что вы клонируете ветку «RepositoryPattern», которая содержит изменения, которые мы сделали в нашем последнем посте.

GitHub — Osempu/BlogAPI и RepositoryPattern

Давайте изменим нашу модель Post 📬

Наша модель довольно проста, и на самом деле свойства, которые у нас есть, — это свойства, которые мы хотим вернуть в наши конечные точки API, поэтому давайте добавим некоторые другие свойства, которые мы не хотим отображать. Мы собираемся добавить два свойства даты, одно для того, когда сообщение было создано, а другое для последнего обновления нашего сообщения.

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; }
}

Теперь, когда мы изменили нашу модель, мы должны обновить нашу базу данных, поэтому давайте добавим миграцию и обновим базу данных с помощью dotnet cli.

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

dotnet ef database update

Теперь наша база данных обновлена, чтобы содержать оба поля даты.

Создайте новый DTO ✔️

Чтобы правильно создать DTO, мы должны подумать о том, какие свойства нашей модели нам не нужны или которые мы не хотим раскрывать. Помните, что преимущества dtos заключаются в том, что мы можем ограничить размер полезной нагрузки, которую мы отправляем клиенту, только соответствующими полями, которые ему понадобятся, и что мы можем скрыть конфиденциальную информацию за нашим dto.

Поэтому давайте скроем наши свойства даты и времени, так как нам не нужно, чтобы клиент знал, когда была обновлена ​​запись. Также помните, что не все блоги отображают дату создания статьи, чтобы дать зрителю ощущение, что он просматривает недавнюю публикацию. .

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

Таким образом, наша модель PostDTO стала выглядеть так же, как наша модель Post до добавления свойств даты.

Теперь вы можете подумать, как это будет работать? ну, дело в том, что всякий раз, когда вы возвращаете модель Post со всеми ее свойствами, вы выполняете ручное сопоставление, чтобы вернуть PostDTO, предоставляя только желаемые свойства. Ниже приведен пример выполнения сопоставления вручную в конечной точке GetPost нашего 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);
}

Но представьте, что у вас есть более сложная модель, и вам нужно выполнить преобразование свойств, в этом случае выполнение этого сопоставления вручную может привести к ошибкам из-за выполнения этого процесса вручную, и здесь появляется автоматический преобразователь.

Картографирование объектов с помощью AutoMapper 🗺️

Давайте начнем установку пакета AutoMapper с помощью dotnet cli.

dotnet add package AutoMapper.Extensions.Microsoft.DependencyInjection

Перейдите к файлу Prorgram и добавьте AutoMapper новую службу.

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

После этого создайте новую папку с именем AutoMapperProfiles и внутри нее мы создадим новый класс с именем PostProfiles, который будет унаследован от Profile, и поместим конфигурацию в конструктор класса PostProfiles.

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

Мы вызываем метод Createmap и внутри угловых скобок с левой стороны мы помещаем исходный класс, который является нашей сущностью, а с правой стороны у нас есть класс назначения, который является нашим DTO. Таким образом, автоматический картограф будет теперь, когда мы хотим конвертировать из Post в PostDTO каждый раз, когда мы его вызываем.

Использование DTO в нашем контроллере 🎮

Все было настроено, поэтому мы можем использовать наш dto в нашем PostController. Итак, давайте добавим интерфейс IMapper в конструктор контроллера.

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;
}

Вот как должен выглядеть конструктор после добавления интерфейса IMapper, и теперь мы можем вызвать его из наших конечных точек, чтобы увидеть магию.

Обновление конечных точек Get 👾

[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;
    }
}

Нам нужно только обновить оба метода get, так как только они возвращают объект Post, в отличие от методов редактирования, публикации и удаления, которые возвращают методы Http, такие как no content или created at.

Как вы видите, реализация отображения довольно проста, нам нужно только вызвать метод mapper.Map<T>(), а затем передать Post, чтобы разобрать его в PostDTO.

Дайте ему тест 🧪

Теперь вы готовы протестировать обе конечные точки получения в нашем веб-API, и вы не заметите никаких изменений, на самом деле все будет работать, как и раньше, но мы знаем, что наш DTO скрывает некоторые свойства, которые мы не хотим отображать клиенту, а также можем скрывать конфиденциальную информацию, если это так.

Помните, что весь код, показанный в этом посте, будет доступен на GitHub.

Вывод 🌇

Как мы уже говорили в статье, DTO могут быть действительно полезны для уменьшения размера полезной нагрузки и улучшения взаимодействия с пользователем за счет отображения только релевантных данных, а также для защиты конфиденциальной информации, которую может содержать наш основной объект и которую лучше не раскрывать с наших конечных точек.

Сопоставление помогает нам сопоставлять наши объекты с простыми DTO, не делая это вручную и избегая потенциальных ошибок на пути, но стоит отметить, что некоторые программисты предпочитают реализовывать собственное ручное сопоставление, потому что некоторые библиотеки, такие как AutoMapper, используют отражение для работы, и это может замедлить работу. наше приложение.

Поддержите меня, если вам понравилась эта статья! 🫱🏽‍🫲🏾

Спасибо, что нашли время прочитать мою статью, если вы считаете, что она помогла вам или добавила ценность вашим знаниям, пожалуйста, поддержите меня, подписавшись на меня и следите за моей работой в моем блоге Unit Coding, а также на моем канале YouTube. В последнее время я ничего не загружаю на свой канал, но планирую это сделать в ближайшее время. Я надеюсь, что вы продолжите учиться и расти на своем пути программирования, и я надеюсь иметь честь идти вместе с вами. Спасибо и увидимся в моем следующем посте 😁