<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Custom APIs</title><link>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis</link><description /><dc:language>en-US</dc:language><generator>14.0.0.586 14</generator><item><title>Custom APIs</title><link>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis</link><pubDate>Tue, 04 Aug 2020 19:29:36 GMT</pubDate><guid isPermaLink="false">c6f2a0d2-2811-48b0-a870-ce4908aeeac3</guid><dc:creator>Former Member</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis#comments</comments><description>Current Revision posted to Developer Training by Former Member on 08/04/2020 19:29:36&lt;br /&gt;
&lt;p&gt;Verint Community provides a robust set of in-process APIs that allow developers to interact with its data. &amp;nbsp;These APIs are accessed through an [[api-documentation:Apis In-Process API Service|API service]] that&amp;nbsp;will&amp;nbsp;return an&amp;nbsp;instance of a class that implements the &lt;code&gt;[[api-documentation:IApi Provider Type|IApi]]&lt;/code&gt; interface when&amp;nbsp;it&amp;#39;s&amp;nbsp;provided the class type. &amp;nbsp;As a developer you can also create your own APIs and expose them to the API service in the same way you access the community [[In-Process API]].&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_Should_You_Create_Your_Own_API" name="When_Should_You_Create_Your_Own_API"&gt;&lt;/a&gt;When&amp;nbsp;Should You&amp;nbsp;Create Your&amp;nbsp;Own API?&lt;/h2&gt;
&lt;p&gt;APIs are a contract we have with developers developing on our platform. &amp;nbsp;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. &amp;nbsp; 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. &amp;nbsp;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. &amp;nbsp;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 to get to an API. &amp;nbsp;This made for a disjointed development experience.&lt;/p&gt;
&lt;p&gt;If you are creating a small customization not meant for redistribution, or a distributable component that has no public facing API then you don&amp;#39;t need to do this. &amp;nbsp;This feature mainly targets distributable components and core community APIs, however you can use this anytime you want to expose an API through the [[api-documentation:Apis In-Process API Service|API service]].&lt;/p&gt;
&lt;h2&gt;&lt;a id="Exposing_Your_API_To_Telligent_Community" name="Exposing_Your_API_To_Telligent_Community"&gt;&lt;/a&gt;Exposing Your API To Verint Community&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Implementing_the_Correct_Interface" name="Implementing_the_Correct_Interface"&gt;&lt;/a&gt;Implementing the Correct Interface&lt;/h3&gt;
&lt;p&gt;There are a few considerations you need to take into account when designing your API in order to avoid issues later. &amp;nbsp;As you will see when you register an interface, an instance of your API is only created when the application right before the plugins initialize which would be when the application starts or the plugins are forced to be reloaded by some internal event. &amp;nbsp;This means your API class should be stateless or at least only stores data&amp;nbsp;at&amp;nbsp;the instance level that applies to all interactions with the API within the process such as additional dependent services or constant values. &amp;nbsp; While APIs do not have to be singleton classes, the easiest way to develop them is to approach them like they are. &amp;nbsp;Your class&amp;nbsp;can also not be static.&lt;/p&gt;
&lt;p&gt;You can make your class ready to subscribe to the API service by implementing the &lt;code&gt;[[api-documentation:iapi plugin supplementary type|IApi]]&lt;/code&gt; interface. &amp;nbsp;Implementing this interface is easy as it has no properties or methods&amp;nbsp;to implement so other than adding the interface to your class definition it requires no additional work.&lt;/p&gt;
&lt;p&gt;In this example we have an API to expose called &lt;code&gt;PersonService&lt;/code&gt; and it exposes a method to get a random name. &amp;nbsp;In order to prepare our class to be included in the API service, we add the &lt;code&gt;[[api-documentation:iapi plugin supplementary type|IApi]]&lt;/code&gt;&amp;nbsp;interface:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class PersonService : Telligent.Evolution.Extensibility.Api.IApi
{
    public string GetRandomName()
    {
        return &amp;quot;Wally&amp;quot;;
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you design all your APIs using your own interfaces and want to be able to refer to your custom interface when loading the API then you can extend your interface with the &lt;code&gt;IApi&lt;/code&gt; interface instead of the class implementation itself. &amp;nbsp;You will then be able to reference your API in the service using your custom interface type OR the concrete class type.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IPersonService : Telligent.Evolution.Extensibility.Api.IApi
{
   string GetRandomName();
}

public class PersonService : IPersonService
{
   public string GetRandomName()
   {
      return &amp;quot;Wally&amp;quot;;
   }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Registering_the_Interface" name="Registering_the_Interface"&gt;&lt;/a&gt;Registering the Interface&lt;/h3&gt;
&lt;p&gt;Once you have a class that implements &lt;code&gt;IApi&lt;/code&gt; in some fashion, you can register it with the platform. &amp;nbsp;This is done via the [[api-documentation:IApiDefinition Plugin Type|IApiDefinition plugin type]]. &amp;nbsp;If you aren&amp;#39;t yet familiar with the [[Plugins|Plugin model]], it is recommended that you review the topics on [[Plugins]].&lt;/p&gt;
&lt;p&gt;Aside from the members for [[api-documentation:IPlugin Plugin Type|IPlugin]], IApiDefinition only adds a single method called &lt;code&gt;RegisterApi&lt;/code&gt; that gives you an &lt;code&gt;[[api-documentation:IApiController Plugin Supplementary Type|IApiController]]&lt;/code&gt;. &amp;nbsp;Through the controller you register your API by providing an instance of your class implementing &lt;code&gt;IApi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void RegisterApi(IApiController controller)
{
    controller.Add(new PersonService());
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_Your_API" name="Using_Your_API"&gt;&lt;/a&gt;Using Your API&lt;/h2&gt;
&lt;p&gt;First compile your project and deploy the project DLL to both the bin folder of Verint Community and the job service&amp;nbsp;folder. &amp;nbsp;Because &lt;code&gt;IApiDefinition&lt;/code&gt; is a plugin, you will need to enable it in the Administration area before it can be used in code. &amp;nbsp;Assuming it implements no other plugin types you can find it in Administration-&amp;gt;Extensions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/57.29-PM.png"&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" alt=" " src="/resized-image/__size/662x280/__key/communityserver-wikis-components-files/00-00-00-12-83/57.29-PM.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is important to understand when APIs are registered in the product life cycle&amp;nbsp;before you attempt to use it to avoid&amp;nbsp;any errors. &amp;nbsp; The platform registers all APIs before plugins initialize. &amp;nbsp;This means you can utilize a registered API in a plugin &lt;code&gt;Initialize()&lt;/code&gt; method or in any &lt;code&gt;AfterInitialization() method i&lt;/code&gt;n addition to normal use during the application runtime. &amp;nbsp;You should avoid using any API in &lt;code&gt;BeforeInitialization()&lt;/code&gt; of the plugin life cycle as there is no guarantee an API has been registered.&lt;/p&gt;
&lt;p&gt;To use an API, you retrieve it from the [[api-documentation:Apis In-Process API Service|API In-Process service]] using the &lt;code&gt;Get&amp;lt;&amp;gt;()&lt;/code&gt; method the same way you would get a built-in in-process API. &amp;nbsp;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&amp;nbsp;&lt;code&gt;IApi&lt;/code&gt; then you can retrieve the API by the abstract class type. &amp;nbsp;Similarly if you use an interface for your class that extends &lt;code&gt;IApi&lt;/code&gt;, you can retrieve it by your custom interface type.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;PersonService&amp;gt;();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Or because our &lt;code&gt;PersonService&lt;/code&gt; implements &lt;code&gt;IPersonService&lt;/code&gt; which extends &lt;code&gt;IApi&lt;/code&gt;, this is appropriate as well:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IPersonService&amp;gt;();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; When using custom interfaces or abstract classes to extend &lt;code&gt;IApi&lt;/code&gt;, 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. &amp;nbsp;If you have a scenario where your APIs share a common interface, the class implementation of that interface should implement &lt;code&gt;IApi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example if all your APis use an &lt;code&gt;IRepository&lt;/code&gt; interface, then &lt;code&gt;IApi&lt;/code&gt;&amp;nbsp;Should be applied to the class implementation:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IRepository { }

public class PersonRepository : IRepository, IApi { }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You could apply it to an interface if the interface extends a shared interface, but the interface itself still should only have&amp;nbsp;a single implementation:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IRepository { }
public interface IPersonRepository : IApi { }
public class PersonRepository : IPersonRepository{ }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;It is appropriate to wrap any usage of an API in a null check before its used since an &lt;code&gt;IApiDefinition&lt;/code&gt; plugin could have been disabled in Administration(This does not apply to core in-process APIs as they cannot be disabled).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IPersonService&amp;gt;();
if (personAPI != null)
{
    //Intract with personAPI
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Sample" name="Sample"&gt;&lt;/a&gt;Sample&lt;/h2&gt;
&lt;p&gt;You can download the following sample&amp;nbsp;as a guide. &amp;nbsp;Once compiled, deployed to your community bin folder, and the plugin SampleAPIDefinition enabled (Administration -&amp;gt; Extensions) it will write &amp;quot;Random Name: Wally&amp;quot; to the event log (Administration-&amp;gt;Monitoring-&amp;gt;Events) when the plugin initializes.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/59.52-PM.png"&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" alt=" " src="/resized-image/__size/766x242/__key/communityserver-wikis-components-files/00-00-00-12-83/59.52-PM.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/PersonService_2E00_cs"&gt;community.telligent.com/.../PersonService_2E00_cs&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Custom APIs</title><link>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis/revision/3</link><pubDate>Mon, 03 Aug 2020 21:28:41 GMT</pubDate><guid isPermaLink="false">c6f2a0d2-2811-48b0-a870-ce4908aeeac3</guid><dc:creator>Former Member</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis#comments</comments><description>Revision 3 posted to Developer Training by Former Member on 08/03/2020 21:28:41&lt;br /&gt;
&lt;p&gt;Telligent Community provides a robust set of in-process APIs that allow developers to interact with its data. &amp;nbsp;These APIs are accessed through an [[api-documentation:Apis In-Process API Service|API service]] that&amp;nbsp;will&amp;nbsp;return an&amp;nbsp;instance of a class &amp;nbsp;that implements the &lt;code&gt;[[api-documentation:IApi Provider Type|IApi]]&lt;/code&gt; interface when&amp;nbsp;it&amp;#39;s&amp;nbsp;provided the class type. &amp;nbsp;As a developer you can also create your own APIs and expose them to the API service in the same way you access the community [[In-Process API]].&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_Should_You_Create_Your_Own_API" name="When_Should_You_Create_Your_Own_API"&gt;&lt;/a&gt;When&amp;nbsp;Should You&amp;nbsp;Create Your&amp;nbsp;Own API?&lt;/h2&gt;
&lt;p&gt;APIs are a contract we have with developers developing on our platform. &amp;nbsp;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. &amp;nbsp; 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. &amp;nbsp;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. &amp;nbsp;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 to get to an API. &amp;nbsp;This made for a disjointed development experience.&lt;/p&gt;
&lt;p&gt;If you are creating a small customization not meant for redistribution, or a distributable component that has no public facing API then you don&amp;#39;t need to do this. &amp;nbsp;This feature mainly targets distributable components and core community APIs, however you can use this anytime you want to expose an API through the [[api-documentation:Apis In-Process API Service|API service]].&lt;/p&gt;
&lt;h2&gt;&lt;a id="Exposing_Your_API_To_Telligent_Community" name="Exposing_Your_API_To_Telligent_Community"&gt;&lt;/a&gt;Exposing Your API To Telligent Community&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Implementing_the_Correct_Interface" name="Implementing_the_Correct_Interface"&gt;&lt;/a&gt;Implementing the Correct Interface&lt;/h3&gt;
&lt;p&gt;There are a few considerations you need to take into account when designing your API in order to avoid issues later. &amp;nbsp;As you will see when you register an interface, an instance of your API is only created when the application right before the plugins initialize which would be when the application starts or the plugins are forced to be reloaded by some internal event. &amp;nbsp;This means your API class should be stateless or at least only stores data&amp;nbsp;at&amp;nbsp;the instance level that applies to all interactions with the API within the process such as additional dependent services or constant values. &amp;nbsp; While APIs do not have to be singleton classes, the easiest way to develop them is to approach them like they are. &amp;nbsp;Your class&amp;nbsp;can also not be static.&lt;/p&gt;
&lt;p&gt;You can make your class ready to subscribe to the API service by implementing the &lt;code&gt;[[api-documentation:iapi plugin supplementary type|IApi]]&lt;/code&gt; interface. &amp;nbsp;Implementing this interface is easy as it has no properties or methods&amp;nbsp;to implement so other than adding the interface to your class definition it requires no additional work.&lt;/p&gt;
&lt;p&gt;In this example we have an API to expose called &lt;code&gt;PersonService&lt;/code&gt; and it exposes a method to get a random name. &amp;nbsp;In order to prepare our class to be included in the API service, we add the &lt;code&gt;[[api-documentation:iapi plugin supplementary type|IApi]]&lt;/code&gt;&amp;nbsp;interface:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class PersonService : Telligent.Evolution.Extensibility.Api.IApi
{
    public string GetRandomName()
    {
        return &amp;quot;Wally&amp;quot;;
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you design all your APIs using your own interfaces and want to be able to refer to your custom interface when loading the API then you can extend your interface with the &lt;code&gt;IApi&lt;/code&gt; interface instead of the class implementation itself. &amp;nbsp;You will then be able to reference your API in the service using your custom interface type OR the concrete class type.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IPersonService : Telligent.Evolution.Extensibility.Api.IApi
{
   string GetRandomName();
}

public class PersonService : IPersonService
{
   public string GetRandomName()
   {
      return &amp;quot;Wally&amp;quot;;
   }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Registering_the_Interface" name="Registering_the_Interface"&gt;&lt;/a&gt;Registering the Interface&lt;/h3&gt;
&lt;p&gt;Once you have a class that implements &lt;code&gt;IApi&lt;/code&gt; in some fashion, you can register it with the platform. &amp;nbsp;This is done via the [[api-documentation:IApiDefinition Plugin Type|IApiDefinition plugin type]]. &amp;nbsp;If you aren&amp;#39;t yet familiar with the [[Plugins|Plugin model]], it is recommended that you review the topics on [[Plugins]].&lt;/p&gt;
&lt;p&gt;Aside from the members for [[api-documentation:IPlugin Plugin Type|IPlugin]], IApiDefinition only adds a single method called &lt;code&gt;RegisterApi&lt;/code&gt; that gives you an &lt;code&gt;[[api-documentation:IApiController Plugin Supplementary Type|IApiController]]&lt;/code&gt;. &amp;nbsp;Through the controller you register your API by providing an instance of your class implementing &lt;code&gt;IApi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void RegisterApi(IApiController controller)
{
    controller.Add(new PersonService());
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_Your_API" name="Using_Your_API"&gt;&lt;/a&gt;Using Your API&lt;/h2&gt;
&lt;p&gt;First compile your project and deploy the project DLL to both the bin folder of Telligent Community and the job service&amp;nbsp;folder. &amp;nbsp;Because &lt;code&gt;IApiDefinition&lt;/code&gt; is a plugin, you will need to enable it in the Administration area before it can be used in code. &amp;nbsp;Assuming it implements no other plugin types you can find it in Administration-&amp;gt;Extensions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/57.29-PM.png"&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" alt=" " src="/resized-image/__size/662x280/__key/communityserver-wikis-components-files/00-00-00-12-83/57.29-PM.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is important to understand when APIs are registered in the product life cycle&amp;nbsp;before you attempt to use it to avoid&amp;nbsp;any errors. &amp;nbsp; The platform registers all APIs before plugins initialize. &amp;nbsp;This means you can utilize a registered API in a plugin &lt;code&gt;Initialize()&lt;/code&gt; method or in any &lt;code&gt;AfterInitialization() method i&lt;/code&gt;n addition to normal use during the application runtime. &amp;nbsp;You should avoid using any API in &lt;code&gt;BeforeInitialization()&lt;/code&gt; of the plugin life cycle as there is no guarantee an API has been registered.&lt;/p&gt;
&lt;p&gt;To use an API, you retrieve it from the [[api-documentation:Apis In-Process API Service|API In-Process service]] using the &lt;code&gt;Get&amp;lt;&amp;gt;()&lt;/code&gt; method the same way you would get a built-in in-process API. &amp;nbsp;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&amp;nbsp;&lt;code&gt;IApi&lt;/code&gt; then you can retrieve the API by the abstract class type. &amp;nbsp;Similarly if you use an interface for your class that extends &lt;code&gt;IApi&lt;/code&gt;, you can retrieve it by your custom interface type.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;PersonService&amp;gt;();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Or because our &lt;code&gt;PersonService&lt;/code&gt; implements &lt;code&gt;IPersonService&lt;/code&gt; which extends &lt;code&gt;IApi&lt;/code&gt;, this is appropriate as well:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IPersonService&amp;gt;();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; When using custom interfaces or abstract classes to extend &lt;code&gt;IApi&lt;/code&gt;, 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. &amp;nbsp;If you have a scenario where your APIs share a common interface, the class implementation of that interface should implement &lt;code&gt;IApi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example if all your APis use an &lt;code&gt;IRepository&lt;/code&gt; interface, then &lt;code&gt;IApi&lt;/code&gt;&amp;nbsp;Should be applied to the class implementation:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IRepository { }

public class PersonRepository : IRepository, IApi { }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You could apply it to an interface if the interface extends a shared interface, but the interface itself still should only have&amp;nbsp;a single implementation:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IRepository { }
public interface IPersonRepository : IApi { }
public class PersonRepository : IPersonRepository{ }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;It is appropriate to wrap any usage of an API in a null check before its used since an &lt;code&gt;IApiDefinition&lt;/code&gt; plugin could have been disabled in Administration(This does not apply to core in-process APIs as they cannot be disabled).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IPersonService&amp;gt;();
if (personAPI != null)
{
    //Intract with personAPI
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Sample" name="Sample"&gt;&lt;/a&gt;Sample&lt;/h2&gt;
&lt;p&gt;You can download the following sample&amp;nbsp;as a guide. &amp;nbsp;Once compiled, deployed to your community bin folder, and the plugin SampleAPIDefinition enabled (Administration -&amp;gt; Extensions) it will write &amp;quot;Random Name: Wally&amp;quot; to the event log (Administration-&amp;gt;Monitoring-&amp;gt;Events) when the plugin initializes.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/59.52-PM.png"&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" alt=" " src="/resized-image/__size/766x242/__key/communityserver-wikis-components-files/00-00-00-12-83/59.52-PM.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/PersonService_2E00_cs"&gt;community.telligent.com/.../PersonService_2E00_cs&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item><item><title>Custom APIs</title><link>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis/revision/1</link><pubDate>Thu, 13 Jun 2019 19:28:13 GMT</pubDate><guid isPermaLink="false">c6f2a0d2-2811-48b0-a870-ce4908aeeac3</guid><dc:creator>Ben Tiedt</dc:creator><comments>https://community.telligent.com/community/11/w/developer-training/65094/custom-apis#comments</comments><description>Revision 1 posted to Developer Training by Ben Tiedt on 06/13/2019 19:28:13&lt;br /&gt;
&lt;p&gt;Telligent Community provides a robust set of in-process APIs that allow developers to interact with its data. &amp;nbsp;These APIs are accessed through an [[api-documentation:Apis In-Process API Service|API service]] that&amp;nbsp;will&amp;nbsp;return an&amp;nbsp;instance of a class &amp;nbsp;that implements the &lt;code&gt;[[api-documentation:IApi Provider Type|IApi]]&lt;/code&gt; interface when&amp;nbsp;it&amp;#39;s&amp;nbsp;provided the class type. &amp;nbsp;As a developer you can also create your own APIs and expose them to the API service in the same way you access the community [[In-Process API]].&lt;/p&gt;
&lt;p&gt;[toc]&lt;/p&gt;
&lt;h2&gt;&lt;a id="When_Should_You_Create_Your_Own_API" name="When_Should_You_Create_Your_Own_API"&gt;&lt;/a&gt;When&amp;nbsp;Should You&amp;nbsp;Create Your&amp;nbsp;Own API?&lt;/h2&gt;
&lt;p&gt;APIs are a contract we have with developers developing on our platform. &amp;nbsp;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. &amp;nbsp; 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. &amp;nbsp;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. &amp;nbsp;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 to get to an API. &amp;nbsp;This made for a disjointed development experience.&lt;/p&gt;
&lt;p&gt;If you are creating a small customization not meant for redistribution, or a distributable component that has no public facing API then you don&amp;#39;t need to do this. &amp;nbsp;This feature mainly targets distributable components and core community APIs, however you can use this anytime you want to expose an API through the [[api-documentation:Apis In-Process API Service|API service]].&lt;/p&gt;
&lt;h2&gt;&lt;a id="Exposing_Your_API_To_Telligent_Community" name="Exposing_Your_API_To_Telligent_Community"&gt;&lt;/a&gt;Exposing Your API To Telligent Community&lt;/h2&gt;
&lt;h3&gt;&lt;a id="Implementing_the_Correct_Interface" name="Implementing_the_Correct_Interface"&gt;&lt;/a&gt;Implementing the Correct Interface&lt;/h3&gt;
&lt;p&gt;There are a few considerations you need to take into account when designing your API in order to avoid issues later. &amp;nbsp;As you will see when you register an interface, an instance of your API is only created when the application right before the plugins initialize which would be when the application starts or the plugins are forced to be reloaded by some internal event. &amp;nbsp;This means your API class should be stateless or at least only stores data&amp;nbsp;at&amp;nbsp;the instance level that applies to all interactions with the API within the process such as additional dependent services or constant values. &amp;nbsp; While APIs do not have to be singleton classes, the easiest way to develop them is to approach them like they are. &amp;nbsp;Your class&amp;nbsp;can also not be static.&lt;/p&gt;
&lt;p&gt;You can make your class ready to subscribe to the API service by implementing the &lt;code&gt;[[api-documentation:iapi plugin supplementary type|IApi]]&lt;/code&gt; interface. &amp;nbsp;Implementing this interface is easy as it has no properties or methods&amp;nbsp;to implement so other than adding the interface to your class definition it requires no additional work.&lt;/p&gt;
&lt;p&gt;In this example we have an API to expose called &lt;code&gt;PersonService&lt;/code&gt; and it exposes a method to get a random name. &amp;nbsp;In order to prepare our class to be included in the API service, we add the &lt;code&gt;[[api-documentation:iapi plugin supplementary type|IApi]]&lt;/code&gt;&amp;nbsp;interface:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public class PersonService : Telligent.Evolution.Extensibility.Api.IApi
{
    public string GetRandomName()
    {
        return &amp;quot;Wally&amp;quot;;
    }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;If you design all your APIs using your own interfaces and want to be able to refer to your custom interface when loading the API then you can extend your interface with the &lt;code&gt;IApi&lt;/code&gt; interface instead of the class implementation itself. &amp;nbsp;You will then be able to reference your API in the service using your custom interface type OR the concrete class type.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IPersonService : Telligent.Evolution.Extensibility.Api.IApi
{
   string GetRandomName();
}

public class PersonService : IPersonService
{
   public string GetRandomName()
   {
      return &amp;quot;Wally&amp;quot;;
   }
}&lt;/pre&gt;&lt;/p&gt;
&lt;h3&gt;&lt;a id="Registering_the_Interface" name="Registering_the_Interface"&gt;&lt;/a&gt;Registering the Interface&lt;/h3&gt;
&lt;p&gt;Once you have a class that implements &lt;code&gt;IApi&lt;/code&gt; in some fashion, you can register it with the platform. &amp;nbsp;This is done via the [[api-documentation:IApiDefinition Plugin Type|IApiDefinition plugin type]]. &amp;nbsp;If you aren&amp;#39;t yet familiar with the [[Plugins|Plugin model]], it is recommended that you review the topics on [[Plugins]].&lt;/p&gt;
&lt;p&gt;Aside from the members for [[api-documentation:IPlugin Plugin Type|IPlugin]], IApiDefinition only adds a single method called &lt;code&gt;RegisterApi&lt;/code&gt; that gives you an &lt;code&gt;[[api-documentation:IApiController Plugin Supplementary Type|IApiController]]&lt;/code&gt;. &amp;nbsp;Through the controller you register your API by providing an instance of your class implementing &lt;code&gt;IApi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public void RegisterApi(IApiController controller)
{
    controller.Add(new PersonService());
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Using_Your_API" name="Using_Your_API"&gt;&lt;/a&gt;Using Your API&lt;/h2&gt;
&lt;p&gt;First compile your project and deploy the project DLL to both the bin folder of Telligent Community and the job service&amp;nbsp;folder. &amp;nbsp;Because &lt;code&gt;IApiDefinition&lt;/code&gt; is a plugin, you will need to enable it in the Administration area before it can be used in code. &amp;nbsp;Assuming it implements no other plugin types you can find it in Administration-&amp;gt;Extensions.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/57.29-PM.png"&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" src="/resized-image/__size/662x280/__key/communityserver-wikis-components-files/00-00-00-12-83/57.29-PM.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is important to understand when APIs are registered in the product life cycle&amp;nbsp;before you attempt to use it to avoid&amp;nbsp;any errors. &amp;nbsp; The platform registers all APIs before plugins initialize. &amp;nbsp;This means you can utilize a registered API in a plugin &lt;code&gt;Initialize()&lt;/code&gt; method or in any &lt;code&gt;AfterInitialization() method i&lt;/code&gt;n addition to normal use during the application runtime. &amp;nbsp;You should avoid using any API in &lt;code&gt;BeforeInitialization()&lt;/code&gt; of the plugin life cycle as there is no guarantee an API has been registered.&lt;/p&gt;
&lt;p&gt;To use an API, you retrieve it from the [[api-documentation:Apis In-Process API Service|API In-Process service]] using the &lt;code&gt;Get&amp;lt;&amp;gt;()&lt;/code&gt; method the same way you would get a built-in in-process API. &amp;nbsp;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&amp;nbsp;&lt;code&gt;IApi&lt;/code&gt; then you can retrieve the API by the abstract class type. &amp;nbsp;Similarly if you use an interface for your class that extends &lt;code&gt;IApi&lt;/code&gt;, you can retrieve it by your custom interface type.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;PersonService&amp;gt;();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Or because our &lt;code&gt;PersonService&lt;/code&gt; implements &lt;code&gt;IPersonService&lt;/code&gt; which extends &lt;code&gt;IApi&lt;/code&gt;, this is appropriate as well:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IPersonService&amp;gt;();&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; When using custom interfaces or abstract classes to extend &lt;code&gt;IApi&lt;/code&gt;, 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. &amp;nbsp;If you have a scenario where your APIs share a common interface, the class implementation of that interface should implement &lt;code&gt;IApi&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example if all your APis use an &lt;code&gt;IRepository&lt;/code&gt; interface, then &lt;code&gt;IApi&lt;/code&gt;&amp;nbsp;Should be applied to the class implementation:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IRepository { }

public class PersonRepository : IRepository, IApi { }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;You could apply it to an interface if the interface extends a shared interface, but the interface itself still should only have&amp;nbsp;a single implementation:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;public interface IRepository { }
public interface IPersonRepository : IApi { }
public class PersonRepository : IPersonRepository{ }&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;It is appropriate to wrap any usage of an API in a null check before its used since an &lt;code&gt;IApiDefinition&lt;/code&gt; plugin could have been disabled in Administration(This does not apply to core in-process APIs as they cannot be disabled).&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="csharp"&gt;var personAPI = Telligent.Evolution.Extensibility.Apis.Get&amp;lt;IPersonService&amp;gt;();
if (personAPI != null)
{
    //Intract with personAPI
}&lt;/pre&gt;&lt;/p&gt;
&lt;h2&gt;&lt;a id="Sample" name="Sample"&gt;&lt;/a&gt;Sample&lt;/h2&gt;
&lt;p&gt;You can download the following sample&amp;nbsp;as a guide. &amp;nbsp;Once compiled, deployed to your community bin folder, and the plugin SampleAPIDefinition enabled(Administration -&amp;gt; Extensions) it will write &amp;quot;Random Name: Wally&amp;quot; to the event log (Administration-&amp;gt;Monitoring-&amp;gt;Events) when the plugin initializes.&lt;/p&gt;
&lt;p&gt;&lt;a href="/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/59.52-PM.png"&gt;&lt;img style="display:block;margin-left:auto;margin-right:auto;" src="/resized-image/__size/766x242/__key/communityserver-wikis-components-files/00-00-00-12-83/59.52-PM.png" alt=" " /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://community.telligent.com/cfs-file/__key/communityserver-wikis-components-files/00-00-00-12-83/PersonService_2E00_cs"&gt;community.telligent.com/.../PersonService_2E00_cs&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;
</description></item></channel></rss>