A serializer controls how ASP.NET Core turns controller results into JSON responses. It can be adjusted locally on model properties or globally through JSON options, making response shape an explicit API design choice. section 19.5.6
Choose the narrowest configuration that keeps the response predictable:
- Project selected properties into an anonymous object when an endpoint needs precise control over its response. section 19.5.6
- Apply JsonIgnore with WhenWritingNull to omit one nullable property while returning the model directly. section 19.5.6
- Set JsonSerializerOptions.DefaultIgnoreCondition for a general policy, remembering that it affects every JSON response. section 19.5.6
- Treat related Entity Framework Core entities carefully: Include can create circular navigation-property references that serialization rejects as an object cycle. section 20.2
Omit a null supplier
Annotate Product.Supplier with [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]. Returning the Product directly then produces JSON containing productId, name, price, categoryId, and supplierId without a null supplier property.
Listing 19.32 Configuring the serializer in the Program.cs file in the WebApp folder
using Microsoft.EntityFrameworkCore;
using WebApp.Models;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json.Serialization;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<DataContext>(opts => {
opts.UseSqlServer(builder.Configuration[
"ConnectionStrings:ProductConnection"]);
opts.EnableSensitiveDataLogging(true);
});
builder.Services.AddControllers();
builder.Services.Configure<JsonOptions>(opts => {
opts.JsonSerializerOptions.DefaultIgnoreCondition
= JsonIgnoreCondition.WhenWritingNull;
});
var app = builder.Build();
app.MapControllers();
app.MapGet("/", () => "Hello World!");
var context = app.Services.CreateScope().ServiceProvider
.GetRequiredService<DataContext>();
SeedData.SeedDatabase(context);
app.Run();
Inspect the Program.cs configuration that applies WhenWritingNull through JsonOptions to all JSON responses. section 19.5.6
Listing 20.4 Related data in the SuppliersController.cs file in the Controllers folder
using Microsoft.AspNetCore.Mvc;
using WebApp.Models;
using Microsoft.EntityFrameworkCore;
namespace WebApp.Controllers {
[ApiController]
[Route("api/[controller]")]
public class SuppliersController : ControllerBase {
private DataContext context;
public SuppliersController(DataContext ctx) {
context = ctx;
}
[HttpGet("{id}")]
public async Task<Supplier?> GetSupplier(long id) {
return await context.Suppliers
.Include(s => s.Products)
.FirstAsync(s => s.SupplierId == id);
}
}
}
Compare the Include query that loads Supplier.Products with the resulting circular relationship between Supplier and Product. section 20.2



