-
Notifications
You must be signed in to change notification settings - Fork 96
Configuration options
There are four main parts of the GenericServicesConfig
class.
NOTE: By validation I mean using the Validator.TryValidateObject
method on every entity being written
to the database.
By default GenericServices does NOT validate data written to the database - it assumes that the front-end
has validated the data. But it can be useful to turn on validation, especially if you are using the SaveChangesExceptionHandler
fuction - (see below).
You have two ways to turn on validation when GenericServices calls SaveChanges
- globally via the GenericServicesConfig
class at startup (see below), or individually using the PerDtoConfig<TDto, TEntity
.
If set to true then any Create/Update/Delete that is given an entity classes will validate that entity class on save. It will also call the SaveChangesExceptionHandler
(see below) if an exception occurs. This is the ONLY way to turn on validation for direct-access writes
If set to true then any Create/Update/Delete calls with DTOs will include a validation of the data on save. It will also call the SaveChangesExceptionHandler
(see below) if an exception occurs. You can use PerDtoConfig<TDto, TEntity
to only set validation for a single DTO/entity. The PerDtoConfig
setting takes precedence, and can force validation on or off.
If you assign a method to the BeforeSaveChanges
property in GenericServicesConfig
, then it will be called just before SaveChanges/Async is called. The method takes in the current DbContext, which allows you access to the ChangeTracker
method to find out the state of all the tracked entities. The method returns an IStatusGeneric
result and if that status result has errors, i.e. status.IsValid == false
, then it will not call SaveChanges/Async.
How you use this is up to you, but here are some suggestions:
- Add your own validation approach - someone wanted this to apply fluentvalidation.
- Maybe add some code to update certain entities.
- Logging. etc.
If you set this property to a method it will be called if there is an exception when SaveChanges/Async is called. You method should either:
- Return a IStatusGeneric if it handled the exception (either by returning a error message or a status message) if it successfully converted the exception into a user-friendly error that you can show to user.
- Returns null if it didn't recognise the exception/error and couldn't handle it. In that case the code will rethrow the exception and it will bubble up to the top.
See the article Entity Framework Core – validating data and catching SQL errors for an example of how to do this.
Whether returning a null from a ReadSingle
/ReadSingleAsync
is an error or not depends on what you are doing. For instance, when working with html/razor you most likely want to tell the user that was an error. But with Web API it's not an error - you just return NotFound
(HTTP 404).
You can control whether the read of null is an error via the NoErrorOnReadSingleNull
property in the config. By default it adds an error, but if set to true
it will not add an error, but it will set the Message
to "The <Class Name> was not found."
The name matcher is used to match the properties in a DTO with the property names in your DDD-styled entity access methods. The default name matcher matches camel and Pascal-case words by simple string matching. If you want a different matching scheme you can write your own, using the DefaultNameMatcher
as a template.