As OData becomes richer, individual services may support a range of capabilities beyond a core basis of OData functionality. Even within V1 functionality different services may support different sets of functionality, for example updatability. Generic consumers that want to adapt based on service capabilities require a dynamic way of determining those capabilities.

What follows is a proposed Capabilities Vocabulary that aims to provide a way for service authors to describe certain capabilities of an OData Service. We'd love to get your feedback!

-Mike Pizzo

Design Principles

There are many trade-offs that go into defining a vocabulary to describe capabilities of a system at varying levels. The following principles were factored in to the design of this vocabulary.

Keep it as simple as possible

This vocabulary aims to enable expression of most general capabilities without diving into complicated cases. The expectation is that an extension to this vocabulary can be designed to cover more complicated cases.

Reasonable defaults

Annotations are generally extensions to an OData service. Clients consuming an OData service should be able to continue to consume a service regardless of existence of capabilities annotations. However, existence of these annotations enable clients to understand more about the certain capabilities of a service.

There are some capabilities which are strongly recommended for services to support even though they are optional. Support for $top and $skip is a good example as supporting these query options helps with performance of a service and are essential. Such capabilities are assumed to be default capabilities of an OData service even in the case that a capabilities annotation doesn't exist. Capabilities annotations are mainly expected to be used to explicitly specify that a service doesn't support such capabilities. Capabilities annotations can as well be used to declaratively specify the support of such capabilities.

On the other hand, there are some capabilities that may not be appropriate for a given service (such as updatability), that a particular service many not reasonably be capable of supporting, or that a service may only be capable of supporting in varying degrees. $filter and $orderby may be such examples. This vocabulary aims to define terms to specify support or no support for such capabilities.

In the absence of an annotation, a service is assumed to support the following capabilities:

  • Countability ($count, $inlinecount)
  • Client pageability ($top, $skip)
  • Expandability ($expand)
  • Indexability by key
  • Batch support ($batch)
  • Navigability of navigation properties

A service is expected to use the following annotations if any of the relevant restrictions apply:

  • Filterability ($filter)
  • Sortability ($orderby)
  • Queryability of top level entity sets
  • Query functions

In the absence of an annotation, the client cannot assume that a service supports the following capabilities.

  • Insertability
  • Updatability
  • Deletability

Assumed defaults notwithstanding, a client should always be prepared for services to fail to support any optional capabilities.

Namespace

The namespace of this version of the vocabulary is Org.OData.Capabilities.V1

Terms

InsertRestrictions

<ValueTerm Name="InsertRestrictions" Type="Self.InsertRestrictionsType" />
<ComplexType Name="InsertRestrictionsType">
<Property Name="Insertable" Type="Edm.Boolean" />
<Property Name="NonInsertableProperties" Type="Collection(Edm.String)" />
<Property Name="NonInsertableNavigationProperties" Type="Collection(Edm.String)" />
</ComplexType>

Used to express whether Insert operations are supported for an applicable target.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on an applicable target, it means that insertability of that target is unknown.

Target Properties Meaning
EntitySet Insertable If "true", the targeted EntitySet is insertable.If "false", the targeted EntitySet is not insertable.
NonInsertableProperties These properties SHOULD be omitted from POST requests because the server will ignore their values.
NonInsertableNavigationProperties These navigation properties do not allow InsertLink requests.

UpdateRestrictions

<ValueTerm Name="UpdateRestrictions" Type="Self.UpdateRestrictionsType" />
<ComplexType Name="UpdateRestrictionsType">
<Property Name="Updatable" Type="Edm.Boolean" />
<Property Name="NonUpdatableProperties" Type="Collection(Edm.String)" />
<Property Name="NonUpdatableNavigationProperties" Type="Collection(Edm.String)" />
</ComplexType>

Used to express whether Update operations are supported for an applicable target.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on applicable target, it means that updatability of that target is unknown.

