This document is a guide for developers to the Service Layer in Plugins of GrandNode.
Service is a logical layer in application that blends several roles.
Firstly, Service controls CRUD operations on repository (database).
Secondly, Service is a container for specific methods that are only for Service’s entity (and makes no sense to locate it in seprated class).
Thirdly, Service is used by many Controllers, so Controller itself doesn’t have to define any logic (separation of concerns (SoC) design principle).
After reading this you should be able to add to your plugin basic Service layer that
Let’s start from Service’s interface.
It is all typical CRUD operations.
Sometimes all you need is basic, create, read, update, delete record in database.
Depending on what you need, you can make more sophisticated Methods like
Usually knowing what Methods will you need in your Controller is obvious in some point of development process – so, if you don’t know yet what you need now, you will surely do later.
You can see that all CRUD operations usually use the same Domain Model (in this example ShippingPoint).
Domain Model is a type tailored specially for database. Unlike View Model, Domain Model contains only types supported by database engine. All Properties needs to be set as public with auto-implemented getters and setters (Auto Properties). They can contain complex types and collections as well.
In GrandNode, every Domain Model inherits from BaseEntity, and further from ParentEntity, which adds 2 more Properties
Service is plain implementation of Interface, a convenient layer between repository and Controllers (worth to mention – Services should be used only by Controllers – and inside Controllers shouldn’t be any operation on repository).
You should use these structures consistent with thier purpose.
Of course, why don't request Repository straight from Controller. It is so straightforward (it is not an advice).
To enable access to database and its collections with records, you need to declare IRepostiory<DomainModel>
IRepository’s implementation is MongoDBRepository<DomainModel>
MongoDBRepository (definition of Repository layer) does direct operations on database
Let’s return to our Service.
You can see that above method GetById() is used in Service’s Method GetStoreShippingPointById().
The convenient part is, you can put in Service’s Method your own arbitrarily logic.
Whereas in Repository layer you can’t define any own logic, because it has to be generic and widely used mechanism.
Service isn’t only for CRUD operations. It can contain also specific logic for given Service. You just put in one class (Service), any kind of data transformation for given database entity. Then you use it, usually in Controller.
It is worth to notice, that data transformation operations uses other Services. It is good example of structure that implements encapsulation – all in its place, doing its role.
Why there is need for an interface for only one class?
Autofac requires interface during type registration in DependencyRegistrar
Without registration, when you try to use this Service in Controller, Autofact will fire Exception.
Plugin needs to be installed, most important methods are (both imposed by inherited abstract and interface)
There are several types of possible plugin’s interfaces (all inherit from IPlugin)
All of these interfaces impose their own logic
Below you can look at example plugin processor. Different interfaces require different Methods, but GetConfigurationRoute() is common for all.