Extensions
Various pages in this documentation refer to the concept of "Extensions" and which methods are available with or without extensions. What are we talking about?
What are they?
The Archer REST and webservices APIs are well-rounded, but certainly not complete. Some aspects of Archer's object model have no representation in these APIs.
Solutions are a good example. You can query the Archer APIs for almost everything you want to know about Applications, Questionnaires, and to an extent, Subforms, but Solution information is strangely absent. Only one documented Archer API method (ExecuteQuickSearchWithSolutionId in the web services API) even makes reference to the Solution concept. That method requires the integer Solution Id as one of its parameters, despite the fact that there's no way to determine any Solution Ids via the available APIs.
Likewise Subforms are only represented by a single API method (/system/subform/subformid in the REST API). That method allows a subform to be retrieved, but again only by Id, with no associated methods allowing you to easily discover what Ids are applicable. In fact, the only way to determine a subform Id through the standard Archer API is by first encountering a subform field in your Application or Questionnaire metadata (at which point you can determine the related subform's Id via the subform field's "RelatedSubformId" property). Applications and Questionnaires, on the other hand, have API methods that will let you retrieve all of them at once, so it's much easier to look up a specific Application or Questionnaire by name or alias or Guid.
Calc formulas are another concept that are conspicuously absent. The Archer APIs will serve up almost everything you could ever want to know about a field, but if that field is calculated, the APIs will not tell you (as of Archer version 6.12, anyway) what formula is used to calculate that field's value.
Many other features of the Archer platform like this are also inaccessible via the APIs.
Are you using Advanced Workflow, with different layouts configured for each of your workflow stages? Archer's API won't allow you to evaluate any of those. It can only return the default workflow for each level, ignoring all others.
Are you using Datafeeds? Archer's API does have a few methods which allow you to check history for the datafeed and even execute a datafeed on demand, but only if you know the datafeed's Guid. As is the case with the integer Ids of Subforms and Solutions, there are no provisions for discovering a datafeed's Guid, not to mention evaluating a datafeed's configuration or even which datafeeds exist for a given level.
Are you using Reports? The Archer web services API does provide one method for report discovery (GetReports) but it returns nothing that is useful in calling any of the other report-related API methods (all of which need an integer report Id, while GetReports only returns Guids.)
Estrelica.Core's extensions solve all of these problems and more. If extensions are available Estrelica.Core is able to fill in those gaps in Archer's APIs by querying the underlying Archer database for complex entities like Solutions, Subform Ids, Report details, Datafeed details, extended field information like calc formulas, audit info and permission inheritance rules, non-default layouts, level filters, and many other framework entities that are missing from the standard APIs. Estrelica.Core then returns all of these results to the caller through standard interfaces, just like everything else that it returns from the standard Archer APIs.
So how do I make Estrelica.Core do this?
Extensions are available in the Professional and Enterprise editions of Estrelica.Core.
There are two ways to enable Estrelica.Core's extensions in these editions: by supplying Estrelica.Core with a connection string to your Archer instance database as part of its configuration (allowing it to make calls directly to the database), or by configuring the CastleHill Extended API on your Archer IIS server (effectively hiding the database calls behind a REST API).
Extensions are also available for evaluation with a Trial license, but only via the direct database method.
The particulars of each approach are described below.
Direct Database Calls
You may have noticed that the Estrelica.Core.CreateSession() method discussed here has an optional string parameter named archerDbConnectionString, and that the json configuration files discussed here make reference to a "connectionString" setting in those files. Each of these refer to the Archer instance database which hosts the metadata and content for your Archer instance.
If you supply a valid connection string to your Archer instance database during setup (via the archerDbConnectionString parameter if you're calling core.CreateSession() yourself, or via the json "connectionString" setting if you're using CoreConfig.Load()), extensions will become enabled for that instance of the Core.
Here are examples of each approach, first enabling direct database extensions via discrete calls to ValidateLicense() and CreateSession():
var core = Estrelica.Core.ValidateLicense("5E56F79E-E678-4BAF-8FCF-B50141FAD5C7", w => LogWarning(w)));
core.CreateSession("https://archer.company.com", "Archer-Prod", "apiuser@company.com", "Password123",
// Passing a valid connection string to the Archer-Prod instance db in the optional archerDbConnectionString
// parameter enables extensions for this instance of Estrelica.Core:
"Data Source=SQL123;Initial Catalog=Archer-Prod_instance;Persist Security Info=True;User ID=readonly_user;Password=xyz123");
or, alternately, via the CoreConfig.Load() method, with the connection string stored in appSettings.json:
/* Local appSettings.json file looks like this:
{
"CHSAuthKey": "5E56F79E-E678-4BAF-8FCF-B50141FAD5C7",
"Archer": {
"url": "https://archer.company.com",
"instance": "Archer-Prod",
"username": "apiuser@company.com",
"password": "Password123",
"connectionString": "Data Source=SQL-SERVER123;Initial Catalog=Archer-Prod_instance;Persist Security Info=True;User ID=readonly_user;Password=xyz123",
*/
var core = CoreConfig.Load(e => w => LogWarning(w));
Since Estrelica.Core only queries the instance database, never performing inserts or updates, the account specified via this connection string only needs db_datareader access to the target database.
Extended API calls
The CastleHill Extended API is an ASP.NET application available with the Professional and Enterprise editions of Estrelica.Core. When deployed to your Archer IIS server, it provides your Archer instance with a new set of API methods. These methods implement all the database calls described above, wrapping them in a REST API layer which introduces new API endpoints, following the same calling conventions as the standard Archer REST API. This approach mitigates risk since you don't have to grant Archer instance database access to your entire development team, or include connection strings in any of your deployed applications' configuration files. With the Extended API, all connections to the instance database are made from your IIS server, rather than from your Estrelica.Core-based application.
Furthermore, the direct database approach is an all-or-none proposition. Any developer with read access to the database can run whatever arbitrary SQL select statements against it that they like. The Extended API, however, allows you to fine tune this capability with role-based permissions, restricting its access to only those Archer users who have been assigned specific Roles that you define.
Regardless of which path you choose, enabling extensions will cause calls like core.Metadata.AllSolutions to start returning the Solutions you expect rather than empty sets, and any calculated fields that are returned via myLevel.Fields.Where<IIsCalculatedProperty>(f => f.IsCalculated) will actually have formulas in their .Formula property instead of null.
Can I use these extended methods on a SaaS instance hosted by Archer?
Unfortunately no. Extended methods are only available to on-premises customers who have access to their Archer instance database. However, SaaS customers are able to use all of the non-extended methods and behavior of Estrelica.Core with their hosted instance.
Calls made to any Estrelica.Core resolver classes which depend on extended methods (e.g. MetadataResolver.AllSolutions) will return empty IEnumerables or null results in the event that the underlying extension method is unavailable.
I have multiple Archer instances. How does Estrelica.Core ensure that extended results are returned from the correct one?
Estrelica.Core won't do anything without a valid Archer session, and all extended method calls are first verified by checking to confirm that the current session exists in the target instance database (whether you're accessing it directly, or via the Extended API).
When using extensions in database mode (where you've supplied the Core with a specific connection string), this validation step will raise an InvalidOperationException error if your connection string does not resolve to the Archer instance database where your session was established.
When using extensions via the Extended API, your session token is validated by the API server application in the same way, raising a standard "401 Unauthorized" HTTP error if the session cannot be validated (or if your Archer user account is not in any of the Archer Roles required for the method).
In addition, the session token associated with each API call is also used by the server to resolve the correct instance database to be used for making its database calls. This means that if you have multiple Archer instances hosted on the same IIS server, you can likewise configure the Extended API on that server to return extended results for any or all of those Archer instances, simply by configuring it with with separate connection strings to each instance database.
These approaches ensure that the results of the standard Archer API calls and the results of the Estrelica.Core extended method calls are always returned from the same physical Archer instance.
What happens if both extension paths are available?
By default, Estrelica.Core will always attempt to query the database directly if you've provided it with a connection string, even if it detects that the Extended API is available on your Archer IIS server. You can change this behavior if you like by calling:
core.APIFacade.ExtensionPreference = APIPreference.ExtendedAPIFirst; // default is DatabaseFirst
With this setting, all extended method calls will first check to see if an appropriate version of the Extended API is available on your Archer IIS server before falling back to direct database calls.
How do I know if extensions are enabled for my instance of Estrelica.Core?
This method:
var available = core.APIFacade.ExtensionsAvailable();
will return one of the values from this enumeration, depending on the current ExtensionPreference setting:
public enum APISource
{
None = 0,
ExtendedAPI = 1,
Database = 2
}
If extensions are not available (e.g. if you are running Estrelica.Core Basic, or if you're running one of the other versions but have not provided a connection string or deployed the Extended API to your Archer IIS server), this will return APISource.None.
If both extension paths are available, this will return whichever path is discovered first according to the APIFacade.ExtensionPreference setting described above.
Otherwise, if only one of the two paths is available, the corresponding APISource value will be returned for that path.
I have extensions available in my development environment. How can I confirm my code's behavior if deployed to another environment where extensions are not available?
You can test this scenario by temporarily disabling all extensions. This can be done by simply calling:
core.APIFacade.EnableExtensions = false;
When operating in this mode, Estrelica.Core will behave as though neither extension path is present, regardless of whether you've provided it with a connection string or if it discovers the Extended API on your target Archer IIS server. This is equivalent to operating under an Estrelica.Core Basic license, which does not include any extended method capability.
I just upgraded to the latest version of Estrelica.Core, but I have not upgraded my installation of the Extended API yet. What happens if I call a new Estrelica.Core extended method that isn't supported by my instance of the Extended API?
All of the extended methods are versioned, and Estrelica.Core knows which methods are supported by each release of the Extended API. When the Core performs its extension path check (i.e. determining whether to call the Extended API or make the database call directly), it will also evaluate the version of the Extended API when making this determination. In other words, it will treat the Extended API as "temporarily unavailable" in this case if you're calling a new extended method that is not supported by your outdated version of the Extended API.
In this situation, if you've also provided a connection string to your Archer instance database it will fall back to the direct database query. Otherwise it will raise an exception telling you that you need to upgrade your Extended API (with a message indicating the specific minimum version required).