Configuring Bound Actions
The framework supports configuring actions that are bound to entities. An action bound to an entity is invoked on an instance of the entity. OData protocol considers a bound action to be an operation that changes the state of an entity instance on which it is invoked. After the bound action is configured, it is invoked by a POST request to the URL:
<Domain Root>/<Entity Set>(<key>)/<Domain Namespace>.<Bound Action Name>
The body of the POST request contains the parameters that must be passed to the action.
A bound action is configured in the same way as an unbound action, except for the following differences:
name—Name of the bound action, defined in camel case.
description—Short description of the action. The value is displayed as an annotation (“Core.Description”) in the EDM.
isReadOnlyAction—Specifies that the action is read-only and does not change the state of the service. Default is false. For more information see Read-only Actions.
isPageable—Specifies that the action supports paging. Default is false. When set to true, the action must be read-only. If set to true, clients must pass the PTC-EnablePagination header to get the results paged. For more information, see Paging on Actions.
parameters—JSON array specifying the list of parameters for the bound action. Each parameter has the following configuration options:
name—Name of the parameter in camel case.
type—OData type of the parameter. It can be an OData primitive, complex type, or entity.
isNullable—Specifies whether the parameter can be omitted in the request.
isCollection—Specifies whether the parameter takes one (false) or multiple (true) values.
 
TThe bound action must have at least one non-null parameter for the entity it is bound to. If there are more than one parameter, then the first parameter is the binding entity and is non-nullable. For example, a bound action on ChangeRequest, will always have at least the following parameter:
{
"name":"TheBindingParameterForTheAction",
"type":"ChangeRequest",
"isNullable":false
}
returnType—OData type returned by the Action. Specify the following properties for the return types:
type—Type of object that is returned. The return type can be a primitive or an entity type.
isNullable—OData type returned by the action. Can be an OData primitive, complex type, or entity.
isCollection—Specifies whether the action returns one (false) or multiple (true) values.
Consider this information for configuring bound actions:
A bound action is specified in the actions collection property in the <Entity JSON> file.
When the action is specified in the <Entity JSON> file, the property includeInServiceDocument is not applicable to bound actions. This is because bound actions cannot be included in the service document available at the domain root.
The first parameter in the action specification is called the binding parameter. The parameter must be of the same type as the entity that is bound to the action. This is a required parameter.
The action names defined in the <ENTITY>.js start with action_.
Paging on Actions
The configuration property isPageable is used to configure an action as pageable. When it is set to true, the action supports paging. The action is rerun, and the result is navigated to the requested page. This configuration option should be used only for the actions that can be safely rerun (that is, the action does not modify data) and return a flat list. The default is false. Refer to the following example for GetMultiLevelComponentsReport:
Example
"actions":
{
"name": "GetMultiLevelComponentsReport",
"description": "Returns same results as PartStructure's Reports for Multi-Level Components List and Single-Level Consolidated BOM, using Navigation criteria passed in navigationCriteria in the body.",
"isPageable": true,
"isReadOnlyAction":true,
"parameters": [
{
"name": "Part",
"type": "Part",
"isNullable": false,
"isCollection": false
},
{
"name": "NavigationCriteria",
"type": "PTC.NavCriteria.NavigationCriteria",
"isNullable": true,
"isCollection": false
},
{
"name": "ShowSingleLevelReport",
"type": "Boolean",
"isNullable": true,
"isCollection": false,
"description": "Parameter determines if the action returns Multi-Level Components List if set to false or a Single Level Consolidated BOM when set to true. The default value is false if the parameter value is not provided." }
],
"returnType": {
"type": "PartsReportListItem",
"isCollection": true,
"isNullable": true
}
}

A new request header type Boolean PTC-EnablePagination is introduced. When the header is set to true, the response returned to the client is paginated.
For actions marked as pageable, the action is rerun, and the result is navigated to the requested page.
URI
POST / Windchill/servlet/odata/BACMgmt/Preview HTTP/1.1
Request Header
Make a request with a new request header PTC-EnablePagination set to true. The result returned to the client will be paginated, as specified in the odata.maxpagesize Prefer header. The new request header PTC-EnablePagination by default is set to false to avoid breaking existing clients.
Content-Type: application/json
CSRF_NONCE:<Use the value from Fetch NONCE example>
Prefer: odata.maxpagesize=1000
PTC-EnablePagination: true
Request Body
{
"types": [
"Preference"
],
"startDate": "2022-09-01T00:00:00.000Z",
"endDate": "2022-09-14T00:00:00.000Z"
}
Response
{
"@odata.context": "http://<host>:<port>/Windchill/servlet/odata/BACMgmt/$metadata#Collection(PTC.BACMgmt.Delta)",
"@PTC.AppliedContainerContext.LocalTimeZone": "GMT",
"value": [
{
"oid": "wt.preference.PreferenceInstance:262931",
"type": "Preference",
"localizedType": "Preference",
"context": "Site",
"name": "Default cache vault created",
"description": null,
"details": [
{
"key": "Value",
"value": "true"
},
{
"key": "Locked",
"value": "true"
},
{
"key": "Client",
"value": "Windchill"
}
],
"modifiedDate": "2022-09-12T14:46:40Z",
"localizedModifiedDate": "2022-09-12 14:46:40 GMT",
"modifiedBy": null,
"action": "Create"
},
{
"oid": "wt.preference.PreferenceCategoryDefinition:115478",
"type": "Preference",
"localizedType": "Preference",
"context": null,
"name": "Link [Include related Parts - Collector]",
"description": null,
"details": [
{
"key": "Object Type",
"value": "Link [Defintion - Category]"
},
{
"key": "Internal Name",
"value": "Link [MANAGED_COLLECTION_COLLECTOR_CATEGORY.AddToManagedCollection.ASSOCIATED_WTPART.default.option.id - MANAGED_COLLECTION_COLLECTOR_CATEGORY]"
}
],
"modifiedDate": "2022-09-12T14:37:29Z",
"localizedModifiedDate": "2022-09-12 14:37:29 GMT",
"modifiedBy": null,
"action": "Create"
}
],
"@odata.nextLink": "http://<host>:<port>/Windchill/servlet/odata/BACMgmt/Preview?$count=true&$skiptoken=1000"
}
Read-only Actions
Read-only actions are actions that do not change the state of the service and, therefore, do not have any side effects. Typically, read-only actions are implemented as functions, but they require parameters to be passed in the request body (as opposed to the URL parameters).
For example PTC.ProdMgmt.GetPartStructure is a read-only action, and PTC.ProdMgmt.UpdateParts is not read-only action.
A new Boolean JSON configuration element isReadOnlyAction is introduced for actions. If this element is not specified, then the default will be false, as the OData specification assumes that actions may have side effects (https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_Actions).
When this flag is set, the framework treats the request similar to a GET request.
This typically improves performances for read-only actions in CADDocumentMgmt, EffectivityMgmt, and ProdPlatformMgmt domains.
 
Actions that create/update/delete data MUST NOT be flagged as read-only.