# DTO System > Part of `Mango.Nop.Core`. See `Mango.Nop.Core/README.md` for project overview. ## Two Mapping Strategies ### Strategy 1: `ModelDtoBase` (simple DTOs) Used by: `CustomerDto`, `MgGenericAttributeDto` ``` ModelDtoBase → ModelDtoBase → CustomerDto ``` - Manual `CopyEntityValuesToDto`/`CopyDtoValuesToEntity` overrides - `CreateMainEntity()` uses `Activator.CreateInstance()` - No LinqToDB associations ### Strategy 2: `MgEntityBase` + `IModelDtoBase` (complex DTOs) Used by: `MgOrderDto`, `MgOrderItemDto`, `MgStockQuantityHistoryDto` ``` BaseEntity → MgEntityBase → MgOrderDto : IModelDtoBase ``` - Uses `PropertyHelper.CopyPublicValueTypeProperties()` for bulk value-type copy - LinqToDB `[Association]` navigation properties - Generic type parameters for child DTOs ### Strategy 3: Entity inheritance (MgProductDto) ``` BaseEntity → MgEntityBase → MgProductDto : IMgProductDto ``` - No `IModelDtoBase` (entity mapping methods are commented out) - Direct property declarations mirroring `Product` fields ## DTO Types | Type | Generic params | Maps to entity | Key features | |---|---|---|---| | `ModelDtoBase` | — | — | Abstract base, `int Id` only | | `ModelDtoBase` | `TMainEntity : BaseEntity` | `TMainEntity` | `CreateMainEntity()`, `CopyEntityValuesToDto()`, `CopyDtoValuesToEntity()` | | `MgOrderDto` | `TOrderItemDto : IMgOrderItemDto`, `TProductDto : IMgProductDto` | `Order` | Has `Customer`, `List`, `List` navigations. Enum wrappers: `OrderStatus`, `ShippingStatus`, `PaymentStatus` | | `MgOrderItemDto` | `TProductDto : IMgProductDto` | `OrderItem` | Has `TProductDto?` navigation. Computed `ProductName` property | | `MgProductDto` | — | *(commented out)* | Base product DTO. Name, Price, StockQuantity, dimensions. No entity mapping methods (currently commented out) | | `MgGenericAttributeDto` | — | `GenericAttribute` | Inherits `GenericAttribute` directly (not `ModelDtoBase`). Full bidirectional mapping | | `MgStockQuantityHistoryDto` | `TProductDto : IMgProductDto` | `StockQuantityHistory` | Has `TProductDto` navigation. Mapping methods `NotImplementedException` (stub) | | `CustomerDto` | — | `Customer` | `Username`, `Email`, `FirstName`, `LastName`, `FullName` computed. Uses `[AcBinarySerializable]` and LinqToDB `[Table]` | ## DTO Interfaces | Interface | Extends | Purpose | |---|---|---| | `IModelDtoBase` | `IEntityInt`, `IModelDtoBaseEmpty` | Marker for all DTOs with `int Id` | | `IModelDtoBase` | `IModelDtoBase` | Bidirectional mapping contract: `CreateMainEntity()`, `CopyDtoValuesToEntity()`, `CopyEntityValuesToDto()` | | `IMgOrderDto` | `IEntityInt`, `ISoftDeletedEntity` | Order DTO contract with navigation properties and initialization methods | | `IMgOrderItemDto` | `IEntityInt` | Order item DTO contract with product navigation | | `IMgProductDto` | `IEntityInt`, `ILocalizedEntity`, `ISlugSupported`, `IAclSupported`, `IStoreMappingSupported`, `ISoftDeletedEntity` | Product DTO contract | ## GenericAttribute Typed Access `GenericAttributeExtensions` provides typed access to nopCommerce's polymorphic key-value store: | Method | Signature | Purpose | |---|---|---| | `GetValueOrNull` | `(IEnumerable, string key) -> TValue?` | Get typed value, returns null if not found | | `GetValueOrDefault` | `(IEnumerable, string key, TValue default) -> TValue` | Same with default fallback | | `TryGetValue` | `(IEnumerable, string key, out TValue?) -> bool` | Try-pattern for GA value | | `AddNewGenericAttribute` | `(ICollection, ...) -> GenericAttribute` | Create and add new GA with UTC timestamp | **Rule:** Always use these extension methods — never parse `GenericAttribute.Value` strings manually.