Extending the Apprenda Platform

This page describes how to extend normal Platform behaviors to integrate with services outside the Platform.

Guest Applications as Service-Oriented Extensions

The Platform runtime exposes a dynamically configurable service-oriented extension system that allows Developers to publish guest applications with functionality that extends the default Platform business workflows and then tell the Platform to call those services during normal workflow operations. The Platform API contains service contracts for core workflow extension points, each responsible for separate business service workflows. By extending these base classes in a WCF service or group of services, publishing, and then configuring the Platform in real-time, Platform owners can achieve a huge amount of customization. For example, you may want to capture information about new Users that are created in the system and communicate that information to a third-party service.

The configuration of these extensions is performed in the System Operations Center and is based on Platform Registry Settings. Because extension services are guest applications on the Platform, they gain the benefit of the Platform’s application lifecycle management, allowing Platform Operators to test variations of their extensions. Additionally, multiple extension services can be called in succession, allowing Platform Operators to build workflows from extension services published by Developers.

Developing Extension Services

The base classes for the Platform’s extension services can be found in the Apprenda.SaaSGrid.Extensions namespace, which is located in the SaaSGrid.API assembly delivered with the Platform SDK.

Base Classes

Authentication & Signup Workflow:


User Administration Workflow:


Developer Workflow:


Platform Operator Workflow:

Apprenda.SaaSGrid.Extensions.LogAggregatorExtensionServiceBase for log forwarding

Apprenda.SaaSGrid.Extensions.AuditEventForwardingExtensionServiceBase for audit forwarding (available in Platform version 8.0.0 and later)

It is recommended that WCF services receiving audit or log events from the Platform should use the Authorized User Access Model. This access level will make sure that only authorized and authenticated entities can push logs to the WCF service. If you have any more questions about hardening your WCF service and taking advantage of integration to popular operational intelligence platforms contact your support representative.

Storefront Workflow:


Deployment Workflow for any type of component:


Presentation Deployment Workflow (deprecated: Apprenda.API.Extensions.Placement.PlacementExtensionServiceBase is preferred): Apprenda.SaaSGrid.Extensions.PresentationExtensionServiceBase

Storage Deployment Workflow (deprecated: Apprenda.API.Extensions.Placement.PlacementExtensionServiceBase is preferred): Apprenda.SaaSGrid.Extensions.StorageExtensionServiceBase

To build a service whose methods will be called by the Platform extension points, Developers should create WCF services that implement one or more of these base classes and override the methods that they want to use.  Data sent to extension services uses a set of objects located in the namespace Apprenda.SaaSGrid.Extensions.DTO, which is also contained in the SaaSGrid.API assembly.

Below are some examples on implementing an extension:

Example 1

This is an example of a WCF service class that implements the CitadelExtensionServiceBase, and will therefore be capable of handling Authentication & Signup hooks:

namespace MyApprendaExtensionServices.Citadel
    public class ExtensionService : CitadelExtensionServiceBase    
        public override void OnTenantOnBoarding(TenantOnBoarderDTO tenant)
            // your extension logic here           

        public override void OnTenantOnBoarded(TenantOnBoarderDTO tenant)
            // your extension logic here

Along with its accompanying System.ServiceModel configuration in the App.config:

<service name="MyApprendaExtensionServices.Citadel.ExtensionService"
 <endpoint address="net.tcp://localhost:40000/ICitadelExtensionService"

This WCF service should be packaged into an archive for deployment like any other Platform guest application and promoted through the publishing stages in the Developer Portal.

Example 2

This is an example of a WCF service class that implements the LogAggregationExtensionServiceBase, and will be capable of handling an operator hook point for log aggregation.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class LogService : LogAggregatorExtensionServiceBase
    public override void OnLogsPersisted(IEnumerable logs)
        // Your extension logic goes here

Example 3

This is an example of a WCF service class that implements the AuditEventForwardingExtensionBase, and will be capable of handling an operator hook point for audit log aggregation.

public class Aggregator : AuditEventForwardingExtensionBase
    public override void OnAuditedEventReceived(AuditedEventDTO message)
        // Your extension logic goes here

Configuring the Platform to Use Extension Services

Platform Registry Settings in the System Operations Center are used to tell the Platform about the extension services to employ during standard workflows. There is a Registry Setting for each of the core services you can extend:

Extension Service Registry Setting
Authentication & Signup Workflow CitadelExtServices
User Administration Workflow AccountPortalExtServices
Developer Workflow DeveloperPortalExtServices
Platform Operator Workflow

Apprenda.Logging.ExternalServiceAppVersion for logging events in Platform version 7.2.0 and before

Telemetry.Logging.ForwardingServiceExtensionVersions for logging events in Platform version 8.0.0 and later

Telemetry.AuditEventForwardingTarget for audit logs (available in Platform version 8.0.0 and later)

Storefront Workflow


Deployment Workflow Setting Names by component type

Deployment.AspNetPlacementExtServices (for .NET user interface components); may also be used for the deprecated base class Apprenda.SaaSGrid.Extensions.PresentationExtensionServiceBase

Deployment.DBPlacementExtServices (for database components); may also be used for the deprecated base class Apprenda.SaaSGrid.Extensions.StorageExtensionServiceBase

Deployment.ServicePlacementExtServices (for WCF and Windows service components)

Deployment.WarPlacementExtServices (for wars)

Presentation Workflow (deprecated: any value configured for this setting will be migrated to Deployment.AspNetPlacementExtServices) PresentationExtServices
Storage Workflow (deprecated: any value configured for this setting will be migrated to Deployment.DBPlacementExtServices) StorageExtServices

Registry Setting Values

The values for these settings should be a comma-delimited list of application aliases corresponding with the unique application and version aliases (for applications in the Sandbox stage), followed by the service class name that is being called. Formatted as appAlias(versionAlias)/serviceName.

Note: Extensions will not be invoked when deploying a service hosting one of the extensions that should be used for service deployment because this would result in a recursive loop that cannot complete.

To configure the Platform to call the ExtensionService in a published application with alias ‘myextservice’ during account signup, the ExtensionService must

  • implement Apprenda.SaaSGrid.Extensions.CitadelExtensionServiceBase
  • override one or more hook points
  • be configured to expose that contract endpoint
  • be published

Then, the Registry Setting ‘CitadelExtServices’ should have a value of ‘myextservice’, or ‘myextservice(v1)’, which specifies a target version of the application to the Platform. If version 2 of the application is published with the alias v2, update the setting to ‘myextservice(v2)’ and that extension service will be called during the next account signup workflow that fires. To call both versions of this application, or call multiple application/version pairs during the same workflow, use a comma-delimited list, like the following:

Setting Name: CitadelExtServices Setting Value: myextservice(v1)/ExtensionService, myextservice(v2)/ExtensionService, myotherextservice(v1)/ExtensionService

During account creation, the contract endpoints for ICitadelExtensionService on the WCF service called ‘ExtensionService’ are called in order.

Note: Applications in the Published stage do not require a specified version alias, only ones in the Sandbox stage do. If no version is specified, it will call whatever version is Published.

Available Hook Points

The following is an explanation of each hook point that an extension service can implement.

Authentication & Signup Workflow Hooks The following service methods will be called by Apprenda’s Citadel service, which handles account onboarding and authentication.

  • OnFailedLogin
  • OnTenantOnBoarding
  • OnTenantOnBoarded
  • OnUserLogin
  • OnUserLogout
  • ValidatePassword

User Administration Workflow Hooks The following service methods will be called by Apprenda’s AccountPortal service, which handles customer and Tenant account management:

  • OnCreatingUser
  • OnUserCreated
  • OnRemovingUser
  • OnUserRemoved
  • OnUpdatingUser
  • OnUserUpdated

Developer Workflow Hooks The following service methods will be called by Apprenda’s DeveloperPortal service, which handles guest application publishing:

  • OnPromotingVersion
  • OnVersionPromoted
  • OnDemotingVersion
  • OnVersionDemoted

Platform Operator Workflow for log forwarding Hooks The following service methods will be called by Apprenda’s Logging service, which handles log publishing:

  • OnLogsPersisted
    • This endpoint is called in frequent intervals and is passed an array of log messages from the Platform. All logs for all applications will be pushed to this endpoint
    • Parameter: An array Apprenda.SaasGrid.Extension.DTO.LogMessageDTO objects
  • OnAuditedEventReceived (available in Platform version 8.0.0 and later)
    • This endpoint is called in frequent intervals and is passed a single audit event entry message from the Platform. All audit events for the Platform will be pushed to this endpoint
    • Parameter: A single AuditedEventDTO object

It is recommended that automatic scaling is configured for the WCF service receiving audit or log events from the Platform. Although there is no performance penalty when you subscribe to the Platform Operator Workflow hook point, using automatic scaling will allow the component to scale with the dynamic demand of auditing or logging on the Platform.

Storefront Workflow Hooks The following service methods will be called by Apprenda’s Storefront service, which handles the Platform’s authorization mechanisms such as subscriptions:

  • OnPurchasingSubscription
  • OnSubscriptionPurchased
  • OnActivatingSubscriptions
  • OnSubscriptionsActivated
  • OnExpiringSubscriptions
  • OnSubscriptionsExpired
  • OnSuspendingSubscriptions
  • OnSubscriptionsSuspended
  • OnCancellingSubscriptions
  • OnSubscriptionsCancelled

Deployment Workflow for all component types The following service methods will be called by Apprenda’s DeveloperPortal service during deployment of components:

  • FilterHostsForNewWorkload
  • FilterHostsForNewTenantShard

Presentation Workflow Hooks The following service methods will be called by Apprenda’s DeveloperPortal service during deployment of UI components:

  • FilterHostsForPartition
  • FilterHostsForTenantShard

Storage Workflow Hooks The following service methods will be called by Apprenda’s DeveloperPortal service during deployment of storage components:

  • FilterHostsForPartition

Retrieving Contextual Information

The Apprenda Platform allows Developer to access contextual information regarding the current Organization (refer to the Contexts documentation for more information). When using extensions, a new TenantContext is appended to the stack for the Organization that developed the extension, this means that TenantContext.Current won’t retrieve the running Organization but the Developer. In order to retrieve the right information, you can use the following method:

private TenantContext EstablishProperContext()
      if (TenantContext.Current.History.Skip(1).Any())
           /*Because this will run as a single tenant app, the top tenant context is the tenant ID for that deployed the extension application
           In order to get the ID for the executing tenant, we have to move up the stack once.*/
           return TenantContext.NewTenantContext(TenantContext.Current.History.Skip(1).First().TenantId);
           return TenantContext.NewTenantContext(TenantContext.Current.TenantId);

Extensions Example

For a working example of how to use extensions, see the extensions example on the Downloads page. The downloadable archive contains sample code for setting up an extension so you can see how to implement and extension as well as a working applicaiton archive you can use to test on your environment.

Extensions Library and Support

Extensions are an excellent way to enhance the Platform functionality to fit your needs. We dedicated an entire forum just for them in the Apprenda support website. In this forum you will be able to download extensions that were developed by the Apprenda support team and are ready to be deployed, and you can ask questions and get general implementation information.

We are always adding new extensions; if you have an idea for one, e-mail us at support@apprenda.com. Also, if you have developed an extension yourself that wish to publish for the community, please feel free to post it!

See our Extensions Library and Support.