Show/Hide Toolbars

TMS XData Documentation

Navigation: Service Operations

Invoking Operations using HTTP

Scroll Prev Top Next More

To invoke an operation, the client issues an HTTP request to a URL identifying the operation. The URL for an operation is the service root, followed by the name of the service, followed by the name of operation in that service. Consider the following service operation:

 

  [ServiceContract]
  IMathService = interface(IInvokable)
  ['{BAD477A2-86EC-45B9-A1B1-C896C58DD5E0}']
    function Multiply(A, B: double): double;

 

Base routing

 

Note that, by default, the URL path that identifies the service is the same name as the service interface, but without the "I" prefix, followed by the name of the method (Multiply). The default endpoint for the operation will be:

 

http://server:2001/tms/xdata/MathService/Multiply

 

Those names can be modified by adding URIPathSegment attribute to either IMathService interface and Multiply method. By default, the server will respond to a POST method at that address. You can change the HTTP method used by request when defining the service contract. The endpoint URL can also be modified if the method has one or more FromPath parameters (see below).

 

Parameter binding

 

Method parameters can be received in three different ways:

 

From a JSON property in request body (FromBody);

From the query part of the request URL (FromQuery);

From a path segment of the request URL (FromPath);

 

FromBody parameters

 

FromBody parameters are retrieved from a JSON object in the request body, where each name/value pair corresponds to one parameter. The pair name must contain the parameter name (the one declared in the method), and value contains the JSON representation of the parameter value, which can be either scalar property values, the representation of an entity, or the representation of a collection of entities. The following is an example of a request that invokes the Multiply operation with the two parameters defined as FromBody.

 

Method declaration:

    function Multiply(A, B: double): double;

 

Equivalent to:

    [HttpPost] function Multiply([FromBody] A: double; [FromBody] B: double): double;

 

How to invoke:

POST /tms/xdata/MathService/Multiply HTTP/1.1
Host: server:2001
 
{
  "a": 5,
  "b": 8
}

 

FromBody is the default parameter binding mode except for GET requests. When the method is explicitly defined to response to GET requests (using HttpGet attribute), the default parameter binding mode is FromQuery.

 

FromQuery parameters

 

FromQuery parameters are retrieved from the query part of the request URL, using name=value pairs separated by "&" character, and the parameter value must be represented as URI literal. Only scalar property values are allowed, you can't pass representation of entities or collection of entities in GET requests. If the Multiply operation of previous example was modified to respond to a GET request, the binding mode would default to FromQuery, according to the following example.

 

Method declaration:

    [HttpGet] function Multiply(A, B: double): double;

 

Equivalent to:

    [HttpGet] function Multiply([FromQuery] A: double; [FromQuery] B: double): double;

 

How to invoke:

GET /tms/xdata/MathService/Multiply?a=5&b=8 HTTP/1.1

 

FromQuery is the default parameter binding mode for GET requests.

 

FromPath parameters

 

FromPath parameters are retrieved from path segements of the request URL. Each segment is a parameter value, retrieved in the same order where the FromPath parameters are declared in the method signature. As a consequence, it modifies the URL address used to invoke the operation. The following example modified the Multiply method parameters to be received from path.

 

Method declaration:

    [HttpGet] function Multiply([FromPath] A: double; [FromPath] B: double): double;

 

How to invoke:

GET /tms/xdata/MathService/Multiply/5/8 HTTP/1.1

 

Parameter "A" was the first declared, thus it will receive value 5. Parameter "B" value will be 8.

 

Mixing binding modes

 

You can mix binding modes in the same method operation, as illustrated in the following example:

 

Method declaration:

  procedure Process(

    [FromPath] PathA: Integer; 

    [FromQuery] QueryA: string;

    BodyA, BodyB: string;

    [FromQuery] QueryB: Boolean;

    [FromPath] PathB: string;

  ): double;

 

How to invoke:

POST /tms/xdata/MyService/Process/5/value?QueryA=queryvalue&QueryB=true HTTP/1.1

 

{
  "BodyA": "one",
  "BodyB": "two"
}

 

Here are the values of each parameter received:

PathA: 5

QueryA: queryvalue

BodyA: one

BodyB: two

QueryB: true

PathB: value

 

Response

 

On success, the response is 200 OK for operations that return results or 204 No Content for operations without a return type. If the operation returns a value, it will also be in the same JSON format used for parameters. The value is sent by the server wrapped by a JSON object with a name/value pair named "value". The value of the "value" pair is the result of the operation. In the Multiply example, it would be like this:

 

HTTP/1.1 200 OK
 
{
    "value": 40
}

 

There are some exceptions for the general rule above:

 

Methods with parameters passed by reference

 

In this case, the result will be a JSON object where each property relates to a parameter passed by reference. If the method is also a function (returns a value), then an additional property with name "result" will be included. For example, suppose the following method:

 

function TMyService.DoSomething(const Input: stringvar Param1, Param2: Integer): Boolean;

 

This will be a possible HTTP response from a call to that method:

 

HTTP/1.1 200 OK
 
{

    "result": True,

    "Param1": 50,

    "Param2": 30
}

 

Method with a single FromBody object parameter

 

If the method has a single FromBody parameter (parameters with other binding type can exxist) and that parameter is an object, for example:

 

procedure UpdateCustomer(C: TCustomer);

 

then clients must send the JSON entity representation of the customer directly in request body, without the need to wrap it with the parameter name.

 

Method which returns a single object

 

If the method returns a single object parameter, for example:

 

function FindCustomer(const Name: string): TCustomer;

 

then the server will return the JSON entity representation of the customer in the response body, without wrapping it in the "value" name/value pair.

 

Method with a single FromBody scalar parameter

 

If the method receives a single scalar parameter, for example:

 

procedure ChangeVersion(const Version: string);

 

In this case, clients can send the value of Version parameter in a name/value pair named "value", in addition to the original "Version" name/value pair. Both can be used.