ABP project layer dependency rules - which projects can reference which, domain/application/infrastructure separation, cross-layer violations to avoid. Use when reviewing project structure, adding new project references, or checking if a dependency direction is correct.
These principles apply regardless of solution structure:
Note: This section applies to layered templates (app, module). Single-layer and microservice templates have different structures.
Domain.Shared → Constants, enums, localization keys
↑
Domain → Entities, repository interfaces, domain services
↑
Application.Contracts → App service interfaces, DTOs
↑
Application → App service implementations
↑
HttpApi → REST controllers (optional)
↑
Host → Final application with DI and middleware
| Project | Can Reference | Referenced By |
|---|---|---|
| Domain.Shared | Nothing | All |
| Domain | Domain.Shared | Application, Data layer |
| Application.Contracts | Domain.Shared | Application, HttpApi, Clients |
| Application | Domain, Contracts | Host |
| EntityFrameworkCore/MongoDB | Domain | Host only |
| HttpApi | Contracts only | Host |
// Application layer accessing DbContext directly
public class BookAppService : ApplicationService
{
private readonly MyDbContext _dbContext; // ❌ WRONG
}
// Domain depending on application layer
public class BookManager : DomainService
{
private readonly IBookAppService _appService; // ❌ WRONG
}
// HttpApi depending on Application implementation
public class BookController : AbpController
{
private readonly BookAppService _bookAppService; // ❌ WRONG - Use interface
}
// Application layer using repository abstraction
public class BookAppService : ApplicationService
{
private readonly IBookRepository _bookRepository; // ✅ CORRECT
}
// Domain service using domain abstractions
public class BookManager : DomainService
{
private readonly IBookRepository _bookRepository; // ✅ CORRECT
}
// HttpApi depending on contracts only
public class BookController : AbpController
{
private readonly IBookAppService _bookAppService; // ✅ CORRECT
}
// In Domain project
public interface IBookRepository : IRepository<Book, Guid>
{
Task<Book> FindByNameAsync(string name);
}
// In EntityFrameworkCore project
public class BookRepository : EfCoreRepository<MyDbContext, Book, Guid>, IBookRepository
{
// Implementation
}
// In MongoDB project
public class BookRepository : MongoDbRepository<MyDbContext, Book, Guid>, IBookRepository
{
// Implementation
}
When you have multiple applications (e.g., Admin + Public API):
MyProject.Admin.Application - Admin-specific services
MyProject.Public.Application - Public-specific services
MyProject.Domain - Shared domain (both reference this)
When adding a new feature:
| Violation | Impact | Fix |
|---|---|---|
| DbContext in Application | Breaks DB independence | Use repository |
| Entity in DTO | Exposes internals | Map to DTO |
| IQueryable in interface | Breaks abstraction | Return concrete types |
| Cross-module app service call | Tight coupling | Use events or domain |