TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #832 1.15K
День шестьсот семьдесят второй. #ЗаметкиНаПолях
Ваш API и Модели Представления не Должны Использовать Модели Домена
Вы должны быть осторожны с тем, что вы раскрываете в своих клиентских моделях. Модели, предоставляемые клиенту, обычно находятся на уровне пользовательского интерфейса как ViewModels или ApiModels. Их также можно назвать DTO (Domain Transfer Objects - Объекты Передачи Данных). В любом случае они не должны напрямую ссылаться на типы из модели предметной области.

Чтобы понять, почему, давайте посмотрим, почему мы вообще используем DTO и ViewModels/ApiModels. Зачем несколько типов для описания того, что в системе, скорее всего, представляет одно и то же? Допустим, у меня есть веб-сайт, где пользователи могут проходить тесты. У каждого теста есть название, описание и набор вопросов. Моя модель предметной области для теста включает в себя некоторую бизнес-логику чтобы удостовериться, что в тесте есть хотя бы один вопрос, вопросы не повторяются и т.п.

Мне нужно, чтобы администратор мог добавить новый тест или обновить существующий. Я не хочу предоставлять доступ ко всем свойствам теста. Например, чтобы тест можно было создать с любым названием. А у созданного теста нельзя было изменить название, но можно менять описание или вопросы. Я создам типы ViewModel или ApiModel для конкретной операции, которую выполняет пользователь. Для создания теста может использоваться такой класс:
public class CreateTestViewModel {
public string Name {get;set;}
public string Description {get;set;}
}


А реальная сущность домена для теста могла бы выглядеть так:
// BaseEntity<T> определяет тип поля Id
public class Test : BaseEntity<Guid> {
public string Name { get; set; }
public string Description { get; set; }
public ApplicationUser Author { get; set; }
public List<Exercise> Exercises { get; set; }
}


Если бы вместо CreateTestViewModel использовался тип Test, конечные пользователи потенциально могли бы получить доступ к полному состоянию объекта Test. Привязка модели сопоставит все данные JSON или формы с данными модели. В документации к API может быть сказано, что должны передаваться только название и описание, но злоумышленник может угадать другие свойства сущности домена и изменять их, передавая значения. Если серверный код написан небрежно, он молча примет всё, что отправляет пользователь, и сохранит данные в хранилище с помощью простых команд EF, таких как Add() и SaveChanges().

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

Ещё одна причина использовать DTO - это сериализация. Часто типы моделей предметной области имеют закрытые конструкторы по умолчанию и неизменяемые свойства, которые получают значения только при создании экземпляра. Если вы попытаетесь использовать эти типы в API или в привязке модели MVC, вы, вероятно, столкнетесь с проблемами десериализации, поскольку у этих типов нет публичного конструктора по умолчанию.

Следите за Выражениями Using
Самый простой способ избежать проникновения модели предметной области в DTO - посмотреть на операторы using в этих классах. Часто ссылки на модели предметной области попадают в ваши DTO, потому что они добавляются как свойства:
public class TestDTO {
//…
public List<Exercise> Exercises { get; set; }
}


Убедитесь, что типы свойств сами являются DTO. Следите за тем, чтобы пространство имён домена не использовалось в определениях классов DTO. Можно следить за этим вручную или создать правило в таком инструменте, как NDepend.

Источник: https://www.c-sharpcorner.com/blogs/attributes-for-record-properties-in-c-sharp-9
More from @netdeveloperdiary
  1. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  2. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  3. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  4. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
  5. Oct 5, 2026День 2805. #ЧтоНовенького #NET11 Аргументы в Выражениях Коллекций в C#15 В C#15 реализован…
  6. Oct 4, 2026День 2804. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →