Kategorie

Service Layer (Plugin)

1 Introduction

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

  1. works (can be installed from plugin list and can be accessed from Controller)
  2. has CRUD operations on database (MongoDB)

2 Service Interface (IService)

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

step1

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.

step2

3 Domain Model

You can see that all CRUD operations usually use the same Domain Model (in this example ShippingPoint).

step3

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.

step4

In GrandNode, every Domain Model inherits from BaseEntity, and further from ParentEntity, which adds 2 more Properties

  • IList<GenericAttribute> GenericAttributes
  • string Id

step5

step6

4 Service

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).

step7

To enable access to database and its collections with records, you need to declare IRepostiory<DomainModel>

step8

IRepository’s implementation is MongoDBRepository<DomainModel>

step9

MongoDBRepository (definition of Repository layer) does direct operations on database

step10

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.

step11

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.

step12

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.

5 Dependency Registrar (Autofac)

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.

step13

6 Processor

Plugin needs to be installed, most important methods are (both imposed by inherited abstract and interface)

  •                 Install()                                                      add locale strings and optionally send mail
  •                 Uninstall()                                                  delete locale strings
  •                 GetControllerType()                                  makes it possible to call Controller
  •                 GetConfigurationRoute()                           makes it possible to call Configure() Action

There are several types of possible plugin’s interfaces (all inherit from IPlugin)

  •                 IPaymentMethod
  •                 IShippingRateComputationMethod
  •                 IMiscPlugin
  •                 ITaxProvider
  •                 IDiscountRequirementRule
  •                 IExchangeRateProvider
  •                 IAdminMenuPlugin
  •                 IWidgetPlugin
  •                 IExternalAuthenticationMethod

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.

step14

back to top