Connector Development v5.2 References

Connector PlugIn API

From UNIFYBroker v5.2 onwards, the service provides a self-documenting REST endpoint for the web UI and other external actors to use. This API is extensibile and this article details process of implementing support for connector plugins. The following components are required for a standard connector plugin:

  • Shared API Project
    • Agent API Information
    • Agent Extended Information
    • Connector API Information
    • Connector Extended Information
  • API Project
    • Agent Controller
    • Connector Controller
  • Web Project
    • API Client

API Project Components

Agent and Connector Controllers

Controllers contain methods which are exposed via the API. Controllers must feature the following:

Implements PluggedAgentControllerBase<TInfo, TExtendedInfo>Base controller class which contains standard agent controller functions. TInfo is AgentApiInformation<ExampleAgentExtendedInformation> and TExtendedInfo is IAgentExtendedInformation, both described below.
Class has AgentPlugInVersionRouteAttribute setDescribes the route the controller and its methods should take on in the API.
AgentPlugInVersionRouteAttribute argument agentFactoryNameFactory name for the agent.
AgentPlugInVersionRouteAttribute argument agentPathElementName of the agent for use in the path. IE a value of 'Example' results in the path 'api/version/Agent/Example/AgentMethod'
AgentPlugInVersionRouteAttribute argument versionVersion of the API the controller is associated with. Should be in the format of 'x.x'.
Factory name passed to base constructorFactory name for the agent.
Path element passed to base constructorName of the agent for use in the path.
To XML function passed to base constructorA function that accepts TExtended and converts this to XML. Should use the same factory class used elsewhere by the plugin.
From XML function passed to base constructorA function that accepts extended XML and converts it to TExtended. Should use the same factory class used elsewhere by the plugin.
[AgentPlugInVersionedRoute(ExampleAgentAttributes.ADAgentName, "Example", "1.0")]
public class ExampleAgentController : PluggedAgentControllerBase<ExampleAgentApiInformation, ExampleAgentExtendedInformation="">
{
    public ADAgentController(IAgentEngine agentEngine)
        : base(agentEngine, ADAgentAttributes.ADAgentName, ApiExtensions.ActiveDirectoryPathElement, ApiToXml, XmlToApi)
    {
    }
    private static XElement ApiToXml(ExampleAgentExtendedInformation apiInfo) 
    {
        // Convert apiInfo -> internalInfo -> xml (using existing information factory)
    }
    private static ActiveDirectoryAgentExtendedInformation XmlToApi(XElement xml)
    {
        // Convert xml -> internalInfo (using existing information factory) -> apiInfo
    }
}
Implements PluggedConnectorControllerBase<TInfo, TExtendedInfo>Base controller class which contains standard connector controller functions. TInfo is ConnectorApiInformation<ExampleConnectorExtendedInformation> and TExtendedInfo is IConnectorExtendedInformation, both described below.
Class has ConnectorPlugInVersionRouteAttribute setDescribes the route the controller and its methods should take on in the API.
ConnectorPlugInVersionRouteAttribute argument connectorFactoryNameFactory name for the connector.
ConnectorPlugInVersionRouteAttribute argument connectorPathElementName of the connector for use in the path. IE a value of 'Example' results in the path 'api/version/Connector/Example/ConnectorMethod'
ConnectorPlugInVersionRouteAttribute argument versionVersion of the API the controller is associated with. Should be in the format of 'x.x'.
Factory name passed to base constructorFactory name for the connector.
Path element passed to base constructorName of the connector for use in the path.
To XML function passed to base constructorA function that accepts TExtended and converts this to XML. Should use the same factory class used elsewhere by the plugin.
From XML function passed to base constructorA function that accepts extended XML and converts it to TExtended. Should use the same factory class used elsewhere by the plugin.
[ConnectorPlugInVersionedRoute(ExampleConnectorAttributes.ADConnectorName, "Example", "1.0")]
public class ExampleConnectorController : PluggedConnectorControllerBase<ExampleConnectorApiInformation, ExampleConnectorExtendedInformation="">
{
    public ADConnectorController(IConnectorEngine connectorEngine)
        : base(connectorEngine, ADConnectorAttributes.ADConnectorName, ApiExtensions.ActiveDirectoryPathElement, ApiToXml, XmlToApi)
    {
    }
    private static XElement ApiToXml(ExampleConnectorExtendedInformation apiInfo) 
    {
        // Convert apiInfo -> internalInfo -> xml (using existing information factory)
    }
    private static ActiveDirectoryConnectorExtendedInformation XmlToApi(XElement xml)
    {
        // Convert xml -> internalInfo (using existing information factory) -> apiInfo
    }
}

Custom Controller Functions

If additional API methods are required on the plugin API controller they can be implemented by adding them to the API controllers with the appropriate attributes set.