Target Properties Meaning
EntitySet Updatable If "true", the targeted EntitySet is updatable.If "false", the targeted EntitySet is not updatable.
NonUpdatableProperties These properties SHOULD be omitted from PUT or PATCH requests because the server will ignore their values.These properties do not allow UpdateValue and DeleteValue requests.
NonUpdatableNavigationProperties These navigation properties do not allow UpdateLink requests.

DeleteRestrictions

<ValueTerm Name="DeleteRestrictions" Type="Self. DeleteRestrictionsType" />
<ComplexType Name="DeleteRestrictionsType">
<Property Name="Deletable" Type="Edm.Boolean" />
<Property Name="NonDeletableNavigationProperties" Type="Collection(Edm.String)" />
</ComplexType>

Used to express whether Delete operations are supported for an applicable target.

Applicable Targets: EntitySet

If the term doesn't exist on applicable target, it means that deletability of that target is unknown.

Target Properties Meaning
EntitySet Deletable If "true", the targeted EntitySet is deletable.If "false", the targeted EntitySet is not deletable.
NonDeletableNavigationProperties These navigation properties do not allow DeleteLink requests.

Countable

<ValueTerm Name="Countable" Type="Edm.Boolean" />

Used to express whether $count and $inlinecount operations are supported for an applicable target.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on applicable target, it means that countability of that target is supported. 

Value
Meaning

True [Default Value]
$count and $inlinecount is supported for the targeted EntitySet.

$count and $inlinecount is not supported for the targeted EntitySet.

Target
EntitySet False

 

 

Queryable

<ValueTerm Name="Queryable" Type="Edm.Boolean" /> Used to express whether a set is directly queryable as a top level set. Applicable Targets: EntitySet Default Capability: If the term doesn't exist on an applicable target, it means that the queryability of the target is supported.

Value
Meaning

True [Default Value]
The targeted EntitySet can be directly be queried as a top level set.

The targeted EntitySet cannot be directly queried as a top level set. Members are accessed only through relationships or functions

Target
EntitySet False

 

 

ClientPageable

 

<ValueTerm Name="ClientPageable" Type="Edm.Boolean" />

Used to express whether $top and $skip operations are supported for a navigation property or not.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on an applicable target, it means that $top and $skip operations are supported.

Target Value Meaning
EntitySet True [Default Value] $top and $skip operations are supported for the targeted EntitySet.
False $top and $skip operations are not supported for the targeted EntitySet. If a service doesn't support both $top and $skip, it must specify a value of false.

Expandable

<ValueTerm Name="Expandable" Type="Edm.Boolean" />

Used to express whether $expand operation is supported for a navigation property or not.

Applicable Targets: Navigation Property

Default Capability: If the term doesn't exist on an applicable target, it means that $expand is supported.

Target Value Meaning
Navigation Property True [Default Value] $expand operation is supported for the targeted EntitySet.
False $expand operation is not supported for the targeted EntitySet.

Navigable

<ValueTerm Name="Navigable" Type="Edm.Boolean" />

Used to express whether a navigation property can be part of the resource path in a query expression.

Applicable Targets: Navigation Property

Default Capability: If the term doesn't exist on an applicable target, it means that the navigation property is navigable in a query expression.

Target Value Meaning
Navigation Property True [Default Value] Navigation property can be navigated in a query expression.
False Navigation property cannot be navigated in a query expression.

IndexableByKey

<ValueTerm Name="IndexableByKey" Type="Edm.Boolean" />

Used to express whether entities within an entity set can be indexed by key value(s) according to OData URL convention.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on an applicable target, it means that indexing by key is supported.

Target Value Meaning
EntitySet True [Default Value] Indexing by key is supported within the target EntitySet
False Indexing by key is not supported within the target EntitySet

SupportsBatch

<ValueTerm Name="SupportsBatch" Type="Edm.Boolean" />

Used to express whether an EntityContainer supports batch operations.

Applicable Targets: EntityContainer

Default Capability: If the term doesn't exist on an applicable target, it means that $batch is supported.

Target Value Meaning
EntityContainer True [Default Value] $batch is supported for the target EntityContainer
False $batch is not supported for the target EntityContainer

QueryFunctions

<ValueTerm Name="QueryFunctions" Type="Collection(Edm.String)" />

Used to express the list of supported query function names.

Applicable Targets: EntityContainer

Default Capability: If the term doesn't exist on the applicable target, functions that the service supports are unknown.

Target Value Meaning
EntityContainer List of query function names (e.g. length, day, double, isOf) Listed query functions are supported by the service.

If a certain function name is listed in the annotation, it is expected that any property of the type that is filterable on an entity set can be used as the function's parameter.

 

FilterRestrictions

<ValueTerm Name="FilterRestrictions" Type="Self.FilterRestrictionsType" />
<ComplexType Name="FilterRestrictionsType">
<Property Name="Filterable" Type="Edm.Boolean" />
<Property Name="RequiredProperties" Type="Collection(Edm.String)" />
<Property Name="NonFilterableProperties" Type="Collection(Edm.String)" />
</ComplexType>

Used to express restrictions on $filter support of a service.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on an EntitySet, it means that $filter is supported on that EntitySet.

Target Properties Meaning
EntitySet Filterable If "true", $filter is supported. If "false" $filter is not supported on any properties. Default value for this property is true.
RequiredProperties This collection of property paths must be specified in the $filter clause when enumerating the set. (Properties of derived types are not supported).
NonFilterableProperties This collection of property paths cannot be specified in the $filter clause.If the last path segment is a navigation property, all properties related via that navigation property cannot be specified.

It is possible to specify various capabilities by annotating with this term and picking values for the parameters. The table below shows some examples.

Annotation Meaning

<ValueAnnotation Term="C.FilterRestrictions">
<Record>
<PropertyValue Name="Filterable" Boolean="False" />
</Record>
</ValueAnnotation>
The EntitySet is not filterable.

<ValueAnnotation Term="C.FilterRestrictions">
<Record>


<PropertyValue Name="Filterable" Boolean="True" />
</Record>


</ValueAnnotation>
The entity set is filterable and all properties of all types can be used in $filter expression. This is the same as not including an annotation.

<ValueAnnotation Term="C.FilterRestrictions">
<Record>
<PropertyValue Name="RequiredProperties">
<Collection>
<String>Prop1</String>
<String>Prop2</String>
</Collection>


</PropertyValue>


</Record>


</ValueAnnotation>
The entity set is filterable and Prop1 and Prop2 of the type must be used in the $filter expression

<ValueAnnotation Term="C.FilterRestrictions">
<Record>
<PropertyValue Name="NonFilterableProperties">
<Collection>
<String>Prop3</String>
<String>Prop4</String>
<String>NavProp5/Prop6</String>
<String>NavProp7</String>
</Collection>
</PropertyValue>
</Record>
</ValueAnnotation>
The entity set is filterable but Prop3 and Prop4 of the type cannot be used in the $filter expression, as well as Prop6 of the type related via NavProp5 and all properties of the type related via NavProp7. All other properties can be used.

<ValueAnnotation Term="C.FilterRestrictions">
<Record>
<PropertyValue Name="RequiredProperties">
<Collection>
<String>Prop1</String>
<String>Prop2</String>
</Collection>
</PropertyValue>


<PropertyValue Name="NonFilterableProperties">
<Collection>
<String>Prop3</String>
<String>Prop4</String>
</Collection>
</PropertyValue>
</Record>
</ValueAnnotation>
The entity set is filterable and Prop1 and Prop2 properties of the type must be used in the $filter. However, Prop3 and Prop4 of the type cannot be used in a $filter expression.

SortRestrictions

