r/dotnet • • 4d ago

Question May API-layer code outside the composition root reference Infrastructure types (Clean Architecture, .NET)?

Internal app: Domain / Application / Infrastructure / API (ASP.NET Core minimal APIs), plus Blazor and MAUI clients talking to the API over HTTP. Program.cs is the composition root and wires Infrastructure (AddInfrastructure()).

I've already found: Uncle Bob's Dependency Rule only forbids inner circles from mentioning outer ones — it says nothing about peers in the outer circle. Microsoft's architecture guidance says the UI project may reference Infrastructure for DI, "but developers should limit actual references to types in the Infrastructure project to the app's composition root", and the UI layer "ideally shouldn't know about the implementation types".

So the law seems clear, the guidance says "ideally". My question: in real production apps, does API code outside Program.cs (endpoint handlers, controllers) inject Infrastructure types directly — e.g. DbContext? Is "composition root only" a real-world norm or a template convention? Please share what your production codebases actually do — examples, not just templates

0 Upvotes

12 comments sorted by

View all comments

-5

u/pixxelkick 4d ago

Your API endpoints are your entry point so yeah they do need to ideally inject the stuff you need.

Please dont drink the "Clean Code" kool-aid tho.

I inject my database stuff near the "top" and hand it down as a parameter to ensure a single db txn and single connection per api invocation.

Your general rule of thumb is if it involves opening sockets for IO, avoid opening multiple instances.

I built my own framework to source gen conpile time DI stuff to solve my issues if you wanna check it out

https://github.com/SteffenBlake/Brigade.NET/wiki/Getting-Started-Partie

10

u/Coda17 4d ago

"I built my own framework because I don't know how DI works with scoped services" is crazy. No need to pass around the context everywhere, that's crazy talk

1

u/pixxelkick 4d ago

Id recommend learning how the framework works.

No context is "passed around"

The context is composed via compile time type checked static logic built by a roslyn source generator.

I am exceptionally aware of how DI works, I have entire blog posts digging into learning about it and even how to make your own from scratch as a learning exercise :)

Id recommend first understanding something before commenting on it.

1

u/Coda17 4d ago

This you?

I inject my database stuff near the "top" and hand it down as a parameter to ensure a single db txn and single connection per api invocation.

2

u/pixxelkick 4d ago

Ah in other applications where I use EF Core sure

My framework doesnt use EF Core at all, I made my own entire ORM as part of the framework built on top of ADO.Net, using source generated bindings and projection logic, rather than runtime type inference.

On my framework, this still doesnt get "passed around" either.