Overview
The Intent.Application.Contracts module generates service interface contracts that define the public API of your application services. This promotes the Interface Segregation Principle and enables clean separation between interface definitions and implementations.
Module : Intent.Application.ContractsVersion : 5.1.2+Dependencies :
Intent.Application.Dtos
Intent.Common.CSharp
Intent.Modelers.Services
Key Features
Clean Architecture : Separate interface definitions from implementations
Service Contracts : Generate strongly-typed service interfaces
Async Support : Automatic Task<T> return types and CancellationToken parameters
DTO Integration : Seamless integration with DTO types
XML Documentation : Preserve comments from designer
Generic Operations : Support for generic type parameters
Installation
intent install Intent.Application.Contracts
Architecture Benefits
Service contracts enable:
Dependency Inversion Depend on abstractions, not implementations
Testability Easy mocking and unit testing
Modularity Clear boundaries between modules
Flexibility Swap implementations without changing consumers
Generated Service Contracts
Basic Service Interface
Designer Definition
Generated Interface
// ProductService (in Services Designer)
// Operations:
// - GetProduct(id: Guid): ProductDto
// - GetAllProducts(): List<ProductDto>
// - CreateProduct(dto: CreateProductDto): Guid
// - UpdateProduct(id: Guid, dto: UpdateProductDto): void
// - DeleteProduct(id: Guid): void
Async by Default
All service operations are generated as async by default:
Return types wrapped in Task<T>
CancellationToken parameter added automatically
Follows async best practices
The Async suffix is automatically added to method names following .NET async conventions.
XML Documentation
Comments from the Services Designer are preserved:
Designer Comments
Generated Interface
// Operation: GetProduct
// Description: Retrieves a product by its unique identifier
// Parameter id: The unique identifier of the product
// Returns: The product details if found, null otherwise
Service Implementation
Implement the generated interface:
using MyApp . Application . Interfaces ;
using MyApp . Domain . Repositories ;
public class ProductService : IProductService
{
private readonly IProductRepository _repository ;
private readonly IMapper _mapper ;
public ProductService (
IProductRepository repository ,
IMapper mapper )
{
_repository = repository ;
_mapper = mapper ;
}
public async Task < ProductDto > GetProductAsync (
Guid id ,
CancellationToken cancellationToken )
{
var product = await _repository . FindByIdAsync ( id , cancellationToken )
?? throw new NotFoundException ( nameof ( Product ), id );
return _mapper . Map < ProductDto >( product );
}
public async Task < List < ProductDto >> GetAllProductsAsync (
CancellationToken cancellationToken )
{
var products = await _repository . FindAllAsync ( cancellationToken );
return _mapper . Map < List < ProductDto >>( products );
}
public async Task < Guid > CreateProductAsync (
CreateProductDto dto ,
CancellationToken cancellationToken )
{
var product = new Product
{
Name = dto . Name ,
Price = dto . Price ,
// ... map other properties
};
await _repository . AddAsync ( product , cancellationToken );
return product . Id ;
}
public async Task UpdateProductAsync (
Guid id ,
UpdateProductDto dto ,
CancellationToken cancellationToken )
{
var product = await _repository . FindByIdAsync ( id , cancellationToken )
?? throw new NotFoundException ( nameof ( Product ), id );
product . Name = dto . Name ;
product . Price = dto . Price ;
// ... update other properties
await _repository . UpdateAsync ( product , cancellationToken );
}
public async Task DeleteProductAsync (
Guid id ,
CancellationToken cancellationToken )
{
var product = await _repository . FindByIdAsync ( id , cancellationToken )
?? throw new NotFoundException ( nameof ( Product ), id );
await _repository . RemoveAsync ( product , cancellationToken );
}
}
Dependency Injection
Register interfaces and implementations:
services . AddScoped < IProductService , ProductService >();
services . AddScoped < IOrderService , OrderService >();
services . AddScoped < ICustomerService , CustomerService >();
Intent Architect modules automatically generate DI registration code. You typically don’t need to manually register services.
Advanced Features
Generic Operations
Service operations can have generic type parameters:
Designer Definition
Generated Interface
Implementation
// Operation: GetById<T>(id: Guid): T
Complex Return Types
Supports complex return types including:
public interface IOrderService
{
// Paginated results
Task < PagedResult < OrderDto >> GetOrdersAsync (
int pageNo ,
int pageSize ,
CancellationToken cancellationToken = default );
// Collections
Task < List < OrderDto >> GetOrdersByCustomerAsync (
Guid customerId ,
CancellationToken cancellationToken = default );
// Nullable results
Task < OrderDto ?> FindOrderAsync (
string orderNumber ,
CancellationToken cancellationToken = default );
// Void operations
Task CancelOrderAsync (
Guid id ,
CancellationToken cancellationToken = default );
// Tuples
Task <( int TotalOrders , decimal TotalRevenue )> GetOrderStatisticsAsync (
CancellationToken cancellationToken = default );
}
Parameter Attributes
The module preserves parameter attributes from stereotypes:
public interface IProductService
{
Task < ProductDto > GetProductAsync (
[ FromRoute ] Guid id ,
CancellationToken cancellationToken = default );
Task < List < ProductDto >> SearchProductsAsync (
[ FromQuery ] string searchTerm ,
[ FromQuery ] int ? minPrice ,
[ FromQuery ] int ? maxPrice ,
CancellationToken cancellationToken = default );
Task < Guid > CreateProductAsync (
[ FromBody ] CreateProductDto dto ,
CancellationToken cancellationToken = default );
}
Testing
Service contracts make unit testing straightforward:
Mocking with Moq
public class ProductControllerTests
{
private readonly Mock < IProductService > _mockProductService ;
private readonly ProductController _controller ;
public ProductControllerTests ()
{
_mockProductService = new Mock < IProductService >();
_controller = new ProductController ( _mockProductService . Object );
}
[ Fact ]
public async Task GetProduct_WithValidId_ReturnsProduct ()
{
// Arrange
var productId = Guid . NewGuid ();
var expectedProduct = new ProductDto
{
Id = productId ,
Name = "Test Product" ,
Price = 29.99m
};
_mockProductService
. Setup ( s => s . GetProductAsync ( productId , It . IsAny < CancellationToken >()))
. ReturnsAsync ( expectedProduct );
// Act
var result = await _controller . GetProduct ( productId , CancellationToken . None );
// Assert
var okResult = Assert . IsType < OkObjectResult >( result );
var product = Assert . IsType < ProductDto >( okResult . Value );
Assert . Equal ( expectedProduct . Id , product . Id );
Assert . Equal ( expectedProduct . Name , product . Name );
}
[ Fact ]
public async Task CreateProduct_WithValidDto_ReturnsCreatedProduct ()
{
// Arrange
var createDto = new CreateProductDto
{
Name = "New Product" ,
Price = 39.99m
};
var newProductId = Guid . NewGuid ();
_mockProductService
. Setup ( s => s . CreateProductAsync ( createDto , It . IsAny < CancellationToken >()))
. ReturnsAsync ( newProductId );
// Act
var result = await _controller . CreateProduct ( createDto , CancellationToken . None );
// Assert
var createdResult = Assert . IsType < CreatedAtActionResult >( result );
Assert . Equal ( newProductId , createdResult . Value );
}
}
Integration Testing
Test real implementations:
public class ProductServiceIntegrationTests : IClassFixture < WebApplicationFactory < Program >>
{
private readonly WebApplicationFactory < Program > _factory ;
private readonly IServiceScope _scope ;
private readonly IProductService _productService ;
public ProductServiceIntegrationTests ( WebApplicationFactory < Program > factory )
{
_factory = factory ;
_scope = _factory . Services . CreateScope ();
_productService = _scope . ServiceProvider . GetRequiredService < IProductService >();
}
[ Fact ]
public async Task CreateAndRetrieveProduct_Success ()
{
// Arrange
var createDto = new CreateProductDto
{
Name = "Integration Test Product" ,
Price = 49.99m
};
// Act - Create
var productId = await _productService . CreateProductAsync (
createDto ,
CancellationToken . None );
// Act - Retrieve
var retrievedProduct = await _productService . GetProductAsync (
productId ,
CancellationToken . None );
// Assert
Assert . NotNull ( retrievedProduct );
Assert . Equal ( createDto . Name , retrievedProduct . Name );
Assert . Equal ( createDto . Price , retrievedProduct . Price );
}
}
Naming Conventions
The module automatically applies naming conventions:
Service Name Generated Interface ProductServiceIProductServiceOrderServiceIOrderServiceProductRestControllerIProductService (removes “RestController”)OrderControllerIOrderService (removes “Controller”)
The “Service” suffix is always used in the interface name regardless of the original service name.
Default Output Location
Generated contracts are placed in:
YourProject.Application/Interfaces/
You can customize this location in the template configuration.
Best Practices
Each service interface should represent a cohesive set of operations related to a single bounded context or aggregate. // ✅ Good - Cohesive
public interface IProductService
{
Task < ProductDto > GetProductAsync (...);
Task < Guid > CreateProductAsync (...);
Task UpdateProductAsync (...);
Task DeleteProductAsync (...);
}
// ❌ Bad - Too broad
public interface IEverythingService
{
Task < ProductDto > GetProductAsync (...);
Task < OrderDto > GetOrderAsync (...);
Task < CustomerDto > GetCustomerAsync (...);
// ...
}
Use DTOs for All Parameters
Avoid exposing domain entities in service interfaces. Use DTOs for all inputs and outputs. // ✅ Good
Task < ProductDto > GetProductAsync ( Guid id , ...);
Task < Guid > CreateProductAsync ( CreateProductDto dto , ...);
// ❌ Bad
Task < Product > GetProductAsync ( Guid id , ...);
Task < Guid > CreateProductAsync ( Product product , ...);
Always Include CancellationToken
All async operations should accept a CancellationToken for proper cancellation support. // ✅ Good
Task < ProductDto > GetProductAsync (
Guid id ,
CancellationToken cancellationToken = default );
// ❌ Bad
Task < ProductDto > GetProductAsync ( Guid id );
The module adds CancellationToken parameters automatically.
Document Public Contracts
Add XML documentation in the Services Designer for all operations and parameters. This documentation flows through to generated code and API documentation.
Integration with Other Modules
Service Implementations Generate service implementations
MediatR CQRS pattern with MediatR
ASP.NET Core Controllers Expose services via REST APIs
Contracts Clients Generate client proxies
Troubleshooting
Issue : Service interface not created after running Software Factory.Solution :
Verify the module is installed
Check that the service has operations defined
Ensure the service is in a Services Designer package
Run Software Factory again
Issue : Generated method signatures don’t match expectations.Solution :
Check operation return types in designer
Verify parameter types are correctly mapped
Ensure DTOs are properly generated
Review any applied stereotypes
Release Notes
For detailed version history, see the module changelog .