All docs
V21.2
21.2
21.1
20.2
20.1
The page you are viewing does not exist in version 20.1. This link will take you to the root page.
19.2
The page you are viewing does not exist in version 19.2. This link will take you to the root page.
19.1
The page you are viewing does not exist in version 19.1. This link will take you to the root page.
18.2
The page you are viewing does not exist in version 18.2. This link will take you to the root page.
18.1
The page you are viewing does not exist in version 18.1. This link will take you to the root page.
17.2
The page you are viewing does not exist in version 17.2. This link will take you to the root page.

Transfer Data via REST API

  • 6 minutes to read

You can use a REST API to transfer data over the web. A REST API service is directly connected to a database and exchanges data records with client applications.

To transfer data over the web, use the following XPO components:

On the backend side, the web API controller must accept POST requests to the following actions:

  • /updateschema?doNotCreateIfFirstTableNotExist={true|false}
  • /selectdata
  • /modifydata

Tip

You can download a complete example here:

Create a Web API Controller

The steps below describe how to add an XPO web API controller to an ASP.NET Core Web API application.

  1. Register WebApiDataStoreService in a service collection on startup. Add XML Serializer formatters to MVC services.

    // Startup.cs
    using DevExpress.Xpo;
    using DevExpress.Xpo.DB;
    // ...
    public void ConfigureServices(IServiceCollection services) {
        // ...
    
        // configure WebApiDataStoreService
        string connectionString = Configuration.GetConnectionString("MyConnectionString");
        IDataStore dataStore = XpoDefault.GetConnectionProvider(connectionString, AutoCreateOption.SchemaAlreadyExists);            
        services.AddSingleton(new WebApiDataStoreService(dataStore));
    
        // add XML Serializer formatters
        services.AddMvc()
            .AddXmlSerializerFormatters();
    
        // ...
    }
    

    Tip

    More information: Dependency Injection.

  2. Add a controller with three POST methods: UpdateSchema, SelectData, and ModifyData.

    using System.Threading.Tasks;
    
    using DevExpress.Xpo.DB;
    
    using Microsoft.AspNetCore.Mvc;
    // ...
    // In this example, the controller URI is `[Your Service Address]/xpo`. 
    [ApiController]
    [Route("[controller]/[action]")]
    public class XpoController : ControllerBase {
        readonly WebApiDataStoreService DataStoreService;
        public XpoController(WebApiDataStoreService dataStoreService) {
            this.DataStoreService = dataStoreService;
        }
            [HttpPost]
            public Task<OperationResult<UpdateSchemaResult>> UpdateSchema([FromQuery] bool doNotCreateIfFirstTableNotExist, [FromBody] DBTable[] tables) {
                return DataStoreService.UpdateSchemaAsync(doNotCreateIfFirstTableNotExist, tables);
            }
            [HttpPost]
            public Task<OperationResult<SelectedData>> SelectData([FromBody] SelectStatement[] selects) {
                return DataStoreService.SelectDataAsync(selects);
            }
            [HttpPost]
            public Task<OperationResult<ModificationResult>> ModifyData([FromBody] ModificationStatement[] dmlStatements) {
                return DataStoreService.ModifyDataAsync(dmlStatements);
            }
    }
    

Support Cached Data Store

On the client side, create a WebApiDataStoreClient object and pass it as a parameter to the DataCacheNode constructor. Use this DataCacheNode instance as IDataStore. For example, pass it as a parameter to the SimpleDataLayer or ThreadSafeDataLayer constructor.

ICacheToCacheCommunicationCore cacheRoot = new WebApiDataStoreClient(httpClient, AutoCreateOption.SchemaAlreadyExists);
IDataStore dataStore = new DataCacheNode(cacheRoot);

