Writing API prototypes
This tutorial will teach you the basics of creating an api for your services.
Prerequisites
- Windows 10/11
- Visual studio 2019/2022
- Phoesion Glow Blaze , with Reactor running (see getting started guide)
Sample Code
You can download the Sample Code archive from the downloads section.
This tutorial follows the 1_REST sample in the archive. (View code on GitHub)
What is a Module API?
While a Module is a class that contains the code for your Actions, a Module API is a class that contains the prototypes and attributes for those Actions. You don't necessarily need a module api to create your web services, but having one can be very useful and can be used in many different ways. Since the api classes for your service are in a separate assembly, you can distribute/publish the api assemblies(.dll) to the clients that will consume it so they can directly reference/use it in their client-side application. (see Client-side API consumption)
Creating a Module API
In the previous guide we learned how to create a simple Service/Module/Action that simply returned the string "Hello World".
An [Action] can be declared in the module, making it an api-less function, or it can be declared in a different project/class that will serve as the api of the module.
Here is a sample of a module with it's api.
Module Api :
namespace Foompany.Services.SampleService1.API
{
public abstract class SampleModule1
{
[Action(Methods.GET)]
public static string Action1() => null;
}
}
Module Code :
namespace Foompany.Services.SampleService1
{
[API(typeof(API.SampleModule1))]
public class SampleModule1 : FireflyModule
{
[ActionBody(Methods.GET)]
public string Action1()
{
return "Called Action1 of SampleModule1";
}
}
}
Module API Rules
An api class and how it's action prototypes are declared follow some simple rules that you need to keep in mind :
1. The API class must be in a different assembly (c# project) than it's implementation
This separation into different assemblies will :
- Allow other services (c# projects) to reference the api without creating cyclic references.
- Allow the api consumers to use your api dll directly and consume your services in a strong-typed fashion.
2. API method prototypes must be static, have as return the concrete dto type or void, and return null(default) or nothing(void).
The methods that are in api class will never be actually called/executed. They will only be used as prototypes when calling it from other services or client-side.
3. API methods must match the name and arguments of the implementation method.
When compiling the project into a hologram for deployment, the Phoesion Glow Hologram Compiler will examine all action implementations/prototypes and will not allow you to proceed unless everything checks out. This will save you from any problems that could occur at run-time due to api incompatibilities.
Important
An async action that returns Task must have as prototype the return type without async or Task.
Example : for an action body
[ActionBody(Methods.XXX)]
public async Task<string> Action1()
{
//do something with await...
return "ok";
}
the api prototype must be
[Action(Methods.XXX)]
public static string Action1() => null; //NO async and NO Task<>
Recommended solution structure
Having many services with their api and models can get complicated fast.
It's better to follow a pattern when creating a new service to save you from trouble and unnecessary refactoring down the road.
Assuming for example we want to create a new service named SampleService1.
It's recommend that you create the following c# project (assemblies) :
- SampleService1.DataModels or SampleService1.Dto : This will be the project with the data transfer object definitions. No code here, only the classes that will be used for requests and responses to your services.
- SampleService1.API or API.SampleService1 : This will be the project with your public API classes.
- SampleService1.API.Private or API.Private.SampleService1 : This will be the project with your private API classes. (eg. interop api)
- SampleService1 or SampleService1.Code : This will be the project with code for the service.
The hierarchy (references) will be : DataModels <-- API Public/Private <-- Service Code
(so service Code project will reference api projects and the api projects will reference dataModels/Dto )