The services have a base class that wires most of the required functionality. A typical service flow is outlined as follows
public virtual async Task<TId> AddAsync(TEntity entity)
{
try
{
IEnumerable<string> validationMessages = Enumerable.Empty<string>();
//Input data validations go here
if (!ValidateEntity(entity, EntityOperations.Create, out validationMessages))
{
throw new EntityValidationException("Entity data validation failed");
}
//Access permission checks go here
if (!ValidateACL(EntityOperations.Create, entity))
{
UnPrivilegedAccess(entity);
}
//pre-processing of the data is done here
string message = string.Empty;
if (!TryPreProcessEntity(entity, EntityOperations.Create, out message))
{
throw new EntityPreProcessorExceptions("Entity preprocessing failed");
}
//Repository call
await _repository.AddAsync(entity);
int status = await _repository.SaveAsync();
//Status reporting if any failure
if (status != 0) OperationFailed(EntityOperations.Create, entity);
//Post-processing of the data
if (!TryPostProcessEntity(EntityOperations.Create, out message, entity))
{
throw new EntityPostProcessorExceptions("Entity postprocessing failed");
}
return entity.Id;
}
catch (Exception exception)
{
ExceptionHandler(exception); //Extendible exception handler in the implementation
}
finally
{
CompleteServiceCall(EntityOperations.Create, entity); // final cleanup hook customizable in the service implementation
}
return default(TId);
}