Search Results for

      Show / Hide Table of Contents

      Intent.Application.ServiceCallHandlers

      Implement service operations using individual handler classes instead of large service classes.

      What This Module Does

      This module enables the Service Call Handler pattern, where each service operation is handled by a dedicated handler class implementing a common interface. Instead of large service classes with many methods, you create focused, single-responsibility handler classes.

      When enabled, Intent generates:

      • One handler class per service operation
      • Handler base class with dependency injection setup
      • Dependency registration in DI container
      • Consistent handler invocation pattern

      Generated Artifacts

      Service Call Handler Classes

      For each service operation, generates:

      • IServiceCallHandler<TRequest, TResponse> - Handler interface
      • [OperationName]Handler : IServiceCallHandler<TRequest, TResponse> - Implementation
      • Handler accepts request object, returns response object
      • Handles operation logic, validation, and error scenarios

      Request/Response Objects

      • Request - Input parameters for the operation
      • Response - Output/return value from the operation
      • Automatically generated from service operation definition

      Handler Dispatcher

      • Resolves appropriate handler from dependency injection
      • Invokes handler with request
      • Captures and returns response
      • Enables consistent error handling across all operations

      Key Design Patterns

      Single Responsibility Principle

      Each handler has one reason to change: its specific operation

      • Easier to test individual operations
      • Clearer code organization and navigation
      • Simpler cognitive load per class

      Handler Interface Contract

      All handlers implement common interface:

      public interface IServiceCallHandler<TRequest, TResponse>
      {
          Task<TResponse> HandleAsync(TRequest request);
      }
      

      Dependency Injection

      Handler dependencies injected in constructor:

      • Repositories for data access
      • Domain services for business logic
      • Cross-cutting concerns (logging, validation)
      • Current user context

      Operation Composition

      Build complex operations from simpler handlers:

      • Reusable handler patterns across operations
      • Composition over inheritance
      • Mix and match handler behaviors

      Integration with Other Modules

      Required Dependencies

      • Intent.Application.ServiceImplementations - Service interface and container generation

      When To Use

      Use Service Call Handlers when:

      • Your service classes have 10+ operations
      • Operations are largely independent
      • You want maximum testability per operation
      • Team prefers focused, single-responsibility classes
      • You need clear operation-specific cross-cutting concerns

      Use traditional Service classes instead when:

      • Service has only 2-5 operations
      • Operations share significant common logic
      • You prefer fewer, larger classes
      • Team is unfamiliar with handler patterns

      Use MediatR Handlers instead when:

      • You want full CQRS pattern separation
      • You need sophisticated pipeline behaviors
      • Operations fit cleanly into Command/Query categories
      • Cross-cutting concerns are better expressed as pipeline behaviors

      Handler Pattern Example

      // Auto-generated Request DTO
      public class CreateProductRequest
      {
          public string Name { get; set; }
          public decimal Price { get; set; }
      }
      
      // Auto-generated Response DTO
      public class CreateProductResponse
      {
          public int ProductId { get; set; }
          public string Name { get; set; }
      }
      
      // Auto-generated Handler Interface
      public interface IServiceCallHandler<CreateProductRequest, CreateProductResponse>
      {
          Task<CreateProductResponse> HandleAsync(CreateProductRequest request);
      }
      
      // User-implemented Handler
      public class CreateProductHandler : IServiceCallHandler<CreateProductRequest, CreateProductResponse>
      {
          private readonly IProductRepository _repository;
          private readonly ICurrentUser _currentUser;
      
          public CreateProductHandler(IProductRepository repository, ICurrentUser currentUser)
          {
              _repository = repository;
              _currentUser = currentUser;
          }
      
          public async Task<CreateProductResponse> HandleAsync(CreateProductRequest request)
          {
              // Validate authorization
              if (!_currentUser.IsInRole("Admin"))
                  throw new UnauthorizedException();
      
              // Create entity
              var product = new Product { Name = request.Name, Price = request.Price };
              
              // Persist
              await _repository.AddAsync(product);
              await _repository.SaveChangesAsync();
      
              // Return response
              return new CreateProductResponse
              {
                  ProductId = product.Id,
                  Name = product.Name
              };
          }
      }
      

      Related Modules

      • Intent.Application.ServiceImplementations - Service interface generation and registration
      • Edit this page
      ☀
      ☾
      In this article
      Back to top Copyright © 2017-, Intent Architect Holdings Ltd