To configure the Data Cache Root on the server side:

  1. Wrap an IDataStore instance in a DataCacheRoot object.

    // Startup.cs
    using DevExpress.Xpo;
    using DevExpress.Xpo.DB;
    // ...
    public void ConfigureServices(IServiceCollection services) {
        // ...
    
        // configure a WebApiDataStoreService
        string connectionString = Configuration.GetConnectionString("MyConnectionString");
        IDataStore dataStore = XpoDefault.GetConnectionProvider(connectionString, AutoCreateOption.SchemaAlreadyExists);            
        dataStore = new DataCacheRoot(dataStore);
        services.AddSingleton(new WebApiDataStoreService(dataStore));
    
        // add XML Serializer formatters
        services.AddMvc()
            .AddXmlSerializerFormatters();
    
        // ...
    }
    
  2. Add the following POST methods to the controller:

    • ModifyDataWithCookie
    • NotifyDirtyTables
    • ProcessCookie
    • SelectDataWithCookie
    • UpdateSchemaWithCookie
    using System.Threading.Tasks;
    
    using DevExpress.Xpo.DB;
    
    using Microsoft.AspNetCore.Mvc;
    // ...
    // In this example, the controller URI is `[Your Service Address]/xpo`. 
    [ApiController]
    [Route("[controller]/[action]")]
    public class XpoController : ControllerBase {
        readonly WebApiDataStoreService DataStoreService;
        public XpoController(WebApiDataStoreService dataStoreService) {
            this.DataStoreService = dataStoreService;
        }
    
        // ...
    
        [HttpPost]
        public OperationResult<DataCacheModificationResult> ModifyDataWithCookie([FromBody] WebApiDataContainer<ModificationStatement[]> data) {
            return DataStoreService.ModifyDataWithCookie(data);
        }
        [HttpPost]
        public OperationResult<DataCacheResult> NotifyDirtyTables([FromBody] WebApiDataContainer<string[]> data) {
            return DataStoreService.NotifyDirtyTables(data);
        }
        [HttpPost]
        public OperationResult<DataCacheResult> ProcessCookie([FromBody] DataCacheCookie data) {
            return DataStoreService.ProcessCookie(data);
        }
        [HttpPost]
        public OperationResult<DataCacheSelectDataResult> SelectDataWithCookie([FromBody] WebApiDataContainer<SelectStatement[]> data) {
            return DataStoreService.SelectDataWithCookie(data);
        }
        [HttpPost]
        public OperationResult<DataCacheUpdateSchemaResult> UpdateSchemaWithCookie([FromQuery] bool doNotCreateIfFirstTableNotExist, [FromBody] WebApiDataContainer<DBTable[]> data) {
            return DataStoreService.UpdateSchemaWithCookie(doNotCreateIfFirstTableNotExist, data);
        }        
    }
    

Connect a Client Application to a Web API Service

You can connect a client application to a web service in any of the following ways:

Note

Since WebApiDataStoreClient uses the HttpClient component, HttpClient.BaseAddress should point to a controller route. Note that HttpClient merges BaseAddress with a relative URI according to section [5.2.3. Merge Paths] of RFC 3986. This means that HttpClient excludes the last segment of the BaseAddress. To prevent this, add a slash / to the end of the BaseAddress.

This URI is correct: https://example.com/xpo/

This URI is not correct: https://example.com/xpo

Configure HttpClient options

To use the advanced HttpClient features (for example, the automatic HTTP content response decompression), connect the application to a Web API service using Option 2. Note that users will lose the ability to dynamically set the data store type using the XpoProvider connection string parameter.

using System;
using System.Net;
using System.Net.Http;
using DevExpress.Xpo.DB;
using DevExpress.Xpo.DB.Helpers;
// ...
var handler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.Brotli };
var httpClient = new HttpClient(handler, true);
httpClient.BaseAddress = new Uri("https://localhost:5001/xpo/");
httpClient.DefaultRequestHeaders.Add("Accept-Encoding", "br");
IDataStore dataStore = new WebApiDataStoreClient(httpClient, autoCreateOption);

To allow users to specify the data store type with the XpoProvider parameter, register a new provider name associated with a method that creates a provider instance.

using System;
using System.Net;
using System.Net.Http;
using DevExpress.Xpo;
using DevExpress.Xpo.DB;
using DevExpress.Xpo.DB.Helpers;
// ...
DataStoreBase.RegisterDataStoreProvider("WebApiWithBrotli", CreateDataStoreFromString);
string connectionString = @"XpoProvider=WebApiWithBrotli;uri=https://localhost:5001/xpo/";
IDataStore dataStore = XpoDefault.GetConnectionProvider(connectionString, AutoCreateOption.DatabaseAndSchema);
// ...
static IDataStore CreateDataStoreFromString(string connectionString, AutoCreateOption autoCreateOption, out IDisposable[] toDispose) {
    var handler = new HttpClientHandler() { AutomaticDecompression = System.Net.DecompressionMethods.Brotli };
    var httpClient = new HttpClient(handler, true);
    var parser = new ConnectionStringParser(connectionString);
    httpClient.BaseAddress = new Uri(parser.GetPartByName("uri"));
    httpClient.DefaultRequestHeaders.Add("Accept-Encoding", "br");
    toDispose = new IDisposable[] { httpClient };
    return new WebApiDataStoreClient(httpClient, autoCreateOption);
}

Connect a Xamarin App

You can connect a Xamarin app to an XPO in the same way as described in the previous section, but you need to follow extra steps to run the application in simulators. For detailed information, refer to the following help topic: Connect to local web services from iOS simulators and Android emulators.

An Android emulator uses its own network and cannot connect to a web service running on IIS Express, because IIS Express does not allow remote access. The solutions are as follows:

  1. For the ASP.NET Core Web API application: run a web service project using the “Project” profile instead of “IIS Express”.

  2. For the ASP.NET Web API application: use an open-source iisexpress-proxy tool.

Transfer Data via REST API using JSON Format

If you need a Web API service that returns XPO objects in the JSON format, manually implement the required controllers and the client API. The following examples illustrate how to implement such a service: