Telligent Community provides a robust set of in-process APIs that allow developers to interact with its data. These APIs are accessed through an API service that is similar to dependency injection but will only return the first instance of a class or interface that implements or extends the IAPI interface. As a developer you can also create your own APIs and expose them to the API service.
Why should I Create My Own API
APIs are a contract we have with developers developing on our platform. It is our agreement that we will not change an API in a way that would break an existing integration or customization without providing ample notice. There are also many vendors, independent software developers and partners who create various custom components for the platform that may want to expose similar API contracts for their products. For that reason subscribing an API to the API service makes sense as it will allow developers to access the custom API the exact same way as all other APIs. In previous versions all community APIs were handled via a sealed static class so third party developers had to create their own version of this or an equivalent method in their own code. This made for a disjointed experience.
If you are creating a small customization not meant for redistribution, or a distributable component that has not public facing API then you don't need to do this. This feature mainly targets distributable components and community APIs, however you can use this anytime you want to expose an API.
Exposing Your API To Telligent Community
Implementing the Correct Interface
There are a few considerations you need to take into account when designing your API in order to avoid issues later. As you will see when you register an interface, an instance of your API is only created when the application starts or right before the plugins initialize. This means your API class should be stateless or at least only stores data at the instance level that applies to all interactions with the API within the process such as additional services or constant values. While APIs do not have to be singleton classes, the easiest way to develop them is to approach them like they are singleton classes. Your class can also not be static.
You can make your class ready to subscribe to the API service by implementing the IApi interface. Implementing this interface is easy as it has no properties or methods to implement so other than adding the interface to your class definition it requires no additional work.
In this example we have an API to expose called PersonService and it exposes a method to get a random name. In order to prepare our class to be included in the API service, we add the IAPI interface:
public class PersonService : Telligent.Evolution.Extensibility.Api.IApi { public string GetRandomName() { return "Wally"; } }
If you design all your APIs using your own interfaces and want to be able to refer to your custom interface then you can extend your interface with the IApi interface. You will then be able to reference your API in the service using your custom interface OR the concrete class.
public interface IPersonService : Telligent.Evolution.Extensibility.Api.IApi { string GetRandomName(); } public class PersonService : IPersonService { public string GetRandomName() { return "Wally"; } }
Registering the Interface
Once you have a class that implements IApi, you can register it with the platform. This is done via the IApiDefinition plugin type. If you aren't yet familiar with the Plugin model, it is recommended that you review the topics on Plugins.
Aside from the members for IPlugin, IApiDefinition only adds a single method called RegisterApi
that gives you an IApiController. Through the controller you register your API by providing an instance of your class implementing IApi.
public void RegisterApi(IApiController controller) { controller.Add(new PersonService()); }
Using Your API
Because IApiDefinition
is a plugin, you will need to enable it in the Administration area before it can be used in code. Assuming it implements no other plugin types you can find it in Administration->Extensions.
It is important to understand first when your API becomes available before you attempt to use it to avoid any errors. The platform registers all APIs before plugins initialize. This means you can utilize a registered API in a plugin Initialize()
method or in any AfterInitialization() i
n addition to the running application. You should avoid using any API in BeforeInitialization()
of the plugin life cycle as there is no guarantee an API has been registered.
Yo use an API, you retrieve it from the API IN-Process API service using the Get<>() method the same way you would get a built in in-process API. In addition to the concrete class, the API service keeps track of an API and its inheritance chain, so if your API uses an abstract class that implements IApi then you can retrieve the API by the abstract class name. Similarly if you use an interface for your class that extends IApi, you can retrieve it by your custom interface.
var personAPI = Telligent.Evolution.Extensibility.Apis.Get<PersonService>()
Or because our PersonService implements IPersonService which extends IApi, this is appropriate as well:
var personAPI = Telligent.Evolution.Extensibility.Apis.Get<IPersonService>()
NOTE: When using custom interfaces or abstract classes to extend IApi, you need to remember that the API service can only associate 1 API to a type so you cannot have multiple APIs that use the same abstract class or interface. If you have a scenario where your APIs share a common interface, the class implementation of that interface should implement IApi.
For example if all your APis use an IRepository interface, then IApi Should be applied to the class implementation:
public interface IRepository { } public class PersonRepository : IRepository, IApi { }
You could apply it to an interface if the interface extends a shared interface, but the interface itself still only has a single implementation:
public interface IRepository { } public interface IPersonRepository : IApi { } public class PersonRepository : IPersonRepository{ }
It is appropriate to wrap any usage of an API in a null check before its used since an IApiDefinition plugin could have been disabled in Administration(This does not apply to core in-process APIs as they cannot be disabled).
var personAPI = Telligent.Evolution.Extensibility.Apis.Get<IPersonService>(); if (personAPI != null) { //Intract with personAPI }