Understand OData Services in Windows Azure Pack

 

Applies To: Windows Azure Pack

This topic provides basic information about what OData is and how it works with the IaaS service of Windows Azure Pack. The IaaS OData service is offered by Service Provider Foundation through the Service Management API.

  • OData Introduction

  • URL placeholders

  • The service URL format for collections and entities

  • Identify an entity through the URL

  • Common GET HTTP Info

  • Common HTTP request information

  • Common HTTP response information

  • Entity Basics

  • Updating Entities

  • Complex Types

  • OData Operations

OData Introduction

You can think of the OData service as a database exposed through an HTTP REST interface. When you work with a database you are working with records in a table. You perform one of four operations on the records: create, read, update, or delete. These operations are known as CRUD operations. OData shares this same concept of record manipulation.

An OData service has three basic components, entities (data model types), entity sets (collections), and OData operations. A collection (like a database table) contains instances (like database records) of a specific entity type. Entity types are data structures that are used by collections and have key properties whose values uniquely identify one instance from another. OData operations (like database stored procedures) are pieces of custom logic that you can call. For more information about basic OData concepts, see the OData documentation.

URL placeholders

This programming guide provides URLs that need information about your infrastructure, such as server names or names of objects that have been previously created. The following list describes all of the placeholders used in these URLs.

Placeholder name

Description

{server-name}

The Service Management API server hosting the services.

{auth-port}

The authentication port used when connecting to the service.

{subscription-id}

The tenant subscription GUID you are currently working with.

{collection-name}

The name of an OData collection.

{entity-identifier}

An identifier that points to a specific entity. Such as an index or a single key property. For more information about how to identify an entity, see OData URL Conventions

{entity-uri}

A URI that identifies an entity instance. Generally this will include {collection-name}/{entity-identifier}. But it could be a query hanging off of a collection that identifies a single entity or a link from one entity to the target entity.

{key-property-name}

A key property from an entity type.

The service URL format for collections and entities

The URL is used to identify the resources of the service, such as a collection or an entity instance. Create (POST) works with a collection resource, while the update (PUT) and delete (DELETE) operations work with the entity resources offered by a collection. Read (GET) operations can generally work with a collection and an entity. However, the collection defines what you can and cannot do with the backing entities. Some collections may let you only read instances, but never create, update, nor delete them. The following list defines the URL format of each operation as it relates to either a collection or an entity.

  • The service root returns you a list of all collections (GET)
    https://{server-name}:{auth-port}/{subscription-id}/services/systemcenter/vmm

  • Read multiple entity instances or create a single entity instance of a collection (GET/POST)
    https://{server-name}:{auth-port}/{subscription-id}/services/systemcenter/vmm/{collection-name}

  • Read, update, or delete a single entity instance of a collection (GET/PUT/DELETE)
    https://{server-name}:{auth-port}/{subscription-id}/services/systemcenter/vmm/{collection-name}/{entity-identifier}

    - or -

    https://{server-name}:{auth-port}/{subscription-id}/services/systemcenter/vmm/{collection-name}({key-property-name}={value},{more-key-property-name-value-pairs})

For more information about how the URL of the service is formatted, see OData URL Conventions. To understand how the entity instance works with a collection, see Entity Basics.

Identify an entity through the URL

To identify a single entity resource, you can use a collection and then a composite identifier of all the key properties of the entity. For example, if you wanted to identify a Job entity through the Jobs collection, you would provide the ID and StampId properties (both being key properties) on the URI: https://{server-name}:{auth-port}/{subscription-id}/services/systemcenter/vmm/Jobs(ID=guid'851d7da2-c9e0-4227-8290-2770dcbd10b9', StampId=guid'56ebc6dc-f63c-46e2-8438-2967e0ad83bc').

When working with a collection whose backing entity only has a single key property, you may be able to provide it as a URI segment directly instead of using the name-value notation as was used by the Jobs collection. Here is an example of the UserRole entity being identified (who only has a single key (GUID) property): https://{server-name}:{auth-port}/{subscription-id}/services/systemcenter/vmm/UserRoles/86e93b7f-25e3-4c44-8ca1-3ebdbd2dfc06

Another way of identifying a resource is by using the index of it in the collection. Regardless of how you identify an entity resource, once it is identified, you can work with it. For more information about how the URL of a resource is formatted, see OData URL Conventions.

