Aras Innovator Programmers Guide
Aras Innovator Programmers Guide
Programmer’s Guide
Document #: 12.0.02019054101
Last Modified: 05/24/2019
Aras Innovator 12
Programmer’s Guide
Copyright Information
Copyright © 2019 Aras Corporation. All Rights Reserved.
Aras Corporation
100 Brickstone Square
Suite 100
Andover, MA 01810
Phone: 978-806-9400
Fax: 978-794-9826
E-mail: [email protected]
Website: https://www.aras.com
Notice of Rights
Copyright © 2019 by Aras Corporation. This material may be distributed only subject to the terms and conditions set forth in the
Open Publication License, V1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/).
Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.
Distribution of the work or derivative of the work in any standard (paper) book form for commercial purposes is prohibited unless
prior permission is obtained from the copyright holder.
Aras Innovator, Aras, and the Aras Corp "A" logo are registered trademarks of Aras Corporation in the United States and other
countries.
All other trademarks referenced herein are the property of their respective owners.
Notice of Liability
The information contained in this document is distributed on an "As Is" basis, without warranty of any kind, express or implied,
including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-
infringement. Aras shall have no liability to any person or entity with respect to any loss or damage caused or alleged to be caused
directly or indirectly by the information contained in this document or by the software or hardware products described herein.
Table of Contents
Send Us Your Comments ............................................................................................. 6
Document Conventions ................................................................................................ 7
1 Introduction .............................................................................................................. 8
1.1 The Item ....................................................................................................................................... 8
1.2 The Aras Markup Language (AML) .............................................................................................. 9
1.3 Methods and the IOM ................................................................................................................. 10
2 AML ......................................................................................................................... 11
2.1 <Item> Tag ................................................................................................................................. 11
2.2 <Relationships> Tag .................................................................................................................. 11
2.3 <property> Tags ......................................................................................................................... 11
2.4 Attributes .................................................................................................................................... 12
2.4.1 Item Attributes ............................................................................................................. 12
2.4.2 Property Attributes ....................................................................................................... 14
4 Methods .................................................................................................................. 23
4.1 Item Actions Extend the Item Class ........................................................................................... 23
4.1.1 Context Item ................................................................................................................ 24
4.1.2 Methods are Item Factories ......................................................................................... 24
4.1.3 Handling the Wrong ItemType ..................................................................................... 24
4.1.4 Methodology ................................................................................................................ 25
4.2 Built in Action Methods ............................................................................................................... 25
4.3 Generic Methods ........................................................................................................................ 27
4.3.1 Context Item ................................................................................................................ 27
4.3.2 Methods are Item Factories ......................................................................................... 27
4.3.3 Methodology ................................................................................................................ 28
9 Debugging .............................................................................................................. 91
9.1 Enabling Debugging in Aras Innovator ...................................................................................... 91
9.2 Setting up VS.NET to debug Server side Methods .................................................................... 91
9.3 Setting up VS.NET to debug Client side Methods ..................................................................... 93
9.4 Setting up the server side logging .............................................................................................. 94
If you find any errors or have any other suggestions for improvement, indicate the document title, and the
chapter, section, and page number (if available).
If you would like a reply, provide your name, email address, address, and telephone number.
Document Conventions
The following table highlights the document conventions used in the document:
Document Conventions
Convention Description
Yellow highlight Red text highlighted in yellow indicates the code parameter
with red text that needs to be changed or replaced.
Successive menu Successive menu choices may appear with a greater than
choices sign (-->) between the items that you will select
consecutively.
Example: Navigate to File --> Save --> OK.
1 Introduction
The purpose of this document is to provide a Guide to Programming Aras Innovator. It covers key
aspects of programming Aras Innovator for implementing your own business logic within the Aras
Innovator Enterprise Application Framework.
This document is intended to be used as a Desktop Reference and User Guide covering the following
topics:
The AML (Aras Markup Language), which is the language that drives the Aras Innovator server.
The IOM (Innovator Object Model), which is the Object API for the AML.
How Methods work and the Methodology for implementing your own business logic.
A Cookbook of recipes for performing common tasks.
The .NET controls API the Innovator Client is built on.
There is the ‘Method’ ItemType, which is used to implement user defined business logic. Methods are
written in JavaScript, C#, or VB.Net and use the IOM API to implement the business logic.
The following is a Method in JavaScript using the IOM that is the same as the AML BOM example in the
previous section:
var innovator = new Innovator();
var partItem = innovator.newItem("Part","add");
partItem.setProperty("item_number", "999-888");
partItem.setProperty("description", "Some Assy");
bomItem.setRelatedItem(relatedItem);
partItem.addRelationship(bomItem) ;
2 AML
The AML is the XML dialect and language that drives the Aras Innovator server. Clients submit AML
documents to the Aras Innovator server via HTTP. The server parses the AML applying the business
logic defined as the action attribute for the Items in the AML document, and an AML document is
returned. The AML dialect is very simple. The following sections describe the tags that define the AML
language:
Refer to section 4.2 Built in Action Methods for the list of Innovator pre-built actions.
The following is an AML query example requesting a Part Item and its BOM relationships:
<Item type="Part" id="ACBDEF0123456789…" action="get">
<Relationships>
<Item type="BOM" action="get"/>
</Relationships>
</Item>
The following AML illustrates a simple Item configuration for describing a Part to Part BOM relationship:
<Item type="Part" action="add">
<item_number>999-888</item_number>
<description>Some Assy</description>
<Relationships>
<Item type="Part BOM" action="add">
<quantity>10</quantity>
<related_id>
<Item type="Part" action="add">
<item_number>123-456</item_number>
<description>1/4w 10% 10K Resistor</description>
</Item>
</related_id>
</Item>
</Relationships>
</Item>
Property values always use locale-neutral formats. Decimal and float values use the period symbol (.) as
the decimal separator and no digit separator (i.e. commas separating thousands). The dash symbol (-) is
used to denote a negative value. Date/Time values should be in ‘YYYY-MM-DD[Thh:mm:ss]’ format and
in the local (or corporate) time zone. Language-specific values use the xml:lang attribute to specify the
language code. For example:
<Item type="Part">
<item_number>292-102</item_number>
<i18n:name xml:lang="de"
xmlns:i18n="http://www.aras.com/I18N">Rad</i18n:name>
<i18n:name xml:lang="en"
xmlns:i18n="http://www.aras.com/I18N">Wheel</i18n:name>
<cost>232.13</cost>
<created_on>2008-08-24T08:12:02</created_on>
</Item>
2.4 Attributes
Properties are used to define the data for an Item. Attributes are meta-data for the Item or Property. They
are used to control the server logic and Methods. Think of attributes like command line switches, or as
arguments to a function.
In addition to the type, id, and action attributes mentioned above there are several additional attributes
used to control the server. The following is the attribute reference for the <Item> tag:
type String The ItemType name for which the Item is an instance.
where String Used instead of the id attribute to specify the WHERE clause for the
search criteria. Include the table name with the column name using
action String The name of the Method (or Built in Action Method) to apply to the
Item.
doGetItem Boolean If 0 then do not perform a final get action on the Item after the server
performed that action as defined by the action attribute. Default is 1.
select String A comma delimited list of property names (column names) to return
which is the SELECT clause in the SQL statement.
orderBy String A comma delimited list of property names (column names) to order
the results and is the ORDER BY clause in the SQL statement.
maxRecords Integer This defines the absolute maximum Items to be searched in the
database.
levels Integer The Item configuration depth to be returned. This should be used
with caution because of the performance hit due to its lack of
granularity in the data fetched. Use the nested Relationships style of
defining your queries to do the same thing but with far greater
performance.
serverEvents Boolean If 0 then disable the server events improving performance. Default is
1.
isCriteria Boolean If 0 then include the nested structure for the Item configuration in the
response but don't use it as search criteria. Default is 1, which uses
the nested structure in the request as search criteria.
related_expa Boolean If 0 then do not expand the related_id Property for the relationship
nd Items to include the related Item. Another word returns its ID.
serverEvents Boolean If 0 then disable the server events improving performance. Default is
1. Only ‘Update’ events are disabled, ‘Lock’ events can be executed
if using ‘Edit’.
Attribute Usage
keyed_name This is the keyed_name Property for the Item referenced by the Item type Property.
condition This is the condition value for the AML query. The condition value is any valid
SELECT condition supported by the database. The following is the list of possible
condition values:
Condition Comments
lt
like The value for the Property tag would include wild card
symbols, which are % for any characters and _ for a single
not like
character.
Example:<name condition="like">Tom%</name>
is Possible values for the Property tag could be null or not null.
is null Example:
is not null <cost condition="is null"/>
<cost condition="is not null"/>
Attribute Usage
Xml:lang Language code for multilingual properties. You must use this in conjunction with
the internationalization namespace on the property tag. For example:
<i18n:name xml:lang="de"
xmlns:i18n="http://www.aras.com/I18N">Rad</i18n:name>
3 IOM Reference
IOM Reference provides a general description of the IOM (Innovator Object Model or Item Object Model)
API. A more detailed API reference may be obtained from one of the following:
On-line: Go to https://www.aras.com/support/documentation/
Under the section Other Documents, click On-Line API Guide.html.
From Innovator Client UI: Login as Innovator Administrator. Under the Help menu, select API
Reference.
In Innovator CD Image: Go to the documentation folder and open Aras Innovator - API
Guide.html.
The IOM is an Object Model for the AML, but it is not purely Object Oriented. Using Object Oriented
terms, an ItemType is like a ‘Class’ and the Item is like an ‘Object’. Although the Item is an Object with
methods, there is only one Item Class for all ItemTypes. In a pure Object Oriented representation, there
would be a Class for each ItemType because each ItemType has its own set of Properties to describe the
different Items.
An Item Object is intended to be abstract and pliable. Depending on its internal structure, the Item Object
usually represents one of five following supported types of IOM Items:
Note: The term ‘method’ has two meanings in this guide; the typographical convention used throughout
this Guide is as follows:
Lowercase ‘method’ refers to methods on an IOM Item Object.
Capitalized ‘Method’ refers to Method Items stored in the Aras Innovator database.
Sample code is shown in Courier 10pt font.
Optional arguments are surrounded by [] characters.
Typically, you do not need to know about or deal with the credentials Object because the Methods run in
a logged in session. You can, however, set the credentials for the Item Object using these methods, if
you want to submit the apply requests to a different Aras Innovator server. The IOMCredentials Class
methods are mostly getters and setters for URLs (Innovator and Vault servers), DB name, and login name
and password.
Other members of this class perform miscellaneous non-Item related operations. Use them if you need to
get a new GUID (methods getNewID() ), generate a next sequence value (method
getNextSequence(…) ), or calculate the MD5 hash value for a given string (method ScalcMD5(…) .)
Item public constructor has one required argument itemtype-name and one optional argument action.
The new Item is only populated with the Properties and default values from the ItemType when the
optional action argument is ‘add’.
The Item Class public field dom represents a DOM Object that holds the data for the Item in the AML
format.
The Item Class base method apply(…)submits the AML apply request to the Innovator Server using the
context Item DOM as the AML source and returns a new Item built on the XML returned by the Server. In
contrast, the base method loadAML(…) does not return a new Item but rather rebuilds this.dom using
AML taken as an argument.
You can call clone(…)method to get a new identical instance of the context Item and you can call
setNewID() method to replace the context Item id by newly generated GUID.
Use Call method isCollection()to find out whether or not the Item represents a set of Items, e. g.
whether or not its dom property holds more than one Item node. Use Call isError()method to find out
whether or not the Item represents an Error. See the IOM API on-line reference for more boolean
members of the Item Class.
Methods such as getAction(), getID(), and getType() return a value of Item node action, id, and
type attribute respectively, while method getAttribute(…) takes an attribute-name as an argument
and, therefore, can be used to get any attribute by name. Thus, getAction()is a short cut to
getAttribute(“action”), getID() is a short cut to getAttribute(“id”), and so on.
Each get method in this group has a corresponding set method: setAction(…),
setID(…),setType(…), and setAttribute(…). Notice that method setAttribute(…) not only
sets new value for an existing attribute but can also add a new attribute to the Item node and then sets its
value.
Property methods comprise a set of accessors to Item properties and Item property’s attributes: get_, set_
(which acts also as add_), and remove_. In addition, if a property has/needs a nested Item there are
methods to get/insert these nested Items.
The setProperty method requires property values to be in a locale-neutral format. Decimal and float
values should use the period symbol (.) as the decimal separator and no digit separator (i.e. commas
separating thousands). The dash symbol (-) should be used to denote a negative value. Date/Time
values should be in ‘YYYY-MM-DD[Thh:mm:ss]’ format and in the local (or corporate) time zone.
Language-specific values should be set using the language code as the third argument.
This group is comprised of methods to work with collections. Collection in this context is a set of Items as
in the case for results from a query. Method appendItem(…) appends its Item Object argument to an
existing collection or converts a single Item instance to a set of Items. This mechanism is illustrated in the
following C# sample:
Innovator myInnovator = this.getInnovator();
Item myItem = myInnovator.newItem("myType","myAction");
At this point, myItem presents a single Item instance, myItem.dom XML looks like this:
<Item isNew="1" isTemp="1" type="myType" action="myAction" />
and myItem.isCollection() returns false. But three extra line of code:
Item addedItem = myInnovator.newItem("added","myAction");
// set ID to be able to remove addedItem later
addedItem.setID(myInnovator.getNewID());
myItem.appendItem(addedItem);
converts myItem to a collection, e.g. myItem.isCollection() returns true, and myItem.dom XML
becomes as follows:
<AML>
<Item isNew="1" isTemp="1" type="myType" action="myAction" />
<Item isNew="1" isTemp="1" type="added" action="myAction"
id="B12F9384B1DE4C4F8158C36D18269BE9" />
</AML>
If the Item object id is not NULL it can be removed from the collection:
myItem.removeItem(addedItem);
Use the getItemCount() method to determine the size of a collection, the getItemByIndex(…)
method to get an instance of the Item Object based on its position inside of the collection, and method
getItemsByXPath(…) to find an Item by its XPath.
The methods newOR(), newAND(), and newNOT() inserts logical node with tag <or>, <and> and
<not> respectively under the parent Item node and returns an Item Object that represents a newly
inserted logical node. For example, the following code:
You can create a new item using method newItem(…). See code samples in sections 3.3.6-3.3.8 for the
method usage illustration.
Error methods are comprised of a set of accessors to Error specific properties such as “faultcode”
(methods get/setErrorCode(…),) “faultstring” (methods get/setErrorString(…) ,) “faultactor”
(get/setErrorSource(…) ,) and “detail” (methods get/setErrorDetail(…) .)
This set of methods implements specific functionality on the Item, which extends the base Item Class.
For reference purposes all the Extended Item Class methods are organized in the following four
categories:
Getting Innovator reference method:
getInnovator() – see examples of usage in section 3.2.
Lock methods:
lockItem()
unlockItem()
Life Cycle method:
promote(…)
Workflow methods:
instantiateWorkflow(…)
The following methods are obsolete and will be removed from future releases:
4 Methods
Business logic in Aras Innovator is implemented using Method Items and is written in JavaScript, C#, or
VB.Net often using the IOM to interact with Aras Innovator Items.
There are three ways to implement Methods in Aras Innovator on the server side:
Item Action Methods which extend the Item Class and perform logic on Item instances.
Generic Methods, which implement arbitrary logic.
Server Events which implement logic on the context Item before and\or after the server operates on
the Item.
Similarly there are three ways to implement Methods in Aras Innovator on the client side:
Item Methods which extend the Item Class and perform logic on Item instances.
Generic Methods, which implement arbitrary logic.
Form, Field, and Grid Events which implement logic on client side UI events.
Client Events that can be attached to an Item Type; triggered when user’s interaction with Innovator
UI generate a new Item.
The Method Item has a comment Property that you can use to annotate the Method and can be seen
when you search and review the Methods as mentioned above.
As mentioned before Item Action Methods are executed on an instance of Item which is called context
item (read section 5 Action Items for more information on how context item is obtained for Item Action
Methods). The context item must be referenced inside Item Action Methods as the this keyword in
JavaScript, and C#, and the Me keyword Object in VB.Net. The context item is an instance of IOM Item
class; correspondingly any methods of IOM Item class (see section 3.3 for more details) could be called
on the context item, e.g this.getProperty(“foo”) (C#) or Me.getProperty(“foo”) (VB.Net).
Note: In order to be able to execute Method’s code Innovator plugs it into a particular template that
provides required code attributes (method and class boundaries, import statements, etc.). Each
supported language (JavaScript, C#, VB.NET, etc.) has several available templates in Innovator.
Everything written in the section is applied to default templates (there is one default template per
supported language). Methods can explicitly redefine the template that is used during the method
compilation. Usage of alternative templates and the methodology of writing valid Methods for
them is left outside the scope of the document.
Methods follow the Factory design pattern in that they return an Item or Error Object. The ‘Item Action’
Method must return an Item, which often is the result of an Item.apply() method call; typically the last step
in the business logic for the Method. There are several ways to create an Item; the following IOM
methods return an Item Object: Item.apply(), Item.newItem(), Item.clone(), Innovator.newItem(),
Innovator.newResult(), and Innovator.newError().
C#
Item qryItem = this.newItem(this.getType(), "get");
qryItem.setID(this.getID());
qryItem.setLevels(1);
return qryItem.apply();
If the Method needs to return an Error then use the Innovator.newError(text) method.
C#
Innovator innovator = this.getInnovator();
return innovator.newError("This method has <b>failed</b>.");
Sometimes it is desirable to share the same Method for many ItemTypes. However, there are cases in
which the Method is intended to be used only by an Item of a specific ItemType.
The way you can prevent the use of a Method with a context item of a wrong type is to throw an exception
when the wrong ItemType is used (this is what the core Item Class methods do when the ItemType is not
of the specific desired value). Here is a sample of what should be done in a Method that needs to
operate on a specific type of Item:
C#
Innovator innovator = this.getInnovator();
if (this.getType() != "My ItemType")
{
return innovator.newError("Item must be of type 'My ItemType'");
}
return null;
4.1.4 Methodology
One of the principle concepts in programming Aras Innovator is to write Methods called on Items. The
‘Item Action’ relationships on ItemTypes simulate Object Oriented programming, where the ItemType is
the Class and ‘Item Action’ relationships to Methods are the Class methods. Literally the Method code is
compiled dynamically to extend the Item Class with this method and calls it (see also notes to 0). Similar
to class instance in OO programming the context item is an object on which Methods are performed. At
the same time there are some peculiarities in how to use a context item in Innovator’s Item Action
Methods. One important detail about Item Action Methods is that they must always return an Item which
is considered to be the result of work done by the Item Action Method. An Item Action Method might work
with context item but the context item is used here more as an input value (it still must be referenced as
this or Me from inside Methods). It’s highly recommended that Item Action Methods do not change the
context item but rather create a new item that is returned from the method. You can use the combination
of the Item.getProperty(…) method with the Item.setProperty(…) method to populate the new
temporary Item or use the Item.clone(…) method to construct the new Item from the context item. If
the developer of Method code chooses to modify the context item and not create a new item, the context
item must be returned from the method.
Built in Comments
Action
Method
delete Deletes all versions of the Item. The purge and delete are the same for non-
versionable Items.
get Gets the Item(s) and its configuration based on the AML Item configuration used to
query the database.
getItemConfig Returns the Item configuration as described by the standard AML query. The AML
in and out are no different from the standard action=‘get’.
The GetItemConfig is optimized by limiting the logic done between the SQL call
and the AML result. The performance improvement is gained by limiting the
features typically available in Innovator GetItem (no server events or access
checking on the sub level Items).
lock Locks the Item and is the same as the Item.lockItem() method.
unlock Locks the Item and is the same as the Item.unlockItem() method.
version Creates a new generation of an Item, clearing the locked_by_id of the originating
Item and setting the locked_by_id in the new generation. It then applies an update
to the newly created generation. The server events triggered in the following
sequence: onBeforeVersion, onAfterVersion, onBeforeUpdate, onAfterUpdate.
If the item is not versionable, an exception is thrown.
The context Item is the this keyword Object in JavaScript and C#, and is the Me Object in VB.Net. The
XML data for the context Item is the XML submitted as the payload for the request and it may not be valid
AML, just well formatted XML. It does not matter it is the input for the Generic Method and can be
whatever you want it to be.
The Generic Method must return an Item or an Error similar to ‘Item Action’ Methods. Often the result of
the Generic Method is some simple text or an HTML fragment. The text can be returned using the
Innovator.newResult(text) method. If the Method needs to return an Error use
Innovator.newError(text) method.
C#
Innovator innovator = this.getInnovator();
return innovator.newResult("This method was <b>successful</b>.");
OR
Innovator innovator = this.getInnovator();
return innovator.newError("This method has <b>failed</b>.");
C# Example
Innovator innovator = this.getInnovator();
Item item = this.newItem("User", "get");
Item results = item.apply();
4.3.3 Methodology
Typically all you need are simple name/value pairs as input for your Method and those are like Property
tags for the Item. The body for the Generic Method is nested inside an <Item> tag so you can pass a
name/value pair as arguments to the Generic Methods like ordinary Property tags.
The Item passed as the context Item can represent any Item you want including fictitious Items. You have
the added advantage of continuing to use the IOM API to operate on the context Item Object.
In the case of the Server Event Method, the context item is a direct analogy of a class instance (i.e.
object) in OO programming in the sense that the Method operates on its context item (as it was
mentioned above the context item could be referenced as the this keyword in JavaScript and C#, and
the Me keyword Object in VB.Net from inside the Method). In other words the purpose of a Server Event
can be defined as ‘changing the context item’, so the modified context item is the result of work done by
the Server Event Method. Of course, the Server Event Method doesn’t necessarily have to alter its
context item but rather perform some other actions (e.g. log some info; send e-mail; etc.); this is usually
typical for Methods performed on OnAfterXXX event.
4.4.2 Methodology
A Server Event Method might return an Item only if it wants to return an error. Otherwise Server Event
Method may not have a return statement.
C#
Innovator innovator = this.getInnovator();
return innovator.newError("This method failed.");
In the case Method is called as the OnBeforeXXX event and it returns an error, the context Item is
replaced with an Error Item and is simply passed on through to the client. No further server action is
taken. In the case of an OnAfterXXX event the server rolls back the transaction and passes the Error
back on through to the client.
It’s important to understand that Server Event Methods that are called on OnBeforeXXX events operate
on the request AML sent from the client. Server Event Methods that are called on OnAfterXXX events
operate on the response AML that server is about to send back to client and Server Event Methods that
fully replace server actions (OnXXX) get client request AML as context item and must replace it with
response AML that is passed on through to the client. In other words, it’s important to remember that
Server Event Methods called on OnBeforeXXX events are invoked before the server parses the request
and after the Method is done the context item must have a valid request AML format (it could be modified
by the method but it still should have a valid format so that server would be able to parse it). From the
other side, Server Event Methods called on OnAfterXXX events are invoked after the server processed
the request, and after the Method is done the context item must have a valid response AML format (it
could be modified, e.g. Method could populate it with federated data, but it should be valid response AML,
so that client would be able to parse it.)
The following Server Events are currently available in Aras Innovator. Each of the following events is
followed by a short description and an example of common use.
OnBeforeAdd
o Runs before an item is added to the database (through the add, create or merge actions.)
o OnBeforeAdd methods are often used for validation purposes (e.g. to make sure the
property values do not violate a business rule). The same method that is called
OnBeforeAdd is often also called OnBeforeUpdate, to perform the same validation.
OnAfterAdd
o Runs after an item is added to the database (through the add, create or merge actions), but
before it is returned to the client.
o OnAfterAdd methods are used to synchronize with other items or with external systems
(e.g. add a new part number to ERP).
OnAdd
o Runs in place of the built-in add action (via add, create or merge). Neither OnBeforeAdd
nor OnAfterAdd events are called when using OnAdd.
o An OnAdd method completely replaces the built-in add action, and is typically used for
federated items. The method is expected to create the appropriate records in the database
and form a proper AML response. Failure to do either is likely to result in an error.
OnBeforeUpdate
o Runs before an item is updated in the database (through the update, edit or merge actions.)
o OnBeforeUpdate methods are often used for validation purposes (often along with
OnBeforeAdd). The request may either be rejected completely (by returning an error) or
modified to conform to the proper rules.
OnAfterUpdate
o Runs after an item is updated in the database (through the update, edit or merge actions), but
before it is returned to the client.
o OnAfterUpdate methods can be used to synchronize with other items or with external
systems (e.g. updating a part description in ERP).
OnUpdate
o Runs in place of the built-in update action (via update, edit or merge). Neither
OnBeforeUpdate nor OnAfterUpdate events are called when using OnUpdate.
o An OnUpdate method completely replaces the built-in update action, and would typically be
used for federated items. The method is expected to modify the appropriate records in the
database and form a proper AML response.
OnBeforeDelete
o Runs before an item is deleted (through the delete or purge actions.)
o OnBeforeDelete methods are typically used to cancel a delete operation based on a
business rule.
OnAfterDelete
o Runs after an item is deleted (through the delete or purge actions.)
o OnAfterDelete methods would be used to synchronize with other items or with external
systems (e.g. remove a record from ERP.)
OnDelete
o Runs in place of the built-in delete action. Neither OnBeforeDelete nor OnAfterDelete
events are called when using OnDelete.
o An OnDelete method completely replaces the built-in delete action, and is typically used for
federated items. The method is expected to remove the appropriate records in the database
and form a proper response.
OnBeforeGet
o Runs before a search.
o OnBeforeGet methods are typically used to add additional criteria to a search, based on
business rules. For example, the method might find the default location of the user and add
that location as criteria for the query.
OnAfterGet
o Runs after a search is executed, but before the results are returned.
o OnAfterGet methods are commonly used to populate federated properties. This might
involve performing calculations on other properties or extracting data from an external
system. Once the value of the federated property is set, it appears to the client like any other
property.
OnGet
o Runs in place of the built-in get action. Neither OnBeforeGet nor OnAfterGet events are
called when using OnGet.
o An OnGet method completely replaces the built-in get action, and is typically used for
federated items. The method is expected to retrieve the appropriate records in the database
and form a proper AML response.
OnBeforeCopy
o Runs before an item is copied (via the copy action.)
o An OnBeforeCopy method might be used to cancel a copy operation that violates a
business rule.
OnAfterCopy
o Runs before an item is copied (via the copy action.)
o OnAfterCopy methods can be used to set properties of the new item created by the copy.
OnBeforeLock
o Runs before an item is locked (via the lock or edit actions)
o An OnBeforeLock method may be used to prevent an item from being locked based on
business rules.
OnAfterLock
o Runs after an item is locked (via the lock or edit actions.)
o OnAfterLock methods may be used to synchronize locks with other items.
OnBeforeUnlock
o Runs before an item is unlocked.
o An OnBeforeUnlock method may be used to prevent an item from being unlocked based
on business rules.
OnAfterUnlock
o Runs after an item is unlocked.
o OnAfterUnlock methods may be used to synchronize locks with other items.
OnBeforeVersion
o Runs before an item is versioned (through the version, update, edit or merge actions.)
o OnBeforeVersion methods are typically used to cancel a version operation based on a
business rule.
OnAfterVersion
o Runs after an item is versioned (through the version, update, edit or merge actions.)
o An OnAfterVersion method might be used to set properties of the new item version.
OnBeforeMethod
o Runs before Server Action Method.
OnAfterMethod
o Runs after Server Action Method.
OnGetKeyedName
o Runs when the system generates the keyed_name for an item.
o Used to override the standard logic for generating keyed names.
The ability to define a server event against a Polymorphic ItemType was introduced with the Aras
Innovator 12.0 release. The benefits of defining the server event against the Polymorphic ItemType is
that the event will be processed for all poly-sources.
For example, if you want a single server event to be triggered against all CAD, Document, and Part
ItemTypes, you could simply add an event handler to a server event on the Change Controlled Item
ItemType. Once defined against the Polymorphic ItemType, all poly sources will inherit the event handler
which will be executed every time the event occurs on any of poly sources.
You can view all inherited methods against an ItemType by selecting the Inherited Server Events
tab for the ItemType you are working with.
The ability to mark a server event as “required” was introduced with the release of Aras Innovator 12.0.
Server Events that are marked as required cannot be ignored by using the serverEvents=0 attribute as
part of AML request.
To set a server event as required, so that it is not ignored, you need to set the is_required Boolean
property to 1 for the ServerEvent.
Figure 1.
A new version for server events was introduced with the release of Aras Innovator 12. The new version
of server events allows for improved performance when there is a group of items passed to be acted
upon.
By default all server events follow the standard behavior that has been seen in previous releases of Aras
Innovator (Version 1). The new version (Version 2) is described for each operation in the following
sections.
4.4.6.1 onAfterUpdate, onAfterAdd, and onAfterVersion Version 2
The onAfterUpdate, onAfterAdd, and onAfterVersion Version 2 event is designed for use when where or
idList attribute is specified on the <Item …> node of the AML request. The server event is executed only
once for the entire group, as opposed to once per item as the Version 1 event does. The context item
contains the results of all the items applied as part of the update statement.
Form Events
Field Events
Grid Events
Item Type Events
Item Actions
The this keyword context Object is an Item Object for Item Actions. However, the context Object is not
the Item Object for Form, Field, and Grid Events. This context Object is the browser document (DOM)
Object for the Form and Grid Events and is the Field Object for Field Events.
The context Item Object for Form, Grid, and Field Events is the document.thisItem Object, which is
an Item Object and should be used with the IOM API. For relationship grid events use
parent.thisItem, which is a pointer to the document.thisItem Object.
The Form Events are the HTML page events; for example, onLoad, onUnload, onResize,
onMouseDown, onMouseUp, and others (refer to the ‘Form Events’ List in Aras Innovator for the complete
list of available events.)
You bind your Method to the Form Event using the Form Tool. Select the Form Event tab and add the
event relationships as shown below:
Figure 2.
The Field Events are the HTML field events; for example, onSelect, onClick, onChange, onBlur, onFocus,
and others (refer to the ‘Field Events’ List in Aras Innovator for the complete list of available events.) Use
the following procdure:
1. Bind your Method to the Field Event using the Form Tool.
2. Select the Field by clicking on it in the canvas area in form Tool or from the Fields grid in the
upper left hand corner of the Form Tool.
3. Select the Field Event tab and add the event relationships as shown below:
Figure 3.
Grid Events are the events for the grid control, which is used in the Relationships tab area for tear off Item
windows. The grid events occur on the row (section 4.5.4.1) and on the cell (section 4.5.4.2.)
Like Server Events you bind a Method as the callback for the event as the Grid Event relationship on the
RelationshipType Item, and as the Grid Event relationship on the Property Item.
The Method gets at least three arguments: relationshipID, relatedID, gridApplet. The relationshipID is the
ID for the relationship Item for the selected row. The relatedID is the ID for the related Item for the
selected row. And the gridApplet is a handle to the grid control object. The relatedID maybe empty if
there is no related Item for the relationship row. The relationshipID is also the ID for the grid control row.
Edit the RelationshipType Item and add Grid Events relationships as shown below:
Figure 4.
Event Comment
relationshipID String The ID for the relationship Item. This is also the
selected row ID for the grid control.
relatedID String The ID for the related Item. The relatedID maybe
empty if there is no related Item for the relationship
row.
Figure 5.
Event Comment
Default Search
onSearchDialog
relationshipID String The ID for the relationship Item. This is also the
selected row ID for the grid control.
relatedID String The ID for the related Item. The relatedID maybe
empty if there is no related Item for the relationship
row.
propertyName String The name of the Property for the cell column selected.
Client Events that can be attached to an Item Type are triggered when your UI actions generate a new
Item. These events are triggered from the client interface regardless of UI context or where in the GUI the
new Item creation was initialized. These events would be triggered universally from the Main Menu, the
TOC RMB menu, the Main Grid RMB menu, Relationship Grid, etc.
For Item Type new item creation, 3 events have been implemented. One event is triggered before a new
Item is created; another event is triggered after an Item has been created; the third event replaces the
standard client ‘new Item’ logic.
onBeforeNew: Method runs prior to a new Item creation. It has the ability to cancel subsequent
client operations (i.e., form opening). It has the ability to cancel creation of new Items.
This event is often used to validate current conditions and determine if it is ok to create a new Item.
onAfterNew: Method runs after a new Item is created. Subsequent standard client logic is executed
following method completion (i.e., form opening). Method is passed a new Item.
This event is often used to populate a new item with data and open custom dialogs.
onNew: The method replaces the standard ‘new Item’ client behavior.
This event is used in special situations where a solution must maintain full control over the new Item
creation process.
Note: It is possible that both onBeforeNew and onAfterNew events are assigned to the same
ItemType and therefore executed sequentially.
Figure 6.
The Methods related to the ItemType via the ‘Item Action’ relationship are called via the action attribute
and the Item.apply() method. Review them by searching the ‘Item Actions’ Tab on the ItemType.
The Methods related to the ItemType via the ‘Server Event’ relationship are called by the server as pre
and post event callbacks for the primitive server actions: add, update, delete, and get. Review them by
searching the ‘Server Events’ Tab on the ItemType.
Review the Generic Methods by searching the Method Items.
5 Action Items
An Action Item is how Methods are bound to the client User Interface. Actions provide the hooks for
invoking Methods from the Action menu bar choice or from the right mouse context popup menu. An
Action is invoked on the client side but can call either a client or server side Method. In both cases the
context Item must be defined.
The item_query Property on the Action Item is used to specify the query used to populate the context
Item. This Property is of data_type="text" because it is actually an XSLT stylesheet. Simply put the
item_query Action Property drives the content for the context Item for the Action Methods.
The use of an XSLT stylesheet for the item_query is consistent with how Aras Innovator sends out Email
Notifications for Life Cycle promotions both on the State and on the Transition, on Workflow Activities,
and in the Report Tool. The concept is the XSLT stylesheet is applied to the Item and the result is the
AML query, which is used to get the context Item for the Method. This allows you to basically turn an
Item into a query for the data you want as the context Item for the Method.
The default value for the item_query Action Property is:
<Item type="{@type}" id="{@id}" action="get" levels="0"/>
Note the use of the XSLT ‘Attribute Substitution’ for the type and id attributes.
If you want all your old actions, created with Innovator 6.1.5 or earlier, that expect relationships to work,
use the following query string:
<Item type="{@type}" id="{@id}" action="get" levels="1"/>
The rules for how the content for the context Item are defined in the following sections for both client and
server Methods.
The Action needs to set up the Item for the server side Method request. This can range from the dirty
Item from the client cache to only the <Item> tag with its type and id attributes plus the action
attribute specifying the Method name to run.
To achieve backward compatibility with existing server side Method logic the context Item must be the
Item from a server pre-GetItem call with levels="0". The server knows to do this when the same
format for the AML we pass today is still passed, which is to put the ID for the Item as a Property in
the request not as an attribute:
<Item type="ItemType Name" action="Method Name">
<id>itemID</id>
</Item>
The stylesheet for the item_query value would be the following, which constructs the AML format
above:
<Item type="{@type}"><id><xsl:value-of select="@id"/></id></Item>
If there is no cache Item and no item_query value then the temporary Item with the type attribute and
the id is nested as a Property tag as shown above is passed as the request triggering the server to do
the pre-GetItem levels="0" as today and the result is the context Item for the Method.
If there is a cache Item and it is dirty and no item_query value then passes the dirty Item, which is the
content for the context Item for the server Method.
If there is an item_query value but no cache Item then a temporary Item is used containing only the
Item tag with the type and id attributes. Plus the doGetItem="1" attribute is included, which forces the
server to do the pre-GetItem using this as its query criteria and its results is the content for the
context Item for the server side Method.
If there is a cache Item and it is not dirty and has item_query value applies the stylesheet to the
cached Item and pass that as the Item request. Plus the doGetItem="1" attribute is included, which
forces the server to do the pre-GetItem using AML passed as the query criteria and the results is the
content for the context Item for the server side Method.
Summary: Invokes client side Item Method and the content for the context Item
is the cached Item.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="client".
Exception Paths:
Summary: Invokes client side Item Method and the only criteria known is the
type and id so the content for the context Item is only the Item tag
with the type and id attributes.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="client".
Exception Paths: The type or id is unknown when the condition requires them to be
known.
5.3.3 Client side - has cache Item not dirty - no item_query value
Use Case Client side has cache Item not dirty no item_query value
Name:
Summary: Invokes client side Item Method and the content for the context Item
is cached Item.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="client".
Exception Paths:
5.3.4 Client side - has cache Item not dirty - has item_query value
Use Case Client side has cache Item not dirty has item_query value
Name:
Summary: Invokes client side Item Method and the content for the context Item
is the result from a server request using the result of the XSLT
transformation of the cached Item with the item_query stylesheet as
the AML query server request.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="client".
Summary: Invokes client side Item Method and the content for the context Item
is the result of a server request using the result of the XSLT
transformation of a temporary Item that only includes the type and id
attributes with the item_query stylesheet as the AML query server
request.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="client".
Exception Paths: 1. The type or id is unknown when the condition requires them to
be known.
2. The item_query is not a valid XSLT stylesheet.
Summary: Invokes server side Item Method and the content for the context Item
is the cached Item passed as the request AML.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="server".
Exception Paths:
Summary: Invokes server side Item Method and the only criteria known is the
type and id. The AML request is the nested id tag style we pass
today, which tells the server to perform the pre-GetItem with
levels="0" and the result is the content for the context Item. This is
the same as we currently do today.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="server".
Exception Paths: The type or id is unknown when the condition requires them to be
known.
Use Case Server side has cache Item not dirty no item_query value
Name:
Summary: Invokes server side Item Method and the AML request is the nested
id tag style we pass today, which tells the server to perform the pre-
GetItem with levels="0" and the result is the content for the context
Item. This is the same as we currently do today.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="client".
Exception Paths:
5.3.9 Server side - has cache Item/not dirty - has item_query value
Use Case Server side has cache Item not dirty has item_query value
Name:
Summary: Invokes server side Item Method and the content for the context Item
is the result from a server pre-GetItem where the AML passed is the
AML query, which is the result of the XSLT transformation of the
cached Item with the item_query stylesheet; plus the doGetItem="1"
attribute is also set, which tells the server to do the pre-GetItem using
the request AML as the query, the results is the content for the
context Item.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="server".
Summary: Invokes server side Item Method and the content for the context Item
is the result from a server pre-GetItem where the AML passed is the
AML query, which is the result of the XSLT transformation of a
temporary Item that has only the Item tag with the type and id
attributes with the item_query stylesheet; plus the doGetItem="1"
attribute is also set, which tells the server to do the pre-GetItem
passing its results as the content for the context Item.
Preconditions: 1. That an Item is selected and the type and id for the selected
Item is known by the client.
2. That the ItemType for the selected Item has an "Item Action"
RelationshipType and the Action type="item" and
location="server".
Exception Paths: 1. The type or id is unknown when the condition requires them to
be known.
2. The item_query is not a valid XSLT stylesheet.
7 Cookbook
This section is a Cookbook of recipes to help you solve common tasks while developing Methods. The
examples are shown in JavaScript, C# and VB.Net when possible.
Technique
There are basically two ways to create a new Innovator object; by getting the Innovator from the Item
object or (only in JavaScript) calling the Class constructor.
JavaScript
var myInnovator = new Innovator();
var myInnovator = this.getInnovator();
C#
Innovator myInnovator = this.getInnovator();
VB.Net
Dim myInnovator As Innovator = Me.getInnovator()
Technique
There are basically two ways to create a new Item Object; by calling the factory methods on the Item
object or Innovator object or (only in JavaScript) calling the Class constructor.
JavaScript
var myItem = new Item();
var myItem = this.newItem(myType,myAction);
var myInnovator = this.getInnovator();
var myItem = myInnovator.newItem(myType,myAction);
var myResult = myInnovator.newResult(resultText);
var myError = myInnovator.newError(errorMessage);
C#
Item myItem = this.newItem(myType,myAction);
VB.Net
Dim myItem As Item = Me.NewItem(myType,myAction)
Dim myInnovator As Innovator = Me.getInnovator()
Dim myItem As Item = myInnovator.NewItem(myType,myAction)
Dim myResult As Item = myInnovator.NewResult(resultText)
Dim myError As Item = myInnovator.NewError(errorMessage)
Technique
There are a few ways to get an Item when you know its id and type, the simplest being the
Innovator.getItemById() method. However, if you need to be granular about your request then
building the query using the IOM is required. This provides the ability to include controls to limit the
results and define the structure to be returned for the Items found.
JavaScript
var qryItem = this.newItem(myType,"get");
qryItem.setID(myId);
var results = qryItem.apply();
C#
Item qryItem = this.newItem(myType,"get");
qryItem.setID(myId);
Item results = qryItem.apply();
VB.Net
Dim qryItem As Item = Me.NewItem(myType,"get")
qryItem.setID(myId)
Dim results As Item = qryItem.Apply()
Technique
There is no difference in setting up a query for a single Item or for many. Only the criteria define the set
size returned. In this recipe you create an Item and populate the query criteria, apply it, and iterating over
the Items returned producing a HTML <TABLE> fragment.
JavaScript
var qryItem = this.newItem("Part","get");
qryItem.setAttribute("select","item_number,description,cost");
qryItem.setProperty("cost", "100");
qryItem.setPropertyCondition("cost", "gt");
var results = qryItem.apply();
var count = results.getItemCount();
var content = "<table>";
for (var i=0; i<count; ++i)
{
var item = results.getItemByIndex(i);
content += "" +
"<tr>" +
"<td>" + item.getProperty("item_number") + "</td>" +
"<td>" + item.getProperty("description") + "</td>" +
"<td>" + item.getProperty("cost") + "</td>" +
"</tr>";
}
content += "</table>";
return content;
C#
Item qryItem = this.newItem("Part","get");
qryItem.setAttribute("select","item_number,description,cost");
qryItem.setProperty("cost", "100");
qryItem.setPropertyCondition("cost", "gt");
Item results = qryItem.apply();
int count = results.getItemCount();
int i;
string content = "<table>";
for (i=0; i<count; ++i)
{
Item item = results.getItemByIndex(i);
content += "" +
"<tr>" +
"<td>" + item.getProperty("item_number") + "</td>" +
"<td>" + item.getProperty("description") + "</td>" +
"<td>" + item.getProperty("cost") + "</td>" +
"</tr>";
}
content += "</table>";
Innovator innovator = this.getInnovator();
return innovator.newResult(content);
VB.Net
Dim qryItem As Item = Me.NewItem("Part","get")
qryItem.SetAttribute("select","item_number,description,cost")
qryItem.SetProperty("cost", "100")
qryItem.SetPropertyCondition("cost", "gt")
Dim results As Item = qryItem.Apply()
Dim count As Integer = results.GetItemCount()
Dim i As Integer
Dim content As String = "<table>"
For i=0 to count - 1
Dim item As Item = results.GetItemByIndex(i)
content += "" + _
"<tr>" + _
"<td>" + item.GetProperty("item_number") + "</td>" + _
"<td>" + item.GetProperty("description") + "</td>" + _
"<td>" + item.GetProperty("cost") + "</td>" + _
"</tr>"
Next
content += "</table>"
Technique
To query for an Item and retrieve its structure you build the query as the structure you want returned.
Use the IOM methods to add the relationships you want and build the structure in the Item. The server
returns the structure that follows the request structure.
This recipe illustrates several related concepts together, which are how to get a set of Items from an Item
and how to iterate over the set, plus how to get the related Item from the relationship Item.
JavaScript
var innovator = this.getInnovator();
content += "<tr>" +
"<td>" + bomPart.getProperty("item_number") + "</td>" +
"<td>" + bomPart.getProperty("description") + "</td>" +
"<td>" + bomPart.getProperty("cost") + "</td>" +
"<td>" + bom.getProperty("quantity") + "</td>" +
"</tr>";
}
return content + "</table>";
C#
Innovator innovator = this.getInnovator();
if (results.isError()) {
return innovator.newError("Item not found: " + results.getErrorDetail());
}
content += "" +
"<tr>" +
"<td>" + bomPart.getProperty("item_number") + "</td>" +
"<td>" + bomPart.getProperty("description") + "</td>" +
"<td>" + bomPart.getProperty("cost") + "</td>" +
"<td>" + bom.getProperty("quantity") + "</td>" +
"</tr>";
}
content += "</table>";
return innovator.newResult(content);
VB.Net
Dim innovator As Innovator = Me.getInnovator()
' Get a handle to the related Item for this relationship Item.
Dim bomPart As Item = bom.getRelatedItem()
content += _
"<tr>" + _
"<td>" + bomPart.getProperty("item_number") + "</td>" + _
"<td>" + bomPart.getProperty("description") + "</td>" + _
"<td>" + bomPart.getProperty("cost") + "</td>" + _
"<td>" + bom.getProperty("quantity") + "</td>" + _
"</tr>"
Next
content += "</table>"
Return innovator.newResult(content)
Technique
Create an Item Object but use the Item.loadAML() method to populate the Item.
JavaScript
var innovator = new Innovator();
var qryItem = innovator.newItem();
qryItem.loadAML(
"<Item type='Part' action='get' select='item_number,description,cost'>" +
"<item_number condition='like'>1%</item_number>" +
"<Relationships>" +
"<Item type='Part BOM' action='get' select='quantity'>" +
"<quantity condition='gt'>1</quantity>" +
"</Item>" +
"</Relationships>" +
"</Item>"
);
Technique
Use the item action getItemNextStates to get the next state values. This recipe assumes there is a
select input field on the form for us to populate with state values.
HTML
<select id="mySelect"></select>
JavaScript
var results = document.thisItem.apply("getItemNextStates");
var nextStates = results.getItemsByXPath('//Item[@type="Life Cycle State"]');
var count = nextStates.getItemCount();
Technique
The following are some key points to understand when constructing an AML query:
1. Use the get action on the relationship Items to include it as search criteria.
a. Without the get action the relationship Item is ignored as search criteria.
b. The relationship Items are also returned. Currently there is no way to use relationships as
search criteria and not return them in the results, as you can with the related Item described
below.
2. Include the related_id property name in the select attribute for the relationship Item if you want to
return the related Item nested inside the related_id property in the results.
<Item type="Part BOM" select="quantity,related_id"/>
Use () to include the select attribute value for the related Item inside the select attribute for the
relationship Item.
<Item type="Part BOM" select="quantity,related_id(item_number,description)"/>
3. The select attribute for the nested Item tag for the related_id property has higher precedence over
the select value inside the () for the relationship's select attribute.
4. The get action is not required for the nested Item tag for the related_id property to include it as
search criteria.
These two AML scripts are equivalent queries for selecting the name property for the related
Item:
<Item type="User" action="get" select="first_name,last_name,email">
<Relationships>
<Item type="alias" action="get" select="related_id(name)"/>
</Relationships>
</Item>
<Item type="User" action="get" select="first_name,last_name,email">
<Relationships>
<Item type="alias" action="get" select="related_id">
<related_id>
<Item type="Identity" action="get" select="name"/>
</related_id>
</Item>
</Relationships>
</Item>
Clearly the first example is simpler and requires less coding (referring to the IOM logic that would
construct the AML) and is the recommended style when all you require is specifying a select for
the related Item for the query.
But the second style opens the opportunity to now include additional search criteria for the related
Item.
AML
<Item type="User" action="get" select="first_name,last_name,email">
<Relationships>
<Item type="Alias" action="get" select="related_id">
<!--
This get will limit root Items to only those that match the relationship
criteria.
The get action is required otherwise the criteria are ignored.
To include the nested Item tag for the related_id include the property name
in the select attribute for the relationship Item.
Can include the select attribute value for the related Item inside ()
i.e. related_id(name)
-->
<related_id>
<Item type="Identity" action="get" select="keyed_name">
<!--
This get has no effect and the search will work with or without it.
It is recommended that you include it because the AML parser may be stricter
in the future.
The select attribute over rules the parent relationships select.
-->
<name>Larry Bird</name>
</Item>
</related_id>
</Item>
</Relationships>
</Item>
JavaScript
var innovator = new Innovator();
var qry = innovator.newItem("User","get");
qry.setAttribute("select","first_name,last_name,email");
alias.setRelatedItem(identity);
qry.addRelationship(alias) ;
Technique
Adding an Item configuration is done by building the Item structure using the IOM methods.
JavaScript
var innovator = new Innovator();
var partItem = innovator.newItem("Part","add");
partItem.setProperty("item_number", "123-456");
partItem.setProperty("description", "Blah blah");
bomItem.setRelatedItem(relatedItem);
partItem.addRelationship(bomItem) ;
Technique
The following is the same thing but uses the Item.loadAML() method to populate the Item Object with
AML text.
JavaScript
var innovator = new Innovator();
var partItem = innovator.newItem();
partItem.loadAML(
"<Item type='Part' action='add' >" +
"<item_number>123-456</item_number>" +
"<description>Blah blah</description>" +
"<Relationships>" +
"<Item type='Part BOM' action='add'>" +
"<quantity>10</quantity>" +
"<related_id>" +
"<Item type='Part' action='get'>" +
"<item_number>555-555</item_number>" +
"</Item>" +
"</related_id>" +
"</Item>" +
"</Relationships>" +
"</Item>"
);
Technique
Use the Item Class Extended Method set to add a new Named Permission Item.
JavaScript
var innovator = new Innovator();
var permItem = innovator.newItem("Permission","add");
permItem.setProperty("name", "AK Part Permissions");
setIdentityAccess(permItem, "All Employees", "get", true);
setIdentityAccess(permItem, "CM", "get", true);
setIdentityAccess(permItem, "CM", "update", true);
setIdentityAccess(permItem, "CM", "delete", true);
resultItem = permItem.apply();
if (resultItem.isError()) {
top.aras.AlertError(resultItem.getErrorDetail());
return;
}
Technique
Use the Item Class Extended Method set to set a new private Permission for an Item.
JavaScript
// Set up the Part query
var innovator = new Innovator;
var qryItem = innovator.newItem("Part", "get");
qryItem.setAttribute("select", "id,permission_id");
qryItem.setAttribute("expand", "1");
qryItem.setAttribute("levels", "1");
qryItem.setPropertyCondition("item_number", "like");
qryItem.setProperty("item_number", "123%");
// Iterate over the Items returned and add the private permissions for each.
var count = resultItem.getItemCount();
for (i=0; i<count; ++i) {
var item = resultItem.getItemByIndex(i);
var permItem = item.getPropertyItem("permission_id");
permItem.setProperty("name", permItem.getID());
setIdentityAccess(permItem, "Component Engineering", "get", true);
setIdentityAccess(permItem, "CM", "get", true);
setIdentityAccess(permItem, "CM", "update", true);
item.setAction("edit");
resultItem = item.apply();
if (resultItem.isError()) {
top.aras.AlertError(resultItem.getErrorDetail()); }
}
Technique
Use the Innovator.applyMethod() method to apply Generic Methods. The following examples
assume a server-side method named "Reverse String" exists, and that it returns a result item containing
the reversed contents of the <string> tag.
JavaScript
var inn = this.getInnovator();
var results = inn.applyMethod("Reverse String", "<string>abc</string>");
return results.getResult(); // returns "cba"
C#
Innovator inn = this.getInnovator();
Item results = inn.applyMethod("Reverse String", "<string>abc</string>");
// Return a result item with "cba" as the contents of the Result tag
return inn.newResult(results.getResult());
VB.Net
Dim inn As Innovator = Me.getInnovator()
Dim results As Item = inn.applyMethod("Reverse String",
"<string>abc</string>")
' Return a result item With "cba" As the contents of the Result tag
Return inn.newResult(results.getResult())
Technique
Use the File and StreamWriter namespaces to write to a text file.
C#
Innovator myInnovator = this.getInnovator();
string path = CCO.Server.MapPath("temp/yoyo.txt");
try
{
if (File.Exists(path)) File.Delete(path);
StreamWriter sw = File.CreateText(path);
sw.Write(this.dom.InnerXml);
sw.Close();
}
catch (Exception e)
{
return myInnovator.newError(e.Message);
}
return myInnovator.newResult("ok");
Technique
Use Aras.IOM.Item.email(mail_item, idnt_item) method to send email to a particular Innovator’s identity.
Note: Innovator’s identity could be a group of people in which case the email is sent to all of them.
C#
...
// It’s assumed here that required identity (item of type ‘Identity’)
// has already obtained (see other examples on how to perform ‘get’
// requests to Innovator server using IOM). Same about item of type
// ‘User’ that represents the person who sends the email (‘fromUser’).
Item idnt = ...
Item fromUser = ...
email_msg.setProperty("subject", subject);
email_msg.setProperty("body_plain", body);
email_msg.setPropertyItem("from_user", fromUser);
Technique
In HTML code use the DOJO control name (e.g. GridContainer in the code sample below), the special
<td> tag and appropriate control event handlers to run the control on the page. Make sure that all the
event handlers for the control are placed in HTML code above the <td> tag:
HTML Code
<script type="text/javascript"
src="../javascript/include.aspx?classes=ScriptSet2"></script>
<script type="text/javascript"
src="../javascript/include.aspx?classes=XmlDocument"></script>
<script type="text/javascript"
src="../javascript/include.aspx?classes=/dojo.js"
data-dojo-config="isDebug: false, parseOnLoad: false,
baseUrl:'../javascript/dojo'"></script>
<script>
var gridControl = null;
var gridXML = '' +
'<table>' +
' <thead>' +
' <th align="c">Name</th>' +
' </thead>' +
' <columns>' +
' <column width="130" order="0" />' +
' </columns>' +
' <tr>' +
' <td>Test</td>' +
' </tr>' +
'</table>';
window.addEventListener("DOMContentLoaded", function () {
clientControlsFactory.createControl("Aras.Client.Controls.Public.GridContaine
r", {id: "grid", connectId: "gridTD"}, function(control) {
gridControl = grid = control;
clientControlsFactory.on(grid, {
"gridClick": onClick,
"gridKeyPress": onKeyPressed,
"gridEditCell": OnEditCell,
"gridMenuClick": onMenuClick,
"gridMenuInit": InitMenu,
"gridDoubleClick": onDoubleClick
});
gridControl.Delimeter="|";
gridControl.InitXML(gridXML);
});
});
function onClick(row, col)
{
return;
}
function onKeyPressed(kEv)
{
return;
}
function OnEditCell(event, row, col)
{
return;
}
function onMenuClick(menuChoice)
{
return;
}
function InitMenu(row, col)
{
return;
}
function onDoubleClick(rId)
{
return;
}
</script>
<table>
<tr>
<td style="width:300px; height: 300px;" valign="top" id="gridTD">
</td>
</tr>
</table>
Technique
Use the Innovator.applySQL(…) method to submit SQL direct to the database. The format of the xml
returned by the Innovator.applySQL(…) where passed SQL statement is a ‘select’ statement is the
following:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=...>
<SOAP-ENV:Body>
<ApplySQLResponse>
<Item>
<A>aval</A>
<B>bval</B>
….
</Item>
<Item>
…
</Item>
…
</ApplySQLResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In case executed SQL statement doesn’t return a record set (e.g. update [table] …), the returned AML
either contains a <Fault> if SQL statement failed or looks like this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV=...>
<SOAP-ENV:Body>
<ApplySQLResponse>
OK
</ApplySQLResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This recipe returns the XML from the applySQL() method and forms HTML for a table to display the data.
C#
Innovator myInnovator = this.getInnovator();
Item results = myInnovator.applySQL(
"select login_name,first_name,last_name,email " +
"from [user] " +
"order by last_name,first_name");
"<thead>" +
"<tr>" +
"<th>Login Name</th>" +
"<th>First Name</th>" +
"<th>Last Name</th>" +
"<th>EMail</th>" +
"</tr>" +
"</thead>" +
"<tbody>";
content += "" +
"</tbody>" +
"</table>";
return myInnovator.newResult(content);
Technique
Add the Grid Event relationship to a Method as the callback for the OnSelectRow event.
Figure 7.
The Method gets three arguments: relationshipID, relatedID and gridApplet. The relationshipID is the ID
for the relationship Item for the selected row. The relatedID is the ID for the related Item for the selected
row. The gridApplet is a handle to the grid control object.
The relationshipID is also the ID for the grid control row. This recipe calls the gridApplet Deselect()
method if the relationship Item for the selected row has not been modified.
JavaScript
// The row ID is the same as the relationship ID
var rowId = gridApplet.getSelectedId();
// Check the isDirty attribute to see if the relationship has been modified
var isDirty = (relItem.getAttribute("isDirty") == "1");
if (!isDirty) { gridApplet.Deselect(); }
Technique
Add the Event relationship to a Property as the callback for the OnEditCell event.
Figure 8.
The Method gets five arguments: relationshipID, relatedID, propertyName, colNumber, gridApplet
The propertyName is the name of the Property for the cell column selected, and colNumber is the column
position number in the grid.
Simple return false and this blurs the grid cell.
JavaScript
// Get the current value of the cell
var cellValue = gridApplet.GetCellValue(relationshipID,colNumber);
Technique
Add an HTML Field (positioned at Point (300,10) in the code sample below) and insert an HTML code
than defines the <div>tag to hold the dynamically populated grid and the JavaScript to get the populating
grid relationships.
HTML Field code
<div id="gridTD" style="width: 400px; height: 500px;"></div>
<script type="text/javascript">
var myCount = 0;
var gridControl;
clientControlsFactory.createControl("Aras.Client.Controls.Public.GridContaine
r", {id: "grid", connectId: "gridTD", canEdit_Experimental: function () {
return false; }}, function(control){
gridControl = control;
clientControlsFactory.on(gridControl, {
"gridClick": function (rowID, column) {
alert("rowId:" + rowID + ", col:" + column);
}
});
fillGrid();
});
function fillGrid() {
var item = document.thisItem;
// Get the relationships
var qry = item.newItem("Part BOM", "get");
qry.setAttribute("select", "quantity,related_id(item_number,name,cost)");
qry.setProperty("source_id", item.getID());
var results = qry.apply();
if (results.getItemCount() < 0) {
top.aras.AlertError(results.getErrorDetail());
return;
}
// Populate the grid with the results.
populateGrid(item, results);
}
function populateGrid(item, results) {
var propNameArr = new Array("item_number", "name", "cost");
var gridXml =
"<table editable='false' draw_grid='true'>" +
"<columns>" +
"<column width='30%' order='0' align='left' />" +
"<column width='40%' order='1' align='left' />" +
"<column width='15%' order='2' align='right' />" +
"<column width='15%' order='3' align='right' />" +
"</columns>" +
"<thead>" +
"<th>Part Number</th>" +
"<th>Name</th>" +
"<th>Cost</th>" +
"<th>Quantity</th>" +
"</thead>" +
"</table>";
var inn = item.getInnovator();
var gridDom = inn.newXMLDocument();
gridDom.loadXML(gridXml);
var tableNd = gridDom.selectSingleNode("/table");
var c = results.getItemCount();
for (var i=0; i<c; ++i) {
var bom = results.getItemByIndex(i);
var part = bom.getRelatedItem();
var trNd = gridDom.createElement("tr");
trNd.setAttribute("id", bom.getID());
var tdNd;
for (var j=0; j<propNameArr.length; j++) {
tdNd = gridDom.createElement("td");
tdNd.text = part.getProperty(propNameArr[j]);+
trNd.appendChild(tdNd);
}
tdNd = gridDom.createElement("td");
tdNd.text = bom.getProperty("quantity");
trNd.appendChild(tdNd);
tableNd.appendChild(trNd);
}
gridControl.InitXML(gridDom.xml);
} </script>
Technique
Use the classic Aras Innovator API top.aras.getIdentityList() method, which returns a comma delimited
string of ID's.
Note: The classic API will eventually be eliminated and this method will become available on the IOM
Innovator object as Innovator.getIdentityList().
JavaScript
// This will get an array of identity IDs from the client cache
var myIdentityIDs = top.aras.getIdentityList().split(',');
Technique
Use the classic Aras Innovator API top.aras.getNetSequence() method, which returns the next sequence
value from the server.
Note: The classic API will eventually be eliminated and this method will become available on the IOM
Innovator object as Innovator.getNetSequence().
Using the Form Tool we add an HTML Field to the Form, which we use to insert the HTML and JavaScript
code for to provide the button to get the next sequence value and update the Field value and client cache.
// This will update the client cache with the new value.
handleItemChange("item_number", seq);
}
</script>
Technique
You will need to use the setFileProperty call which handles creating a file and sets the associated
value on the specified property.
Client-side methods use selectFile()that gets a File object based on user selection:
Javascript
var vlt = top.aras.vault;
vlt.selectFile().then(function (fileObject)
{
var d = aras.IomInnovator.newItem("CAD", "add");
d.setProperty("item_number", "007");
d.setFileProperty("native_file", fileObject);
d.apply();
});
Server-side methods require a string for the physical path to the file. The file must be on the server
machine.
C#
Technique
This is similar to the last recipe, but uses the getItemByKeyedName() method to get an existing File
Item and copyAsNew() to create it as a new File Item.
JavaScript
// Create the Document item
var docItem = this.newItem("Document","add");
docItem.setProperty("item_number","456");
Technique
Use the Pre Server Method on the Life Cycle Transition to call a server side Method to validate the Item
before it is promoted and if invalid rejects the Promote by returning an Error Item.
Figure 9.
C#
Innovator innovator = this.getInnovator();
if (Convert.ToDecimal(this.getProperty("cost")) > 500) {
Item error = innovator.newError("Error promoting: Item costs more than
$500.00");
return error;
}
return this;
VB.Net
Dim innovator As Innovator = Me.getInnovator()
If (CDec(Me.getProperty("cost")) > 500) Then
Dim Err As Item = innovator.newError("Error promoting: Item costs more than
$500.00")
Return Err
End If
Edit String
bginvert Boolean Invert background color of selected cell from this column.
inputformat String
colname String
locale String
<inputrow> Tag
The <inputrow> tag defines the input row, has no attributes, and contains <td> tags.
has attribute visible.
<tr> Tag
The <tr> tag defines a row. Contains <td>, <tr>, and <userdata> tags.
<td> Tag
The <td> tag defines the cell.
Type Comments
Attribute
link String
ftd String
css String
<userdata> Tag
The <userdata> tag defines user data for the row.
<list> Tag
The <list> tag defines a list and contains <listitem> tags.
<listitem> Tag
The <listitem> tag defines the item for the list.
show String The identifier of visible toolbar. If this parameter is absent, first
menubar from list is visible.
<menubar> Tag
The <menubar> tag contains <item>, <checkitem>, and <separator> tags.
id String
<item> Tag
The <item> tag defines a menu item.
<checkitem> Tag
The <checkitem> tag defines a toggle button menu item.
<seperator> Tag
The <seperator> tag defines a separator for the menu.
Technique
Use Item.setAttribute("language","*") to get all language values and
Item.setProperty(myProperty,value,lang) to set specific language values.
JavaScript
var inn = this.getInnovator();
VB.Net
Dim inn As Innovator = Me.getInnovator()
If (resultItem.isError()) Then
Return inn.newError("Error adding List: " + resultItem.getErrorDetail())
End If
' Retrieve the List with labels In both English And German
listItem = Me.newItem("List","get")
listItem.setProperty("name","Numbers")
valueItem = listItem.createRelationship("Value","get")
valueItem.setAttribute("language","en,de")
resultItem = listItem.apply()
If (resultItem.isError()) Then
Return inn.newError("Error retrieving List: " + resultItem.getErrorDetail())
End If
Return inn.newResult("ok")
Technique
Convert date values to "yyyy-MM-ddThh:mm:ss" format before setting the property
JavaScript
// Get yesterday's date
var myDate = new Date();
myDate.setDate(myDate.getDate()-1);
function dateFormat(d) {
var dateString = d.getFullYear()+"-";
dateString += pad(d.getMonth()+1)+"-";
dateString += pad(d.getDate())+"T";
dateString += pad(d.getHours())+":";
dateString += pad(d.getMinutes())+":";
dateString += pad(d.getSeconds());
return dateString;
}
function pad(x) {
return (x<10) ? "0"+x : ""+x;
}
VB.Net
' Get yesterday's date
Dim myDate As Date = Now.AddDays(-1)
' Loop through the returned methods and return the list
Dim methodList As String = ""
Dim i As Integer = 0
For i = 0 To myItem.getItemCount() - 1
methodList += myItem.getItemByIndex(i).getProperty("name","") + ", "
Next i
Technique
Use the built in function to add a variable, read a variable and remove a variable from the RequestState.
This sample determines if there was a change made to the “Name” property of Part.
C#
OnBeforeUpdate event
//Get Part Name before change
OnAfterUpdate event
string prevName = (string)RequestState["prevName"];
if (prevName != curName)
{
//Do some logic here
}
Technique
Create a custom DLL that references the IOM. This DLL is then added to the BIN folder and referenced
in the method-config.xml, allowing it to be called from a server side method.
Class Code
namespace CookBookCustomDLL
{
public class CustomDLLFunct
{
public static string returnUser(Innovator inn)
{
string userID = inn.getUserID();
return userID;
}
}
}
<name>System.Configuration.dll</name>
<name>$(binpath)/IOM.dll</name>
<name>$(binpath)/InnovatorCore.dll</name>
<name>$(binpath)/CoreCS.dll</name>
<name>$(binpath)/SPConnector.dll</name>
<name>$(binpath)/ConversionManager.dll</name>
<name>$(binpath)/CookBookCustomDLL.dll</name>
...
3. Search for the <Template> tag for the language you are using and include the additional
namespace you need by adding additional "using" lines.
a. When adding lines, ensure you update the line_number_offset for accurate debugging
messages.
<Template name="CSharp" line_number_offset="41">
<![CDATA[
using System;
…
using CookBookCustomDLL;
4. Save the Method-Config.xml
Assembly Redirection
If your custom DLL references the current version of the IOM, and you upgrade Aras Innovator to a newer
version, your function fills to execute due to an assembly mismatch on the IOM. A quick workaround until
the DLL can be rebuilt referencing the latest IOM is to add an assembly redirect.
To add an assembly redirect, you need to add the following into the <configuration> section of the
\Innovator\Server\web.config file.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="IOM"
publicKeyToken="524d880b05474146"
culture="neutral" />
<bindingRedirect oldVersion="9.4.0.5804" newVersion="9.4.0.5815" />
</dependentAssembly>
</assemblyBinding>
</runtime>
The oldVersion, highlighted in yellow above, is the original version of the IOM.dll referenced by the
custom DLL. The newVersion, highlighted in red text above, is the version of the IOM.dll that is located in
the upgraded instance of Aras Innovator.
Example #1
var menu = grid.getMenu();
menu.add("item_0", "Item 0");
menu.add("item_0.0", "Item 0.0", "item_0", { onClick: function () { alert(0);
} });
menu.add("item_0.1", "Item 0.1", "item_0", { onClick: function () { alert(1);
} });
menu.add("item_0.2", "Item 0.2", "item_0", { onClick: function () { alert(2);
} });
Example #2
var menu = grid.getMenu(),
subMenus = [
{
id: "item_0.0",
name: "Item 0.0",
onClick: function () { alert(0); }
},
{
id: "item_0.1",
name: "Item 0.1",
onClick: function () { alert(1); }
},
{
id: "item_0.2",
name: "Item 0.2",
onClick: function () { alert(2); }
}
];
menu.add("item_0", "Item 0");
menu.addRange(subMenus, "item_0");
selectbox.component.setState({list: options});
if (options[i].value == val) {
options.splice(i, 1)
break;
selectbox.component.setState({
list: options
});
aras.downloadFile(item.node, 'sample.txt');
...
let nodeValue = ArasModules.xml.getText(xmlNode);
...
if (error.errorCode !== 0) {
return aras.getResource('', 'tz.parse_update_fail_details',
error.reason);
}
...
8.1 Features
The Solution Studio offers several useful features to help aid you in the development of your Methods.
A robust text editor with search/replace and undo/redo capabilities.
Color coding the keywords for the language you are developing in.
An IOM API code guide.
An online help interface that is context sensitive for the methods selected in the code guide.
Syntax checking based on the language you are developing in.
Undo/Redo
Syntax checker
Search/Replace
Figure 10.
9 Debugging
Aras Innovator has the following features for debugging/logging your Methods:
Visual Studio to debug Methods either client or server.
Logging of debug messages to an XML formatted log file.
Server method debugging can then be disabled again by changing the value of this line to false.
After changing this value, you should restart IIS to confirm the change is applied.
Figure 11.
Figure 12.
4. Choose Debug --> Exceptions to force the method into the debugger when an exception occurs
and choose the check boxes "Thrown".
Figure 13.
5. Optionally, you can include the line System.Diagnostics.Debugger.Break() to force a
breakpoint at a specific line in your method.
Figure 14.
4. Select the Advanced tab and make sure the "Disable Script Debugging" is turned off and
"Display notification about script errors" is turned on.
Figure 15.
5. In Internet Explorer, key in your Aras Innovator URL (Do not log in yet).
6. Open Visual Studio.
7. In the menu, select "Debug" and "Attach to Process".
8. Find the "iexpore.exe" process with the "Title" that matches your Aras Innovator instance.
Figure 16.
In order to write messages to the C:/TEMP/DEBUG-* log file, add the following lines of code to the server
side method:
Dim sc as Object = Me.serverConnection
sc.cco.startup.debuglog("Unique string to identify message in log file",
"Actual message written to log file")
10 External APIs
There are a few ways to connect to the Aras Innovator server from other applications. Aras provides
three assemblies (.NET, COM-compatible, and RT) that implement the IOM API and can be used by other
applications. Alternatively, simple SOAP communication can be used to connect to Aras Innovator.
Note: You can pass either encrypted (if required, use static method Innovator.ScalcMD5(string
pwd) for encryption) or non-encrypted password (as shown in the previous example) to the
method IomFactory.CreateHttpServerConnection(…). If you pass a non-encrypted
password it’ll be encrypted inside the method. Otherwise the password is passed to the server
without modifications.
It’s highly recommended to logout of Aras Innovator prior to exiting the application:
…
conn.Logout();
…
If the assembly was successfully registered it must appear in the list of available COM references
as “Aras API”.
3. Add the reference to your project. Similar to .NET you must first create a connection, login and
then create an Innovator object.
Here is the sample code in VBA:
…
Dim url As String: url =
"http://myserver/MyInnovator/Server/InnovatorServer.aspx"
Dim db As String: db = "MyDB"
Dim user As String: user = "admin"
Dim password As String: password = "innovator"
10.3 RT IOM
You will find an RT version of IOM.RT.dll in the \Utilities\Aras Innovator <Version>
IOM SDK\COM\RT directory on the CD Image. You can copy it to another location to
reference it by Windows App Store project. IOM APIs belong to Aras.IOM namespace. First,
every application must create a connection with the Aras Innovator server and login to the
server using the connection. If the login succeeds then you must create an instance of class
Innovator with the connection. Here is a small sample:
…
using Aras.IOM;
…
//create connection to Innovator server
…
//create connection to Innovator server
string server = "http://localhost/InnovatorServer";
string db = "InnovatorSolutions";
string username = "admin";
string password = "innovator";
HttpServerConnection connection =
IomFactory.CreateHttpServerConnection(server, db, username, password);
//login
Item user = await connection.LoginAsync();
if (user.isError())
{
throw new Exception(user.getErrorString());
}
11 Using CheckinManager
The CheckInManager is a function built into the IOM.dll which allows for the loading of large data
structures into Aras Innovator that contain Images, Drawings, Documents, or other Items of the File
Itemtype.
The following use cases describe how to use CheckInManager to submit images and drawings, either
individually or as a collection.
In this scenario, the setFileProperty method is required in order to add a property whose type is File. The
parameters of setFileProperty include the Property’s name and the fully qualified path of the File.
If you need to use the CheckinManager to load an Image Property, you must set the Attribute
checkinManager-type on the Property (such as in the thumbnail, below) to “Image”. The following
example shows the AML for the query:
If you are only importing one Item, you can then pass the Item directly to the CheckinManager. The
following example uses cad0 from the previous scenario:
You can also use this code to import more than one item. For example, given two CAD Items, referenced
as cad0 and cad1 in the following example, you can generate 1 AML that contains both Items, as
demonstrated here:
The following is the AML code which would result from the loadAML statement:
The following code can then be used to apply the query contained in the configuration value:
You must make sure you observe the following requirements in order for the query to work correctly:
You must have at least one File or Image property otherwise CheckinManager will throw an
exception.
The Item passed to CreateCheckinManager cannot be null.
A File item must have either an Add or a Create action associated with it.
CAD items only support the following actions:
o Add
o Update
o Delete
o Version
o Skip
Specifying any other type of action results in an exception being thrown.
MultiParentConfigurationBuilder builder =
factory.CreateMultiParentConfigurationBuilder(configuration);
The following is the AML for the cadA Item from the example:
The following shows the AML code for the drawingA Item:
The addParent function creates a link between these two structures that generates the complete
structure, as shown in the final CAD structure shown below:
</Relationships>
</Item>
<Item isNew="1" isTemp="1" type="CAD" action="add" id="E5F643DCC71A4740AC29189B064C9AC6">
<item_number>5FE746744D8C433281F32C9588F2D64B</item_number>
<native_file>
<Item isNew="1" isTemp="1" type="File" action="add" id="8C4C44D934B14CE0A8779008F4395F89">
<filename>native-C.cad</filename>
<actual_filename>C:\Sandbox\pbellis\checkinmanagerexamples\CompilableCode\examples\submitting-
drawings\bin\Debug\input\native-C.cad</actual_filename>
<checkedout_path>C:\Sandbox\pbellis\checkinmanagerexamples\CompilableCode\examples\submitting-
drawings\bin\Debug\input</checkedout_path>
<Relationships>
<Item type="Located" action="add" where="related_id='67BBB9204FE84A8981ED8313049BA06C'">
<related_id>67BBB9204FE84A8981ED8313049BA06C</related_id>
</Item>
</Relationships>
</Item>
</native_file>
<name>submitting-drawings-drawingC</name>
<Relationships>
<Item isNew="1" isTemp="1" type="CAD Structure" action="add">
<related_id>B236FBFD63CA4BD89AEF8A443E5942FE</related_id>
</Item>
</Relationships>
</Item>
</AML>
In this case, cadA is equal to configuration. The last line of code creates a CAD Structure relationship
between drawingA and cadA. The example repeats similar logic for cadB and cadC. The following code
then applies the query:
// …
The first line converts the Builder’s query into a query that supports multiple parents as determined by the
calls to builder.addParent. After the first line of code, query execution is applied in the same way as a
standard CheckInManager query.
Using the Dispose pattern as the main thread continues execution and disposes of the
CheckInManager will cause a NullReferenceException.
Retrieving the results from the CheckinManager requires a callback for either
UploadFilesCompleted or CheckinCompleted. UploadFilesCompleted loops through all the
files and writes out which files have been added. If an error is encountered, an exception is thrown.
CheckInCompleted stores a list of all the results.
In CheckinCompleted, you must dispose of the CheckInManager to prevent a resource leak