A data transfer object (DTO) carries data between services or between a client and a server. In an online shop, the API returns product DTOs to the UI. The DTO contains the values the UI needs to display, while the database entity can retain fields used for storage, such as its identity field. section 3.2.1
namespace OnlineShop.ServiceDefaults.Dtos;
public record ProductDto(
string Title,
string Summary,
decimal Price
);
ProductDto is a C# record containing Title, Summary, and Price. Unlike the Product entity, it has no database identity or DateAdded field. section 3.2.1
The separate type keeps the UI database-agnostic: the API can change its database implementation without requiring the presentation layer to work with database entities. Both sides exchange the product-shaped DTO instead. section 3.2.2
Listing 3.1 HTTP client for retrieving product data
using OnlineShop.ServiceDefaults.Dtos;
namespace OnlineShop.Web;
public class ProductsApiClient(HttpClient httpClient)
{
public async Task<ProductDto[]> GetProductsAsync(int maxItems = 10, CancellationToken cancellationToken = default)
{
List<ProductDto>? products= null;
await foreach (var product in
httpClient.GetFromJsonAsAsyncEnumerable<ProductDto>(
"/products", cancellationToken)) #1
{
if (products?.Count >= maxItems) #2
{
break;
}
if (product is not null)
{
products ??= [];
products.Add(product);
}
}
return products?.ToArray() ?? []; #3
}
}
ProductsApiClient requests /products and reads the JSON response as ProductDto values, returning up to the requested number of products. section 3.2.2
Listing 3.2 Home page displaying the product data
@page "/"
@using OnlineShop.ServiceDefaults.Dtos
@attribute [StreamRendering(true)]
@attribute [OutputCache(Duration = 5)]
@inject ProductsApiClient ProductsApi
<PageTitle>Products</PageTitle>
<h1>Products</h1>
@if (products == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Price (USD)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var product in products)
{
<tr>
<td>@product.Title</td>
<td>@product.Price</td>
<td>@product.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private ProductDto[]? products;
protected override async Task OnInitializedAsync()
{
products = await ProductsApi.GetProductsAsync();
}
}
The home page consumes those DTOs and renders each product’s title, price, and summary. section 3.2.2