Common GET HTTP Info

If a collection allows you to read entity instances, then you need to do is send a GET request to the collection URL. If it does not, then you can only identify entity resources directly. See the The service URL format for collections and entities and Identify an entity through the URL sections.

When you use a GET HTTP operation, you must send a request to the server without a body and with all the common authentication headers. The authentication headers depend on the type of authentication you are using designated by the port you use in the URL. For more information about authentication, see Windows Azure Pack Authentication Overview. Here is an example of a GET request that reads all Job entities from the Jobs collection.

GET https://contoso.com:30005/86e93b7f-25e3-4c44-8ca1-3ebdbd2dfc06/services/systemcenter/vmm/Jobs HTTP/1.1
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/json;odata=minimalmetadata
Accept-Charset: UTF-8
DataServiceUrlConventions: KeyAsSegment
User-Agent: Microsoft ADO.NET Data Services
Authorization: Bearer {REMOVED ENCODED STRING FOR BREVITY}
x-ms-principal-id: tenant@fabrikam.com
Host: contoso.com:30005

This is an example of a GET request for a specific Job entity.

GET https://contoso.com:30005/86e93b7f-25e3-4c44-8ca1-3ebdbd2dfc06/services/systemcenter/vmm/Jobs(ID=guid'851d7da2-c9e0-4227-8290-2770dcbd10b9',StampId=guid'56ebc6dc-f63c-46e2-8438-2967e0ad83bc') HTTP/1.1
DataServiceVersion: 1.0;NetFx
MaxDataServiceVersion: 3.0;NetFx
Accept: application/json;odata=minimalmetadata
Accept-Charset: UTF-8
DataServiceUrlConventions: KeyAsSegment
User-Agent: Microsoft ADO.NET Data Services
Authorization: Bearer {REMOVED ENCODED STRING FOR BREVITY}
x-ms-principal-id: tenant@fabrikam.com
Host: contoso.com:30005

Additional filtering is provided by the OData service. For more information about the query language OData provides, see the OData Version-3.0 Core Protocol documentation.

Common HTTP request information

The headers used in the HTTP request consist of authentication headers, and any standard OData and HTTP headers. These are detailed at the Common Request Headers section of the OData 3.0 Protocol documentation. Here is a list of some of the common request headers used by the service.

Header

Suggested Value

Description

DataServiceVersion

3.0

The minimal data service version used for the request. Service Provider Foundation uses OData version 3.0.

MaxDataServiceVersion

3.0

The maximum data service version used for the request. This really represents the version you’re requesting the server to work with. Service Provider Foundation uses OData version 3.0.

Accept

application/json

JSON should be the preferred format for returning data from an OData service. However, you want to receive the response in XML format, use the value

x-ms-principal-id

{tenant user id}

This header should be supplied with every call to the service as it identifies the tenant making the requests. The value should be the same as the tenant’s user id used when logging into the tenant portal.

Host

{server-name}:{auth-port}

The Service Management API server that the request was made to.

Authorization

{authentication token}

This header may or may not be required depending on the type of authentication the server requires. When using the tenant Service Management API port 30005, the value of this header would be a Bearer token provided by the authentication service. For more information, see Windows Azure Pack Authentication Overview

Content-Type

application/json

- or -

application/xml

When creating or updating an entity (with the POST or PUT operations) you must specify the type of payload used in the HTTP request body.

Content-Length

{bytes of data}

When creating or updating an entity (with the POST or PUT operations) you must specify the total bytes of the data being sent in the HTTP request body. You must provide this header when you use the Content-Type header.

Common HTTP response information

The headers used in the HTTP response consist of acknowledgement headers, and any standard OData and HTTP headers. These are detailed at the Common Request Headers section of the OData 3.0 Protocol documentation. You may not see all of these in your response. For example, if your response doesn’t contain any content in the body, the Content-* headers will not be provided in the response. Here is a list of some of the common response headers returned by the service.

Header

Value

Description

Content-Length

{bytes of data}

The total bytes of response body.

Content-Type

application/json

- or -

application/xml

The type of data in the response body. This corresponds to what you sent in the Accept header of the request. If the Accept header was omitted from the request, this generally defaults to application/xml.

request-id

{guid}

A GUID generated for the request sent to the server.

DataServiceVersion

3.0

The data services version the server is using. If the response contains a body, the data will conform to this specification.

x-ms-request-id

{guid}

The GUID of a Job instance. When you work with the service, for example when you shut down a virtual machine, a job will be created on the server that monitors the status of that action. The HTTP response will return this header item with the value set to the identifier of the job that was created.

Entity Basics

Entities are data types defined by the data model. They can define relationships to other entities or define OData Operations that you can call. When an entity is submitted by a create (POST) or an update (PUT) HTTP operation, some properties may not be used.

Every entity topic has a table of properties that describes what the property is for. The table also flags whether the property is required, optional, or ignored (which is denoted by a –) when you use a specific HTTP operation. In the example below, the ID property is not used in the create operation, but is required by the update and delete operations. However, it is optional for the read operation.

Name

Create (POST)

Read (GET)

Update (PUT)

Delete (DELETE)

Type

Nullable

Description

ID

-

Optional

Required

Required

Edm.Guid

False

Key Property

The identifier of the entity.

When you work with entities and the CRUD operations, you are working with the collection that is exposing the entity. Here are some common guidelines for each HTTP operation when working with entities. These are presented as if you were working with the UserRoles Collection and UserRole entity.

Updating Entities

Updating an entity is supported either through a replace or merge. Regardless of which way you update the entity, you always send a request to the URL identifying the single entity you want to update.

When you replace an entity, you send a request using the HTTP PUT operation. The body of the request is set to a single entity instance with all required and optional properties set to either their original or modified values.

When you merge an entity, you send a request using the HTTP MERGE or PATCH operation. The body of the quest is set to a single entity with only the properties you are changing along with their modified values.

If the programming library you are using to update the entity does not support the PATCH or MERGE operation, you can use HTTP verb tunneling. This is done by using the HTTP PUT operation along with the X-HTTP-Method header, setting the value of this header to either MERGE or PATCH. See Differential Update for more information about PATCH and MERGE.

Complex Types

Put simply, complex types are data structures. They are like entities (see the Entity Basics section) except that they do not have key properties. And because of this, complex types cannot be created, updated, or deleted without a supporting entity instance. For example, if you wanted to modify a complex type, you would need to get the specific entity instance back from the service, find the property using the complex type, modify it, then submit the entity with an update operation.

OData Operations

OData operations are pieces of custom logic that you can call on either a collection or an entity instance. For detailed information about how OData implements functions and actions (known as OData Operations) see the Operations section of the OData 3.0 protocol documentation. For more information about commonalities between functions and actions, see the Common rules for all operations section of the OData 3.0 protocol documentation.

Functions and actions are similar in nature but have different rules about how they are called and what they can do.

Actions

Actions may have side effects when called, meaning that they cause something to happen. For example, it may cause some records to be deleted, altered, or even cause something to happen on a server somewhere else. Actions can return an entity or an entity set, or nothing at all. Actions are called by sending an HTTP POST request to the URI of an entity or collection hosting the action. If the action requires parameters to be provided when called, this is done by supplying a single JSON object on the request body. Each parameter of the action must be supplied as a name/value pair on the JSON object. For more information about actions, see the Actions section of the OData 3.0 protocol documentation.

Functions

Functions do not have side effects when called, and always return an entity or an entity set in the response. A function is called by sending an HTTP GET request to the URI of the entity or collection hosting the function. If the function requires parameters to be provided when called, these may be provided on the URI or as a single JSON object on the request body. If the parameters are supplied on the body, each parameter is supplied as a name/value pair on the JSON object. For more information about functions, see the Functions section of the OData 3.0 protocol documentation.

Settings

An OData operation topic will have a table of settings that describes how the operation behaves. Based on the settings of an OData operation, you can determine if it is an Action or a Function. If the operation has side effects, it is always an action. If the operation is composable, it is always a function. The following table defines each setting.

Setting

Description

Is composable?

When true, indicates that the URI may continue to be composed. See OData URL Conventions for more information.

Has side effects?

Triggers something on the server. Only actions have side effects.

Requires an entity instance?

The URI must identify an entity instance to trigger the operation on.

Return type

The type of object returned by the operation.

Results belong to an entity set?

When true, indicates that the returned entity belongs to a specific collection (entity set).