Http method attributeAttribute which dictates the HTTP method used. Options include HttpPostAttribute, HttpGetAttribute, HttpDeleteAttribute, HttpPutAttribute and HttpPatchAttribute.
ActionNameAttributeGive the API method a name different to the controller functions name.
ApiMethodDescriptionAttributeSets a description for the method to be used in the APIs self-documentation.
ApiMethodParamDescriptionAttributeSets a description for the specified method parameter to be used in the APIs self-documentation. Add this attribute once for each parameter.
[HttpPost]
[ActionName("FuctionName")]
[ApiMethodDescription("A custom function which does something")]
[ApiMethodParamDescription("argument1", "The first argument, part of the query string")]
[ApiMethodParamDescription("argument2", "The second argument, the post body.")]
public TReturn CustomFunction(string argument1, CustomDataObject argument2)
{
    // Do something
}

Controller Registration

To register a controller, use the appropriate method on the engine. This should be performed in the plugin factory CreateComponent method.

agentEngine.AddAgentController<ExampleAgentController, ExampleAgentApiInformation, ExampleAgentExtendedInformation>(
    VersionConstants.Version1_0,
    () => new ExampleAgentController(agentEngine));        // Other resources can be passed to the controller as needed.
connectorEngine.AddConnectorController<ExampleConnectorController, ExampleConnectorApiInformation, ExampleConnectorExtendedInformation>(
    VersionConstants.Version1_0,
    () => new ExampleConnectorController(connectorEngine));        // Other resources can be passed to the controller as needed.

Shared API Project Components

It is recommended to create a shared API project for the components described in the section as they are referenced by the API controllers and the client in the Web project.

Agent Extended Information and Connector Extended Information

These are the API information classes which contain properties specific to the agent/connector type it is implemented for. They should feature the following:

Implements IAgentExtendedInformationInterface type for the extended information.
AgentType propertyShould be set to the same value as the agent factory name.
DataContractAttribute and DataMemberAttributeThe class and properties (AgentType excluded) should have these attributes set.
RequiredAttributeRequired properties should have this attribute set.
ApiPropertyDescriptionAttributeAll properties (AgentType excluded) should have this attribute set with a description of the property.
[DataContract]
public class ExampleAgentExtendedInformation : IAgentExtendedInformation
{
    public string Type => ExampleAgentAttributes.AgentFactoryName;        // ie: Unify.Agent.Example
    [Required]
    [DataMember]
    [ApiPropertyDescription("The first value.")]
    public string Value1 
    { 
        get; set; 
    }
    [DataMember]
    [ApiPropertyDescription("The second value.")]
    public string Value2 
    { 
        get; set; 
    }
}
Implements IConnectorExtendedInformationInterface type for the extended information.
ConnectorType propertyShould be set to the same value as the connector factory name.
DataContractAttribute and DataMemberAttributeThe class and properties (ConnectorType excluded) should have these attributes set.
RequiredAttributeRequired properties should have this attribute set.
ApiPropertyDescriptionAttributeAll properties (ConnectorType excluded) should have this attribute set with a description of the property.
[DataContract]
public class ExampleConnectorExtendedInformation : IConnectorExtendedInformation
{
    public string Type => ExampleConnectorAttributes.ConnectorFactoryName;        // ie: Unify.Connector.Example
    [Required]
    [DataMember]
    [ApiPropertyDescription("The first value.")]
    public string Value1 
    { 
        get; set; 
    }
    [DataMember]
    [ApiPropertyDescription("The second value.")]
    public string Value2 
    { 
        get; set; 
    }
}

Agent API Information and Connector API Information

Information objects sent via the API cannot be generic types so these classes are needed to provide non-generic versions of ConnectorApiInformation<TExtended>. Each connector and agent type should have a corresponding API information class created using that agent/connectors extended information type.

public class ExampleAgentApiInformation : AgentApiInformation<ExampleAgentExtendedInformation>
{
}
public class ExampleConnectorApiInformation : ConnectorApiInformation<ExampleConnectorExtendedInformation>
{
}

Web Project Components

API Client

To generate the Web API Client code (to allow communication from the user interface back to the service):

  1. install nSwagStudio
  2. Install or deploy new pluggable API
  3. Start Identity Broker
  4. Create a new Web API endpoint, with a white-list filter including only the new API
  5. Target nSwagStudio at the Identity Broker API endpoint
  6. Set the following options:
    1. Off: Generate exception classes (they're included in the the SDK Framework)
    2. Off: Generate DTO Types (these are the ApiInformation and ExtendedInformation classes from above)
  7. Generate the client and make available to the user interface code

    _SomethingClient = new SomethingClient {BaseUrl = ApiAddress};

Is this article helpful for you?