Application operations
Registration and lookup belong to an application service, so HTTP, console and batch callers can share the same policy. This step uses the Customer model and validator; the next step supplies CustomerRepository. Keep one copy of each declaration.
Place this class in CustomerRegistrationService.ds in the same application assembly as CustomerRepository and CustomerValidator. It contains no HTTP types, so console, import and web callers can share it.
import Global.System
import Global.FluentValidation.Results
public class CustomerRegistrationService
private readonly repository as CustomerRepository
private readonly validator as CustomerValidator
public constructor(storage as CustomerRepository, inputRules as CustomerValidator)
require storage is not nothing
require inputRules is not nothing
repository = storage
validator = inputRules
end constructor
public action Check(customer as Customer)
returns ValidationResult
require customer is not nothing
return validator.Validate(customer)
end action
public async action RegisterAsync(customer as Customer)
returns Guid
require customer is not nothing
require Check(customer).IsValid
Cancellation.ThrowIfCanceled()
customer.Id = Guid.NewGuid()
customer.IsActive = false
await repository.AddAsync(customer)
return customer.Id
end action
public async action FindAsync(id as Guid)
returns Customer
return await repository.FindAsync(id)
end action
end class
RegisterAsync assigns the identifier itself and starts the customer inactive. Its precondition protects non-HTTP callers as well. The controller validates before calling it so ordinary input errors produce a response, while the service independently protects its boundary. Local validation is repeated intentionally; expensive asynchronous rules would need a different orchestration policy.
Explicit async service calls propagate cancellation to the DirectSharp repository. Across the C# boundary, pass the token through the normal final cancellation parameter.
Previous: model and validation. Next: persistence.