How to implement HTTP's PUT that works with child collections when using DDD's rich domain models?
Let's say we've got an aggregate root with a nicely encapsulated collection of items:
(I omitted persistence specific properties like Id for brevity)
public class Foo : IAggregateRoot
{
private readonly List<Bar> _items = new List<Bar>();
public IReadOnlyCollection<Bar> Items => _items;
public void AddItem(Bar bar)
{
_items.Add(bar);
}
public void RemoveItem(Bar bar)
{
_items.Remove(bar);
}
}
Now we want to implement PUT /foos/{id}
where you pass DTO like:
public class FooDto
{
public IEnumerable<BarDto> Items { get; set }
}
Now the problem is we can't simply map FooDto
to Foo
. It becomes a complex problem to solve, especially when you want to remove some Bar
from Items
.
We're left with two options:
- Create 2 separate routes for adding and removing items, like
POST /foos/{id}/items
andDELETE /foos/{fooId}/items/{itemId}
- Write some twisted logic to compare changes in collection and based on that deduce what was added and removed and call
AddItem
orRemoveItem
respectively
Is there anything I am missing here or doing wrong? Would I be better off using anemic domain models to simplify implementation of Web API? That would mean Web API would dictate how my domain models should look like and I think it's a bit wrong.
A similar question I've found while looking for solutions: Do RESTful APIs tend to encourage anemic domain models?
Best Answer
I wouldn't consider your option #2 as "twisted logic".
You just need an equality function (something to determine if two
Bar
s are the same) and then:I don't know C#, but in pseudo-code could be something like this: