Table of Contents

Business assemblies

When you create a business assembly in Neos Studio, it generates C# projects following Clean Architecture principles.

Create business assemblies

To create business assemblies for a module in Neos Studio:

  1. Open the module's screen
  2. Navigate to the Business Assemblies tab
  3. Click the Create projects button

A dialog appears allowing you to configure the project generation:

  • Layers: Select which layers to generate (Domain, Application, or both)
  • Unit test projects: Choose whether to generate the associated unit test projects (Domain.Tests.UnitTests and Application.Tests.UnitTests)
Tip

If you only need to implement entity validation rules or event rules that don't require application services, you can generate only the Domain layer. You can always add the Application layer later if needed.

Project structure

modules/
└── MyModule/
    └── businessAssembly/
        ├── Domain/                    # Domain layer
        │   ├── EventRules/            # Entity event rules
        │   ├── ValidationRules/       # Entity validation rules
        │   ├── Startup.cs             # Service registration (optional, manually created)
        ├── Domain.Tests.UnitTests/    # Domain tests
        ├── Application/               # Application layer
        │   ├── DomainValidationRules/ # Entity validation rules needing Application services
        │   ├── DomainEventRules/      # Entity event rules needing Application services
        │   ├── EventRules/            # Entity view event rules
        │   ├── Methods/               # Server methods
        │   ├── ValidationRules/       # Entity view validation rules
        │   ├── Startup.cs             # Service registration (optional, manually created)
        └── Application.Tests.UnitTests/  # Application tests
Note

Beyond the directories created by Neos Studio for validation rules, event rules, and server methods, you are free to organize your business assemblies as you see fit. You can create additional directories such as Helpers/, Services/, Extensions/, or any structure that suits your project. You can also add classes anywhere within the project.

Server methods can be further organized in subfolders within the Methods/ directory (e.g., Methods/Orders/CreateOrder.cs). The Neos code generator determines the expected namespace based on the folder structure. For more details, see Organizing server method files.

Startup class

The Startup.cs file is not automatically generated by the framework. You can create it manually in your business assembly when you need to register custom services for dependency injection. If the file exists, the framework will automatically discover and call the ConfigureServices method at startup. For detailed instructions, see Register additional services.

// Domain layer Startup.cs
public static class Startup
{
    public static void ConfigureServices(IServiceCollection services)
    {
        // Register domain services
        services.AddScoped<IDashboardHelper, DashboardHelper>();
        services.AddScoped<IOrderValidator, OrderValidator>();
    }
}
// Application layer Startup.cs
public static class Startup
{
    public static void ConfigureServices(IServiceCollection services)
    {
        // Register application services
        services.AddScoped<IOrderService, OrderService>();
        services.AddTenantDatabaseMigrationInterceptor<MyMigrationInterceptor>();
    }
}

Repositories and data access

Neos implements the repository pattern to abstract data access, following Clean Architecture principles:

  • Domain layer: Defines repository interfaces (IRepository<TEntity>)
  • Infrastructure layer: Implements repositories using Entity Framework Core
  • Application layer: Uses IEntityViewRepository<TEntityView> for entity views
// Domain layer - uses entity repository
public class OrderDomainService
{
    private readonly IRepository<Order> _orderRepository;

    public OrderDomainService(IRepository<Order> orderRepository)
    {
        _orderRepository = orderRepository;
    }
}

// Application layer - can use entity view repository
public class OrderApplicationService
{
    private readonly IEntityViewRepository<IOrderView> _orderViewRepository;

    public OrderApplicationService(IEntityViewRepository<IOrderView> orderViewRepository)
    {
        _orderViewRepository = orderViewRepository;
    }
}

For more details, see the Repositories documentation and the Unit of Work pattern.

Testing strategy

Clean Architecture enables effective testing strategies at each layer:

Layer Test Type Dependencies
Domain Unit tests Mocked repositories only
Application Unit tests Mocked domain services and repositories
End-to-End E2E tests Full application stack
// Domain layer test - minimal dependencies
public class CheckOrderTotalTests : ValidationRuleTest<CheckOrderTotal, Order>
{
    [Fact]
    public async Task Validate_WhenOrderTotalIsNegative_ShouldReturnError()
    {
        // Arrange
        Order order = new();
        order.Total = -100;
                
        // Act
        IValidationRuleResult result = await ExecuteValidationRuleAsync(order);
        
        // Assert
        result.IsSuccess.Should().BeFalse();
    }
}

For detailed guidance on testing your code in Visual Studio, see Testing your code in Visual Studio.

See also