I've been trying to get away from using AutoMapper, since everyone seems to think it's the devil. Because of this, I've been putting all of my mapping into the DBO and DTO models that I'm handing back and forth. However, this quickly causes a looping problem within the EF framework when it tries to link the objects together.
/* Program.cs File */
using Microsoft.EntityFrameworkCore;
using Scalar.AspNetCore;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.AddJsonOptions(options => {
options.JsonSerializerOptions.MaxDepth = 256;
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
});
builder.Services.AddOpenApi();
builder.Services.AddDbContext<DBContext>(options => {
options.UseSqlServer("Name=ConnectionStrings:Orders");
});
builder.Services
.AddScoped<IOrderActor, OrderActor>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
app.MapScalarApiReference();
}
app.MapControllers();
app.Run();
public class Order {
public Order() {
ID = 0;
Name = string.Empty;
OrderDate = DateTime.Now;
Items = [];
}
public Order(OrderDTO dto) {
ID = dto.ID;
Name = dto.Name;
OrderDate = dto.OrderDate;
Items = dto.Items.Select(i => new OrderItem(i));
}
public int ID {get; set;}
public string Name {get; set;} = null!;
public DateTime OrderDate {get; set;} = null!;
public IEnumerable<OrderItem> Items {get; set;} = [];
}
public class OrderDTO {
public OrderDTO() {
ID = 0;
Name = string.Empty;
OrderDate = DateTime.Now;W
Items = [];
}
public OrderDTO(Order dbo) {
ID = dbo.ID;
Name = dbo.Name;
OrderDate = dbo.OrderDate;
Items = dbo.Items.Select(i => new OrderItemDTO(i));
}
public int ID {get; set;}
public string Name {get; set;} = null!;
public DateTime OrderDate {get; set;} = null!;
public IEnumerable<OrderItemDTO> Items {get; set;} = [];
}
public class OrderItem {
public OrderItem() {
ID = 0;
Name = string.Empty;
Price = 0;
Order = new Order();
}
public OrderItem(OrderItemDTO dto) {
ID = dto.ID;
Name = dto.Name;
Price = dto.Price;
Order = new Order(dto.Order);
}
public int ID {get; set;}
public string Name {get; set;}
public decimal Price {get; set;}
public Order Order {get; set;} = null!;
}
public class OrderItemDTO {
public OrderItemDTO() {
ID = 0;
Name = string.Empty;
Price = 0;
Order = new OrderDTO();
}
public OrderItemDTO(OrderItem dbo) {
ID = dbo.ID;
Name = dbo.Name;
Price = dbo.Price;
Order = new OrderDTO(dbo.Order);
}
public int ID {get; set;}
public string Name {get; set;}
public decimal Price {get; set;}
public OrderDTO Order {get; set;} = null!;
}
I have a web service that is trying to output a list of orders with their order items like so:
public class OrderActor(DBContext context) {
public async Task<List<OrderDTO>> GetAllOrders() {
return await context.Orders
.AsNoTracking()
.Select(o => new OrderDTO(o))
.ToListAsync();
}
}
[ApiController]
[Route("[controller]")]
public class OrderController(OrderActor actor) : ControllerBase {
[HttpGet]
[Route("GetAllOrders")]
public async Task<List<OrderDTO>> GetAllOrders() {
return await actor.GetAllOrders();
}
}
Since I have OpenAPI set up, it's trying to rip through this and as it does, it hits this problem.
System.Text.Json.JsonReaderException: The maximum configured depth of 64 has been exceeded. Cannot read next JSON object.
So, am I doing the mapping wrong? And if so, how should the mapping work between my DBO and DTO?
EDIT: So, much of this seems to be coming from using OpenAPI and Scalar. When my Scalar frontend starts up, that's what fails the entire thing. So maybe Scalar is doing something to try and set up the model list?