SDK Example Projects
Parent page: Altium Vault SDK
The Altium Vault SDK is installed with a number of C# example projects that have been developed to demonstrate important capabilities that are offered through the Vault Web Services. The projects provide valuable information on the structure, methods and resources used to develop web services applications and interfaces using C#.
The installation currently includes the following example projects:
- BatchAddingParameters - batch addition of parameters to selected Vault components.
- EventListener - define event notification Channels, Listeners and email alerts. Read more detail.
- LoginAndListFolders - login and manipulate Vault folders.
- PartChoices - view component Part Choices information.
- RawSearch - perform a search for items within a Vault.
- ReleaseComponent - release Items (including a Bridge-Item) and Item Revisions in folders, and change Lifecycle states. Read more detail.
- UserManagement - add, update, and remove User Roles and their constituent Users.
Two of the key examples are covered in detail in the following sections.
Release Component example
The ReleaseComponent example is a good place to start for examining how C# applications can be developed for interacting with the Vault API. Load this project into Visual Studio from the \Altium Vault\SDK \examples\ReleaseComponent
folder.
The ReleaseComponent example, as you would expect, releases a component into the Vault in line with the required revision and lifecycle structure. The design component entails PCB footprint and Schematic symbol files which are linked to constitute a basic Altium Designer component. The source Footprint and Symbol library files can be found in the project’s ..\TestFile
folder.
A unique aspect of the example is that it also instigates and loads the non-standard Vault Item; a bridge-item - in this example, a simple web link to a video file. As Altium Designer creates and manipulates a defined range of Vault Items that pertain to electronics design (Components, Schematic sheets, etc) a bridge-item is not directly applicable on the design side of the Vault. However, such an Item will have significance to an external enterprise system, such as a company PLM or other system, and can be linked to relevant conventional Items in the Vault - it acts as a ‘bridge’.
Another process demonstrated by the example project is changing the Lifecycle state of a Revision in response to an external event. In this case, the event is manually instigated via the application's right-click menu option.
Note that most operations that can happen in the vault (creating Items Revisions, changing lifecycle states, etc) are framed in the context of an Item's Revision Definition and Lifecycle Scheme. To advance or regress a Revision's lifecycle state for example, its current lifecycle state needs to be referenced against a list of permitted changes (transitions) that are read in from the Vault. The permitted lifecycle transitions are based on the Revision's current lifecycle state and the Item's Lifecycle Scheme.
By way of example, if an Item Revision's current Lifecycle state is New From Design
and its Item Lifecycle Scheme is set to Component Lifecycle
, the permitted lifecycle transitions will be Promote To Prototype Use
, or Abandon Component
.
The program
In the ReleaseComponent example project, the actual process of releasing and updating components is instigated by the Release button in the Release dialog. Three dialogs (forms) are used; the Login dialog (FormLogin), the Explorer dialog (Explorer), and the Release dialog (FormRelease).
Login
Starting with the FormLogin
class method, in response to the Login button, an IDSClient
instance is created and assigned to the vault URI extracted from the Login form text box (textBoxIDSServer
). The IDSClient.Login
function then logs in to the IDS (Identity) service using the name/password text from the form, which returns loginResult
(of the IDSLoginResult
object type) holding user and session ID parameters.
IDSClient idsClient = new IDSClient(textBoxIDSServer.Text); IDSLoginResult loginResult = idsClient.Login(textBoxUName.Text, textBoxPwd.Text, false)
Following a successful IDS login, the vaultUrl
variable is constructed by replacing ids
with vault
in the form's URI string (textBoxIDSServer
). A VaultClient
instance is created and assigned to the variable's new URI.
string vaultUrl = textBoxIDSServer.Text.ToLower().Replace("ids", "vault"); VaultClient vaultClient = new VaultClient(vaultUrl);
The vaultClient
object then logs in to the Vault service (vaultClient.Login
) using the SessionID
parameter (a GUID) from the established loginResult
variable. The Explorer form is opened, passing the URI-specific vaultClient
object variable.
vaultClient.Login(loginResult.SessionId); Explorer explorer = new Explorer(vaultClient);
Explorer
Following a successful Login process, the Explorer dialog is populated with a list of the Folders and Items returned from the Vault, using the VaultClient.GetFolders
and VaultClient.GetItems
methods (Altium.Sdk.DxpAppServer.VaultClient
). The returned folders list (a VaultFolderList
object) is processed by parent/sub folder GUID and tree node to populate the Explorer tree panel (treeViewFolder
).
VaultFolderList folders = vaultClient.GetFolders(String.Format("PARENTFOLDERGUID = '{0}' order by CREATEDAT", parentFolderGuid));
Similarly, the vaultClient
class is subsequently applied to extract the Vault Items and Item Revisions (the GetItems
and GetRevisions
functions), along with the Vault request option to include Child objects. The methods populate the appropriate panel in the Explorer form (treeViewItemAndRevision
).
VaultItemList items = vaultClient.GetItems(String.Format("FOLDERGUID = '{0}' order by CREATEDAT", folderGuid), new VaultRequestOptions() {VaultRequestOption.IncludeAllChildObjects}); VaultItemRevisionList itemRevisions = vaultClient.GetItemRevisions(String.Format("ITEMGUID = '{0}' order by CREATEDAT", itemGuid), new VaultRequestOptions() {VaultRequestOption.IncludeAllChildObjects});
Item lifecycle states (as GUID numbers) are retrieved by the Vault GetLifeCycleState
function, and may range from just two states for the simplest Lifecycle Definition scheme to multiple states for more complex definitions. These are processed and added to the appropriate Explorer dialog form panel (listViewRevisionInfo
).
VaultLifeCycleState state = vaultClient.GetLifeCycleStateByGuid(revision.LifeCycleStateGUID);
Any links between Item Revisions (such as those between a Symbol and Footprint that define a component) are mapped using GetItemRevisionLinksCount from a vaultClient class instance. These exist in a child/parent arrangement, for example where a Component Item is the Parent of the Symbol and Footprint Items, which are in turn Children of the Component.
int childCount = vaultClient.GetItemRevisionLinksCount(String.Format("PARENTITEMREVISIONGUID = '{0}'", revision.GUID)); int parentCount = vaultClient.GetItemRevisionLinksCount(String.Format("CHILDITEMREVISIONGUID = '{0}'", revision.GUID));
The range of Vault data collection and processing actions are used to populate the Explorer dialog using a tree structure and list, enabled by System classes such as System.Windows.Forms.ListViewItem
. The methods ultimately cause matching HTTP SOAP requests to be sent to the Vault, such as GetALU_Items
, GetALU_ItemRevisions
and so on.
Release dialog
The Release dialog, instigated by the Release button in the Explorer dialog, is where the main action happens. The Release dialog is pre-populated with Symbol, Footprint and Component entries, and when enabled by the Enable Video Content Type checkbox, a bridge-item as a video URL link. Entry name suffix numbers are randomly generated by the Reset button - and when the dialog form is loaded.
A critical aspect of this dialog is the Revision Naming Scheme and Lifecycle Definition drop-down lists (comboBoxRevisionNamingScheme
and comboBoxLifeCycleDefinition
). These must be populated with the available list options from the Vault where they are defined. The vaultClient
class members used are:
GetRevisionNamingSchemes
- list of possible schemes, with HRID (human readable) and GUID informationGetLifeCycleDefinitions
- list of possible definitions, with HRID and GUID information
VaultRevisionNamingSchemeList schemes = vaultClient.GetRevisionNamingSchemes("", new VaultRequestOptions() {VaultRequestOption.IncludeRevisionNameLevels}); VaultLifeCycleDefinitionList lifeCycles = vaultClient.GetLifeCycleDefinitions("", new VaultRequestOptions() {VaultRequestOption.IncludeRevisionNameLevels});
Note that Item types are normally predefined by the Vault, but the new bridge-item is defined in the example by a hard coded GUID.
Creating the Release Script
The populated and configured entries in the Release dialog are sent as Vault entries with the Release button action. The methods in the ReleaseComponent
namespace (in FormRelease.cs
) define and send the data as a single composite script to the Vault API. Here, the script not only has a significant number of direct HTTP requests (rather than SOAP requests), but also needs to include the actual data that will be hosted in the vault - namely, the Symbol and Footprint files in the example's ..\TestFile
sub-folders.
To avoid an inefficient (read; slow) transfer response, the 'Release Component' script (componentReleaseScript
) is compressed/zipped into a serialized 'execute' script as a binary file. Alerted by the incoming ExecuteScript format, the receiving Vault API unzips the data and processes the results.
Here, the buttonRelease_Click
method creates the VaultScript object (Altium.Sdk.DxpAppServer.VaultScript
) and instigates the 'Release Component' script command functions (Altium.Sdk.DxpAppServer.AtomicCommandGroup
)
VaultScript componentReleaseScript = new VaultScript(); AtomicCommandGroup componentReleaseCommandGroup = componentReleaseScript.AddCommandGroup("Release Component");
Using the data extracted from the Release dialog, relevant data commands are sequentially added to the script. The Altium.Sdk.DxpAppServer
assembly offers specific classes for the task, such as:
ScriptCommandAddFolder
ScriptCommandAddItem
VaultItemRevisionLinkList
VaultItemRevisionLink
ScriptCommandReleaseItemRevision
Commands to create the Vault Folders and Items are then added to the script using the above AddFolder and AddItem script command methods. The next steps add commands to release Item Revisions (using ScriptCommandReleaseItemRevision
), and include an assembled list of revision links (VaultItemRevisionLink
). The implemented links define the component by linking it to its constituent Symbol and Footprint Items.
ScriptCommandReleaseItemRevision releaseSymbolCommand = componentReleaseCommandGroup.CreateCommandReleaseItemRevision();
Once complete (and the Video Item is assessed for inclusion), the Release Component script is processed and sent to Vault API using the HTTP POST method. This applies the ExecuteScript
function from the VaultClient
class instance.
vaultClient.ExecuteScript(componentReleaseScript);
The returned response from the Vault then repopulates the Explorer dialog with the newly released vault Item Revisions.
Changing a Revision Lifecycle state
The lifecycle change option is available through a right-click context menu, after first selecting a Revision entry in the Explorer dialog.
The initial action of selecting an Item Revision in the Explorer dialog retrieves its lifecycle state (and any links) from the Vault, then inserts HRID strings and lists the information in the lower panel area in the Explorer form.
VaultLifeCycleState state = vaultClient.GetLifeCycleStateByGuid( revision.LifeCycleStateGUID); ListViewItem stateItem = new ListViewItem(String.Format("{0} is in the {1} state", revision.HRID, state.HRID)); listViewRevisionInfo.Items.Add(stateItem);
Subsequently right-clicking on the selected Item Revision retrieves the full list of lifecycle stages, states and possible transitions that apply to the Item's Lifecycle Definition.
VaultLifeCycleDefinition lifeCycleDefinition = vaultClient.GetLifeCycleDefinitionByGuid(item.LifeCycleDefinitionGUID,new VaultRequestOptions(){VaultRequestOption.IncludeAllChildObjects});
This effectively retrieves the information that is presented in Altium Designer's Edit Lifecycle Definitions dialog for that particular Lifecycle Definition. If an Item's Lifecycle Definition is set to 'Component Lifecycle' for example, the Altium Designer dialog would appear as below, where the information is presented visually in a tabular form:
In the ReleaseComponent project, the retrieved information includes 'lifecycle state before' and 'lifecycle state after' statements for each possible state transition (as GUID numbers). The currently selected Item Revision's lifecycle state (as a GUID) can then be compared to 'before' statement GUIDs in the retrieved list, therefore deriving a set of matches. The 'after' statements for each of these matches then populate the right-click context menu as their respective HRID (description) string.
Clicking on one of the options will instigate the VaultLifecycleChangeState
function, thereby sending a formatted state transition request to the Vault for the selected Item Revision. See the Explorer's contextMenuItemRevision_Opening
method section.
VaultLifeCycleStateChange stateChange = new VaultLifeCycleStateChange(itemRevision.GUID, stateTransition.GUID); vaultClient.AddLifeCycleStateChange(stateChange);
The Item information is subsequently retrieved from the Vault again, repopulating the Vault with the updated data.
Event Listener example
The EventListener example project demonstrates the use of the Event Dispatch Service (EDS) hosted by the Vault server, and the Event Notifications it generates. When enabled, the EDS acts as an Event notification engine for the Vault service by monitoring activity and creating event messages for external distribution.
The EDS Event Notification messages are available through a nominated Event Channel, which can be subscribed by Listeners - those that are registered to receive event messages. Specific Event Notifications can be retrieved from the EDS by interrogating the service from an external application, as a Listener registered to the Event Channel, then filtering the response content accordingly.
A wide range of Vault activity (mainly changes and additions) is logged by the EDS and available as Event Notifications. These can be loosely grouped as:
- Folder events
- Item events
- Revision events
- Revision Naming Scheme events
- Lifecycle Definition events
The Event Channel name is available as a Vault option setting in Altium Designer, but can also be defined and modified by an authorized external system. Listeners are nominated names that are registered (associated) with an Event Channel on a session basis, and are defined by the external listening application or service.
To demonstrate the EDS service and its interaction with the Vault service, the C# EventListener example project provides the base functionality needed to disseminate specific Event Notifications to a nominated Listener and email address.
As a sequence of function steps, the compiled EventListener executable allows you to:
- Login to the Vault Server services
- Set the Vault Event Channel
- Register (or un-register) a Listener to Event Channel
- Nominate an email address to receive event notification summaries
- Start and stop the Event listening (monitoring) cycle
For the purposes of the demonstration example, only Item Release and Lifecycle change event notifications are processed for sending, and a Gmail SMPT Client is used for the email function.
The program
The EventListener C# project is essentially composed of two straightforward dialog screens defined by the FormLogin and FormListener forms and their associated objects and methods - these appear as the Login and Listener dialogs, respectively. As with all Vault SDK examples in the C# domain, the key resource is the DxpServerSDK
class assembly and the member classes in its principle namespaces.
The most direct way to look at the program source here is probably as a sequence of operational steps, along with the C# objects they involve.
Starting with FormLogin
section, the Login button method simply captures the dialog’s URI and name/password entries to an IDSClient.Login
function, logs in to the IDS, then redirects the login URI to the Vault and logs in using the initial login Session ID. For more detail, see the above Release Component Login section.
A successful Vault login result calls the FormListener
method (in FormListener.cs
). Here, the Vault URI is reassigned to the EDS service and passed to a new instance of EDSClient
. The FormListener form is loaded and its text boxes populated with the EDSClient URI and the current Vault's current Event Channel property - the latter is sourced from the Vault instance with the VaultInfo.EventChannel
property of the vaultClient
object.
this.textBoxEDSServer.Text = edsClient.ServiceURL.ToString(); this.textBoxChannelName.Text = vaultClient.VaultInfo.EventChannel;
Channel Name
A change in the entry of the Channel Name text box (such as typing in a new Name) instigates the ChannelName_TextChanged
event handler. This performs dialog housekeeping actions such as enabling/disabling the appropriate text boxes and buttons.
Clicking the Set Channel button instigates the buttonSetChannel_Click
method which, along with dialog configuration housekeeping, updates the Vault’s Event Channel name through an UpdateVaultInfo
request to the Vault service.
vaultClient.VaultInfo.EventChannel = channelName; vaultClient.UpdateVaultInfo(vaultClient.VaultInfo);
Listener Name
The Listener Name field, now enabled, accepts a typed name that will apply to the current session. A ListenerName_TextChanged
event handler, as above, performs appropriate dialog housekeeping.
The action of registering a Listener Name to the assigned Event Channel occurs when the Register Listener check box is checked. Its associated checkBoxRegisterListener_CheckedChanged
method, along with the usual dialog housekeeping, sends a register request to the EDS service using the RegisterEventListener
member of the EDSClient
object.
listenerName = textBoxListenerName.Text; edsClient.RegisterEventListener(listenerName, new List<string>() {channelName});
Note that unchecking the Register Listener box will unregister an existing (currently active) Listener Name with the EDS service - EDSClient.UnRegisterEventListener
.
With an email address entered in the Receive Email field, the event listening action is started with the Start/Stop Listening button, which instigates the buttonListen_Click
method. This defines and configures the email sending service by creating an instance of the System.Net.Mail.SmtpClient
class to use a Gmail™ server, and implements the credentials for a valid Gmail account.
smtpClient = new SmtpClient("smtp.gmail.com", 587); smtpClient.Credentials = new NetworkCredential("eventlistenertest", "Altium123!");
Mail address strings are then created from the email address extracted from the dialog text box, and the StartListen
method instigated.
Listening and processing
For the EventListener example, the action of listening for Event Notifications is formed by sending a stream of Read requests to the EDS service, then responding to any return messages that contain the appropriate content. In this case, that’s a notification of a Revision Release or a change in Lifecycle State.
The StartListen
code instigates a new thread that creates a list of EDS messages (EDSQueueMessageList
) by using ReadEvents
calls to the service. The listening method is encapsulated in a While
loop, which sustains until the thread is aborted by the StopListen
method. A further loop decodes (deserializes) the JSON content message and processes the results.
EDSQueueMessageList messages = edsClient.ReadEvents(10, listenerName, appGuid, appName, Environment.MachineName); foreach (var message in messages) { dynamic contentJson = JsonConvert.DeserializeObject(message.Content);
Each returned event message is scanned for the targeted strings of ‘Release’ (for a Revision release event) and ‘RevisionStateChange’ (for a Lifecycle change event). When detected, the relevant GUID value is extracted from the message content (contentJson.Revision.GUID.Value
for the Release event) and the Vault interrogated for the updated item information. The collected information is then assembled into a suitable email alert string.
Taking the example case of a Lifecycle change event being detected, the ItemRevison
and LifeCycleSateAfter
identifiers (as GUIDs) are stored and then applied in the Vault requests that follow. These data requests are targeted (though filtering) at the specific Revisions and Lifecycle Transitions in the Vault that triggered the Event Notification - as identified by the stored GUIDs.
VaultItemRevision revision = vaultClient.GetItemRevisionByGuid(revisionGuid, new VaultRequestOptions() { VaultRequestOption.IncludeAllChildObjects}); VaultLifeCycleState state = vaultClient.GetLifeCycleStateByGuid(lifeCycleStateGuid);
The resulting information held by the revision and state variables is applied to the SendEmail
method to form the email message content.
SendEmail(String.Format("LifecycleState of {0} has been updated to {1} at {2}", revision.HRID, state.HRID, revision.LastModifiedAt));
The event message IDs (as GUIDs) are then added to the messageID
list, which is sent to the EDS service as a standard SOAP-XML message (edsClient.ProcessEvents
).
Backing up slightly, the SendEmail
method simply sends an email containing the assembled content passed by the calling StartListen
method.
mailMessage.Body = content; smtpClient.Send(mailMessage);
As the content passed to the email function represents Event Notification information (event type, object name, time, etc) the resulting email presents a summary of the Event, thereby informing (or perhaps alerting) the email recipient of the change.
JSON encoded Events
As outlined above, event messages (notifications) from the EDS are formed in the JSON (JavaScript Object Notation) open standard, and decoded using the Newtonsoft.Json
assembly. The basic syntax for JSON includes comma-separated objects as Name-Value pairs, array lists, and strings delimited by double-quotes. See JSON for more information.
The transmitted events from the EDS service have the following object stucture:
{"Action":"xxx","Item":{"ObjectFields"}}
- where xxx
can be Add, Update, Delete, Release, RevisionStateChange.
In the EventListener example, the event actions of 'Release' and 'RevisionStateChange' are detected by interrogating the value of the Action
field with contentJson.Action.Value
.
By way of example, the structure for the JSON event of adding a Vault Item would be:
{
"A
ction":"Add",
"Item":
{
"GUID":"",
"HRID":"",
"CreatedAt":"",
"LastModifiedAt":"",
"CreatedByGUID":"",
"LastModifiedByGUID":"",
"CreatedByName":"",
"LastModifiedByName":"",
"SharingControl":0,
"AccessRights":0,
"Description":"",
"FolderGUID":"",
"LifeCycleDefinitionGUID":"",
"RevisionNamingSchemeGUID":"",
"ContentTypeGUID":"",
"Revisions":[],
"IsShared":0
}
}Note that the JSON event structure above does not include values for each Name-Value object. Note also that the Revisions
item value is an array, indicated by the square brackets []
.
For the process illustrated in the EventListener program, the (human readable) Item name would be returned by:
contentJson.Item.HRID.Value
.
The returned JSON content for the range of possible events (Add, Update, Delete, Release, RevisionStateChange) is generally based on the properties for the Item that has changed or been created. In practice, the EDS JSON event content for an action like adding a Vault Item will be similar to that shown below.
A definitive way to ascertain what message will be returned for a particular event, and under what circumstances, is to create a test program that decodes and displays all events as they occur.
A quick change to achieve a basic reporting program is to simply insert a generic display command (with string conversion) in the EventListener example project, as shown below for the StartListen
method in the FormListener
code. See line 5, highlighted in gray.
foreach (var message in messages) { dynamic contentJson = JsonConvert.DeserializeObject(message.Content); MessageBox.Show(contentJson.ToString()); //added to display all decoded JSON events
When making changes to the Vault content in Altium Designer, all resulting notifications from the EDS service will be decoded and displayed in full, so the EDS notification structure can be tested for a specific Vault action. The display function could also be wrapped in a conditional If
statement to detect and then process a particular event Action of interest - as is done for the Release
and RevisionStateChange
actions in the EventListener code.
The images above and below are examples of this simple Event detection and content display approach.
For an overview of the Altium Vault SDK and server-delivered Web Services, go to: