Skip to main content
A newer version of this page is available. .

JSON Data - Register Connections

  • 5 minutes to read

This document describes how to create a set of JSON data connections for the End-User Report Designer. The Data Source Wizard displays these connections when users create new JSON data sources.

web-netcore-designer-json-connections

The Data Source Wizard allows you to create a new JSON data source if a JSON data connection provider is registered in the application. You can register a built-in connection provider or implement and register a custom provider. The built-in connection provider obtains connections from the application’s configuration file (appsettings.json). A custom provider allows you to create connection strings at runtime and use a custom storage to store/load connection strings and credentials. You cannot use both providers in the same application.

Use Application Configuration File

Follow the steps below to use connection strings from the application configuration file:

  1. Specify data connections in the application’s configuration file (appsettings.json).

    {
    "ConnectionStrings": {
            "JsonConnection": "Uri=https://raw.githubusercontent.com/DevExpress-Examples/DataSources/master/JSON/customers.json"
        } 
    }
    
  2. Register the built-in connection string provider. For this, call the static ReportDesignerConfigurationBuilder.RegisterDataSourceWizardConfigFileJsonConnectionStringsProvider method at the application’s startup.

    using DevExpress.AspNetCore.Reporting;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.DependencyInjection;
    
    // ...
    public class Startup {
    // ...
        public void ConfigureServices(IServiceCollection services) {
        // ...
            services.ConfigureReportingServices(configurator => {
                // ...
                configurator.ConfigureReportDesigner(designerConfigurator => {
                    // ...
                    designerConfigurator.RegisterDataSourceWizardConfigFileJsonConnectionStringsProvider();
                    // ...
                });
            });
            // ...
        }
    // ...
    }
    

    web-designer-json-connection-from-webconfig

If you use data connections from the appsettings.json, you cannot use a custom connection string provider described in the next section.

Implement a Custom Connection String Provider

A custom connection provider is an alternative to the appsettings.json file. A custom connection provider allows you to manage JSON connections that are accessible to users:

  • modify the available connections at runtime (for example, on a per-user basis)
  • allow users to create new connections
  • validate and store connections in a separate storage
  • store credentials securely

To review a sample JSON connection provider and storage implementation, use a DevExpress template to create an ASP.NET Core Reporting application. In the Project Wizard, specify the Add Sample JSON Data Connection Storage setting to true. Refer to the following help topic for more information: Create an ASP.NET Core Application with a Report Designer.

To use a custom JSON connection provider in your application, follow the steps below:

  1. Create a class that implements the DevExpress.DataAccess.Web.IDataSourceWizardJsonConnectionStorage interface. The code snippet below demonstrates an implementation that stores connections in a session.

    Tip

    Review the Access HttpContext.Session in Services topic for information on how to use session in methods implemented in a custom connection provider class.

    Show code
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using DevExpress.DataAccess.Json;
    using DevExpress.DataAccess.Web;
    using DevExpress.DataAccess.Wizard.Services;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using JsonAspNetCoreFromTemplate.Code;
    
    namespace JsonAspNetCoreFromTemplate.Services
    {
        public class CustomDataSourceWizardJsonDataConnectionStorage : IDataSourceWizardJsonConnectionStorage
        {
            public const string JsonDataConnectionsKey = "dxJsonDataConnections";
            protected IWebHostEnvironment Environment { get; }
            protected IHttpContextAccessor HttpContextAccessor { get; }
    
            public CustomDataSourceWizardJsonDataConnectionStorage(
                IWebHostEnvironment env, IHttpContextAccessor httpContextAccessor)
            {
                Environment = env;
                HttpContextAccessor = httpContextAccessor;
            }
    
            public Dictionary<string, string> GetConnections()
            {
                if (HttpContextAccessor.HttpContext == null || HttpContextAccessor.HttpContext.Session == null)
                {
                    return null;
                }
                var connectionStrings = 
                    HttpContextAccessor.HttpContext.Session
                    .GetObjectFromJson<Dictionary<string, string>>(JsonDataConnectionsKey);
                if (connectionStrings == null)
                {
                    connectionStrings = GetDefaults();
                    UpdateSessionState(connectionStrings);
                }
                return connectionStrings;
            }
    
            bool IJsonConnectionStorageService.CanSaveConnection { 
                get { return HttpContextAccessor.HttpContext != null 
                        && HttpContextAccessor.HttpContext.Session != null; } }
            bool IJsonConnectionStorageService.ContainsConnection(string connectionName)
            {
                var connections = GetConnections();
                return connections == null ? false : connections.ContainsKey(connectionName);
            }
    
            IEnumerable<JsonDataConnection> IJsonConnectionStorageService.GetConnections()
            {
                var connections = GetConnections();
                if (connections == null)
                {
                    return new List<JsonDataConnection>();
                }
                return connections.Select(x => CreateJsonDataConnectionFromString(x.Key, x.Value));
    
            }
    
            JsonDataConnection IJsonDataConnectionProviderService.GetJsonDataConnection(string name)
            {
                var connections = GetConnections();
                if (connections == null || !connections.ContainsKey(name))
                    throw new InvalidOperationException();
                return CreateJsonDataConnectionFromString(name, connections[name]);
            }
    
            void IJsonConnectionStorageService.SaveConnection(string connectionName,
                JsonDataConnection dataConnection, bool saveCredentials)
            {
                var connections = GetConnections();
                if (connections == null)
                {
                    return;
                }
                var connectionString = dataConnection.CreateConnectionString();
                if (connections.ContainsKey(connectionName))
                {
                    connections[connectionName] = connectionString;
                }
                else
                {
                    connections.Add(connectionName, connectionString);
                }
                UpdateSessionState(connections);
            }
    
            Dictionary<string, string> GetDefaults()
            {
                var connections = new Dictionary<string, string>();
                var uri = new Uri(Path.Combine(Environment.ContentRootPath, "Data", "nwind.json"),
                    UriKind.Relative);
                var dataConnection = new JsonDataConnection(new UriJsonSource(uri)) 
                { 
                    StoreConnectionNameOnly = true, 
                    Name = "Products (JSON)" 
                };
                connections.Add(dataConnection.Name, dataConnection.CreateConnectionString());
                return connections;
            }
    
            void UpdateSessionState(Dictionary<string, string> connectionStrings)
            {
                HttpContextAccessor.HttpContext.Session.SetObjectAsJson(JsonDataConnectionsKey,
                    connectionStrings);
            }
    
            public static JsonDataConnection CreateJsonDataConnectionFromString(string connectionName,
                string connectionString)
            {
                return new JsonDataConnection(connectionString) 
                { 
                    StoreConnectionNameOnly = true,
                    Name = connectionName
                };
            }
        }
    }
    
    using Microsoft.AspNetCore.Http;
    using Newtonsoft.Json;
    
    namespace JsonAspNetCoreFromTemplate.Code {
        public static class SessionExtensions {
            public static void SetObjectAsJson(this ISession session, string key, object value) {
                session.SetString(key, JsonConvert.SerializeObject(value));
            }
    
            public static T GetObjectFromJson<T>(this ISession session, string key) {
                var value = session.GetString(key);
                return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
            }
        }
    }
    
  2. To fetch JSON connections for the Preview, create a new class (CustomJsonDataConnectionProviderFactory in this example) that implements the DevExpress.DataAccess.Web.IJsonDataConnectionProviderFactory interface. The WebDocumentViewerJsonDataConnectionProvider class, that implements the DevExpress.DataAccess.Json.IJsonDataConnectionProviderService interface, resolves a connection name to a connection.

    Show code
    using DevExpress.DataAccess.Json;
    using DevExpress.DataAccess.Web;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using System.Collections.Generic;
    using JsonAspNetCoreFromTemplate.Code;
    
    namespace JsonAspNetCoreFromTemplate.Services
    {
        public class CustomJsonDataConnectionProviderFactory : IJsonDataConnectionProviderFactory {
            protected IWebHostEnvironment Environment { get; }
            protected IHttpContextAccessor HttpContextAccessor { get; }
            Dictionary<string, string> connectionStrings;
    
            public CustomJsonDataConnectionProviderFactory(IWebHostEnvironment env, 
                IHttpContextAccessor httpContextAccessor) {
                Environment = env;
                HttpContextAccessor = httpContextAccessor;
                if (HttpContextAccessor.HttpContext == null || 
                    HttpContextAccessor.HttpContext.Session == null)
                {
                    connectionStrings = null;
                }
                else
                {
                    connectionStrings = 
                        HttpContextAccessor.HttpContext.Session.
                        GetObjectFromJson<Dictionary<string, string>>(
                            CustomDataSourceWizardJsonDataConnectionStorage.JsonDataConnectionsKey);
                }
            }
    
            public IJsonDataConnectionProviderService Create()
            {
                return new WebDocumentViewerJsonDataConnectionProvider(connectionStrings);
            }
        }
    
        public class WebDocumentViewerJsonDataConnectionProvider : IJsonDataConnectionProviderService
        {
            readonly Dictionary<string, string> jsonDataConnections;
            public WebDocumentViewerJsonDataConnectionProvider(Dictionary<string, string> jsonDataConnections)
            {
                this.jsonDataConnections = jsonDataConnections;
            }
            public JsonDataConnection GetJsonDataConnection(string name)
            {
                if (jsonDataConnections == null)
                    return null;
                return CustomDataSourceWizardJsonDataConnectionStorage.CreateJsonDataConnectionFromString(
                    name, jsonDataConnections[name]);
            }
        }
    }
    
  3. Register services at application startup:

    Show code
    public class Startup {
    // ...
    public void ConfigureServices(IServiceCollection services) {
    // ...
    services.ConfigureReportingServices(configurator => {
        configurator.ConfigureReportDesigner(designerConfigurator => {
    // ...
        designerConfigurator.RegisterDataSourceWizardJsonConnectionStorage<CustomDataSourceWizardJsonDataConnectionStorage>(true);
    });
    configurator.ConfigureWebDocumentViewer(viewerConfigurator => {
    // ...
                viewerConfigurator.RegisterJsonDataConnectionProviderFactory<CustomJsonDataConnectionProviderFactory>();
            });
        });
    }
    // ...
    }
    

After you register a custom JSON connection provider, you can:

  • use an existing connection to create a new JSON data source:

    web-designer-json-storage-use-existing-connection

  • create a new JSON connection:

    web-designer-json-storage-create-connection

See Also