<ValueTerm Name="SortRestrictions" Type="Self.SortRestrictionsType" />
<ComplexType Name="SortRestrictionsType">
<Property Name="Sortable" Type="Edm.Boolean" />
<Property Name="AscendingOnlyProperties" Type="Collection(Edm.String)" />
<Property Name="DescendingOnlyProperties" Type="Collection(Edm.String)" />
<Property Name="UnsortableProperties" Type="Collection(Edm.String)" />
</ComplexType>

Used to express restrictions on sortability of an EntitySet.

Applicable Targets: EntitySet

Default Capability: If the term doesn't exist on an EntitySet, it means that EntitySet is sortable in both directions on all properties.

Target Properties Meaning
EntitySet Sortable If "true", $orderby is supported. If "false" $orderby is not supported on any properties of the EntitySet. Default value for this property is true.
AscendingOnlyProperties Properties specified in this collection can only be used for sorting in Ascending order
DescendingOnlyProperties Properties specified in this collection can only be used for sorting in Descending order
UnsortableProperties Properties specified in this collection cannot be used for sorting

Various restrictions can be specified using the combination of term's properties similar to FilterRestrictions.

Formal CSDL Definition

<Schema Namespace="Org.OData.Capabilities.V1" xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Alias="Self">

<ValueTerm Name="InsertRestrictions" Type="Self.InsertRestrictionsType" />

<ValueTerm Name="UpdateRestrictions" Type="Self.UpdateRestrictionsType" />

<ValueTerm Name="DeleteRestrictions" Type="Self.DeleteRestrictionsType" />

<ValueTerm Name="Countable" Type="Edm.Boolean" />

<ValueTerm Name="Queryable" Type="Edm.Boolean" />

<ValueTerm Name="ClientPageable" Type="Edm.Boolean" />

<ValueTerm Name="Expandable" Type="Edm.Boolean" />

<ValueTerm Name="Navigable" Type="Edm.Boolean" />

<ValueTerm Name="IndexableByKey" Type="Edm.Boolean" />

<ValueTerm Name="SupportsBatch" Type="Edm.Boolean" />

<ValueTerm Name="QueryFunctions" Type="Collection(Edm.String)" />

<ValueTerm Name="FilterRestrictions" Type="Self.FilterRestrictionsType" />

<ValueTerm Name="SortRestrictions" Type="Self.SortRestrictionsType" />

<ComplexType Name="InsertRestrictionsType">
<Property Name="Insertable" Type="Edm.Boolean" />
<Property Name="NonInsertableProperties" Type="Collection(Edm.String)" />
<Property Name="NonInsertableNavigationProperties" Type="Collection(Edm.String)" />
</ComplexType>

<ComplexType Name="UpdateRestrictionsType">
<Property Name="Updatable" Type="Edm.Boolean" />
<Property Name="NonUpdatableProperties" Type="Collection(Edm.String)" />
<Property Name="NonUpdatableNavigationProperties" Type="Collection(Edm.String)" />
</ComplexType>

<ComplexType Name="DeleteRestrictionsType">
<Property Name="Deletable" Type="Edm.Boolean" />
<Property Name="NonDeletableNavigationProperties" Type="Collection(Edm.String)" />
</ComplexType>

<ComplexType Name="FilterRestrictionsType">
<Property Name="Filterable" Type="Edm.Boolean" />
<Property Name="RequiredProperties" Type="Collection(Edm.String)" />
<Property Name="NonFilterableProperties" Type="Collection(Edm.String)" />
</ComplexType>

<ComplexType Name="SortRestrictionsType">
<Property Name="Sortable" Type="Edm.Boolean" />
<Property Name="AscendingOnlyProperties" Type="Collection(Edm.String)" />
<Property Name="DescendingOnlyProperties" Type="Collection(Edm.String)" />
<Property Name="UnsortableProperties" Type="Collection(Edm.String)" />
</ComplexType>
</Schema>