Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Module services

Describes the various handlers used when working with Commerce (SaaS).

The main purpose of services within a module is to operate the handler factory. This is where the Chain of Responsibility is executed. The context is required on all service calls.

Module handlers

At its core, Commerce (SaaS) handlers are responsible for the heavy lifting of objects and processing the business logic. Handlers derive from HandlerBase which uses generics to leverage the Parameter Object and Result Object pattern.

The platform dynamically loads the handlers using the DependencyName. This attribute is required when replacing existing handlers or adding new handlers to the chain of responsibility.

The Order property on a handler represents the order in the each handler is executed in the chain. The lower the order number the higher precedence in which that handler is executed. The default order for all Commerce (SaaS) handlers is 500.

Handlers will always override the Execute method which will then define all of the core business logic of that handler.

Add a handler

The following considerations need to be made when adding handlers to the chain. By adding a handler to the chain of responsibly the base code will execute and then execute the next handler in the chain. Unless of course, if the order has been set lower than 500.

Make sure to include the DependencyName attribute on all handlers. The name must be unique if the intent is to add a new handler to the chain however if should be the same as the base handler if the desired result is to override the base handler.

Breaking the handler chain can be done one of two ways:

  • By returning the result instead of calling this.NextHandler.Execute()
  • By setting the next handler to be a NullHandler
    • For example, this.RegisterNext(new NullHandler(TParameter, TResult>())

Override a handler

The following considerations need to be made when overriding handlers. The recommendation is to always add a handler to the chain unless the base functionality has to change for a given implementation.

Set the DependencyName attribute on the handler class to the same name as the handler that you would like to override.

  • The reason for naming it the same name as the base handler is that if you do not set the same name then the platform interprets two instances of the same handler. One with any changes that have been made and the other that is the base handler.
  • When multiple handlers with the same DependencyName are registered, the one with the lower dependency order will be used by the platform. Those that are in the namespace that starts with "Insite" are registered with an order of 999. Handlers where the namespace does not start with "Insite" are registered with an order of 500. Dependency order can be explicitly set by adding the DependencyOrder attribute on the handler.

Pass data to and from handlers

Every REST call can accept a dictionary of data in the properties field. This is defined on BaseModel so any methods which takes objects derived from it will expose a properties field in typescript.

Other rest calls which pass query string data also implicitly accept a properties dictionary.

For example to pass extra data to the /products method, add a query string value in the form

&properties={'extradata':'test','extradata2':'test2' }

These property values will be automatically passed through to the handlers in the Properties dictionary on the ParameterBase derived service parameter object. I t is possible to send custom data on the query string as any arbitrary parameter and pick these up in a custom mapper. However, this requires custom code and overrides and should be avoided whenever possible in order to ease upgrades. In addition, many of the resulting objects that have child objects (usually in collections) will automatically have the Properties dictionary on each child object populated with the properties data from the corresponding service result child object.

For example. WishListModel has a child collection of WishListLineModel objects with a Properties collection on each one and these will automatically get the properties dictionaries from the WishListLineResult objects created by the handler.

To return arbitrary data from a rest call, put data in the Properties collection with Properties. Add and it will be automatically returned to the client. To pass back complex objects, use the AddObjectToResultProperties method in HandlerBase to get the correct serialization this.AddObjectToResultProperties(result, "extradata", new { Something = "test", SomethinglElse = "test2" });

On the client deserialize these complex objects with JSON.parse var extradata = JSON.parse(data.properties["extradata"]);

For more handler details, see the Work with handlers article.