Blog

All Blog Posts  |  Next Post  |  Previous Post

Introducing TMS XData Query Builder and more!

Tuesday, June 22, 2021

Photo by Adyant Pankaj on Unsplash

We're excited to announce TMS XData 5.2 version with several new great features. TMS XData is the more straightforward way to take your Delphi app to the cloud, allowing you to create secure, robust REST servers along with a huge ecosystem around it. Here are the major features in this release, which also includes several minor improvements and bug fixes.

XData Query Builder

XData allows you to easily query entities from automatic entity set endpoints using a full query syntax. For example, to query customers which name is "Paul" or birthday date is lower then August 1st, 1940, ordered by name in descending order, you can write a code like this:

Customers := Client.List<TCustomer>('$filter=(Name eq ''Paul'') or (Birthday lt 1940-08-01)&$orderby=Name desc');

But now you don't need to worry to write the raw query syntax anymore. The new XData Query Builder allows you to build such filter using a fluent interface which already does some validation (like checking for correct property names) before the data is sent to the server:

Customers := Client.List<TCustomer>(
  CreateQuery
    .From(TCustomer)
    .Filter(
      (Linq['Name'] = 'Paul') 
      or (Linq['Birthday'] < EncodeDate(1940, 8, 1))
    )
    .OrderBy('Name', False)
    .QueryString
  );

You can build logical expressions and projections in a similar way you would do with TMS Aurelius criteria.

Receive DTO objects in URL query string

Service operations can now receive DTOs (Delphi objects) from the query string of the request URL (as long the DTO only have properties of scalar types). In this case, each DTO property will be a separated query param. Suppose you have a class TCustomerDTO which has properties Id and Name, then you can declare the method like this:

   [HttpGet] function FindByIdOrName(Customer: TCustomerDTO): TList<TCustomer>;

And have your Customer parameter be received from a request URL like this:

GET /CustomerService/FindByIdOrName?Id=10&Name='Paul'.

XData queries in service operations

Now, in addition to send queries to automatic CRUD entity set endpoints, you can also benefit from XData query mechanism in service operations. You can now easily receive and process XData query syntax like $filter, $orderby, $top and $skip in service operations, even for DTOs, and create Aurelius criteria from it. You can declare a service like this:

type  IMyService = interface(IInvokable)
    [HttpGet] function List(Query: TXDataQuery): TList<TCustomer>;

Which means clients can now invoke the endpoint passing the same $filter, $orderby, $top and $skip parameters, like this:

GET /MyService/List/?$filter=Name eq 'Foo'&$orderby=Name&$top=10&$skip=30

Or, of course, passing the raw filter string with TXDataClient:

  Customer := Client.Service<IMyService>
    .List('$filter=Name eq 'Foo'&$orderby=Name&$top=10&$skip=30');

Or even using the brand new XData query builder fluent interface:

  Customer := Client.Service<IMyService>.List(
    CreateQuery.From(TCustomer)
      .Filter(Linq['Name'] eq 'Foo')
      .OrderBy('Name')
      .Top(10).Skip(30)
      .QueryString
  );

From server-side, you can create an Aurelius criteria automatically from the passed XData query:

function TMyService.List(Query: TXDataQuery): TList<TCustomer>;
begin
  Result := TXDataOperationContext.Current
    .CreateCriteria<TCustomer>(Query).List;
end;

Not only that, you can even create a criteria from a query based on a DTO object:

function TMyService.List(Query: TXDataQuery): TList<TCustomer>;
begin
  Result := TXDataOperationContext.Current
    .CreateCriteria<TCustomer>(Query, TCustomerDTO).List;
end;

In the example above, even though you are creating a criteria for the TCustomer class, the query will be validated based on the TCustomerDTO class. This means XData will only accept queries that use properties from TCustomerDTO. For example, if the filter string is $filter=Status eq 2, even if the Status property exists in TCustomer, if it does not exist in class TCustomerDTO the query will not be accepted and an error "property Status does not exist" will return to the client.

And there is more!

There are even more new features:

  • Nullable<T> types are now supported in plain Delphi objects (in addition to existing support in Aurelius entities). When using plain Delphi objects as DTOs, like when receiving or returning them in service operations, they are now properly serialized/deserialized as JSON.

  • A new Forward middleware processes x-forwarded-* headers for improved behavior of Sparkle servers behind reverse or edge proxies.

  • A new "Sparkle app" demo shows how to create a Windows XData server application working as both VCL application (for Debug) or Windows service (for Release).

Want to know more?

Great new features in this release! If you are already a TMS XData user, please comment below, let us know what do you think about this exciting release!

If want to know more about XData, you can always check the documentation of course, but also don't hesitate to contact us to get help. Also check the existing content in our channels: subscribe to our e-mail newsletter, follow our Facebook page and subscribe to our YouTube channel!

(*) Photo by Adyant Pankaj on Unsplash



Wagner Landgraf




This blog post has received 1 comment.


1. Wednesday, June 23, 2021 at 4:05:21 AM

A really great product keeps on getting better!

Rick Hazell




Add a new comment

You will receive a confirmation mail with a link to validate your comment, please use a valid email address.
All fields are required.



All Blog Posts  |  Next Post  |  Previous Post