Skip to content

Connections Project Template

You can find the official source for the template here:
GitHub – Connections Web API Template


Overview

This template provides:

  1. JWT Authentication and claims-based Authorization.
  2. API Versioning and response compression.
  3. Swagger/OpenAPI with XML comments support.
  4. HSTS and exception handling middleware.
  5. Serilog logging to file and console.
  6. Two ways to register services:
    • Declarative (lazy) via connections.json.
    • Imperative via ServiceLocator.Register(...) in code.
  7. Optional SignalR integration for real-time notifications (disabled by default).

It’s ready-to-run with file-based connection metadata in App_Data/connections.json.

For background on providers and plugins (and placeholders like [AppData] / [env:...]), see: Plugins Reference


Adding the NuGet Package

Install the core package:

dotnet add package DHI.Services.Connections.WebApi

If you use specific domains (e.g., Time Series CSV or USGS), also add their packages, for example:

dotnet add package DHI.Services.TimeSeries
dotnet add package DHI.Services.TimeSeries.WebApi

Or add this for provider-specific as well:

dotnet add package DHI.Services.USGS
dotnet add package DHI.Services.PostgreSQL
...


How Connections Are Registered

You have two options. Use one or mix both as needed.

1) Declarative (Lazy) via connections.json

Enable the Connections Repository and LazyCreation (default true):

var lazyCreation = configuration.GetValue("AppConfiguration:LazyCreation", true);
Services.Configure(new ConnectionRepository("connections.json"), lazyCreation);

Put connections.json in your App_Data folder (the template sets AppDomain.CurrentDomain.SetData("DataDirectory", ...) so [AppData] resolves there).

Example connections.json (CSV repository for Time Series):

{
    "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[DHI.Services.IConnection, DHI.Services]], mscorlib",
    "connections-csv": {
        "$type": "DHI.Services.TimeSeries.WebApi.TimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
        "ConnectionString": "[AppData]",
        "RepositoryType": "DHI.Services.TimeSeries.CSV.TimeSeriesRepository, DHI.Services.TimeSeries",
        "Name": "CSV time series service connection",
        "Id": "connections-csv"
    }
}

How it works:

  • The connection type is a concrete connection class (e.g., TimeSeriesServiceConnection or DiscreteTimeSeriesServiceConnection) that knows how to Create() the actual service instance.
  • The RepositoryType points to the repository implementation type (e.g., CSV, USGS, PostgreSQL, etc.).
  • The ConnectionString is passed to the repository. You can use [AppData] and [env:VAR] placeholders.

For Time Series, the connection class (source linked above) looks like:

  • TimeSeriesServiceConnection creates TimeSeriesService<string,double> from the configured repository.
  • DiscreteTimeSeriesServiceConnection creates DiscreteTimeSeriesService<string,double> similarly.

(These classes resolve RepositoryType, instantiate it with ConnectionString.Resolve(), and return the concrete service.)

You can find the list of Connections classes for TimeSeries in this GitHub repository: GitHub – TimeSeries Web API Connections'

Similar Connections classes are available for other Web APIs.

2) Imperative via ServiceLocator (Register in code)

You can also register connections directly in code using ServiceLocator.Register(...) instead of (or in addition to) defining them in connections.json.

This works with any domain or module (Time Series, Jobs, Scenarios, Workflows, etc.), the following are only examples.

Example: Time Series service via CSV repository

ServiceLocator.Register(
    new DiscreteTimeSeriesService<string, double>(
        new DHI.Services.TimeSeries.CSV.TimeSeriesRepository("[AppData]".Resolve())
    ),
    "csv-timeseries"
);

Example: Time Series service via USGS provider

var fixedStartDate = new DateTime(2020, 01, 01);
var fixedEndDate = new DateTime(2020, 12, 31);

ServiceLocator.Register(
    new TimeSeriesService<string, double>(
        new DHI.Services.Provider.USGS.TimeSeriesRepository(
            $"http://waterservices.usgs.gov/nwis/dv?startDT={fixedStartDate:yyyy-MM-dd}&endDt={fixedEndDate:yyyy-MM-dd}"
        )
    ),
    "usgs-timeseries"
);

Example: Jobs service via PostgreSQL repository

ServiceLocator.Register(
    new JobService(
        new DHI.Services.Provider.PostgreSQL.JobRepository(
            "Server=localhost;Port=5432;Database=ProviderTest;User Id=postgres;Password=Solutions!"
        )
    ),
    "postgres-jobs"
);

Tip: The pattern is always the same:

  1. Choose the correct service class for your domain (e.g., TimeSeriesService, JobService, ScenarioService).
  2. Pass in the repository implementation you want (e.g., CSV, PostgreSQL, USGS, Workflow).
  3. Give it a unique connection name (the second argument).

Choosing and Configuring Connection Types

Pick the connection class that matches your service abstraction: - DHI.Services.TimeSeries.WebApi.TimeSeriesServiceConnection - DHI.Services.TimeSeries.WebApi.DiscreteTimeSeriesServiceConnection - Etc. Set: - RepositoryType to the fully qualified repository type (assembly-qualified). - ConnectionString to what that repository expects (file path, URL, DSN, etc.). Can include [AppData] and [env:...].

Example: Discrete Time Series via CSV

{
    "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[DHI.Services.IConnection, DHI.Services]], mscorlib",
    "discrete-csv": {
        "$type": "DHI.Services.TimeSeries.WebApi.DiscreteTimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
        "ConnectionString": "[AppData]",
        "RepositoryType": "DHI.Services.TimeSeries.CSV.DiscreteTimeSeriesRepository, DHI.Services.TimeSeries",
        "Name": "CSV discrete time series",
        "Id": "discrete-csv"
    }
}

Example: Time Series via USGS (provider)

{
    "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[DHI.Services.IConnection, DHI.Services]], mscorlib",
    "timeseries-usgs": {
        "$type": "DHI.Services.TimeSeries.WebApi.TimeSeriesServiceConnection, DHI.Services.TimeSeries.WebApi",
        "ConnectionString": "http://waterservices.usgs.gov/nwis/dv/?startDT=2015-01-01&endDt=2015-01-31",
        "RepositoryType": "DHI.Services.Provider.USGS.TimeSeriesRepository, DHI.Services.Provider.USGS",
        "Name": "USGS time series service connection",
        "Id": "timeseries-usgs"
    }
}

The actual repository class names may vary across domains/providers; check the package you’re using.


Security Notes

  • Store your RSA public key with [env:PublicRSAKey] and inject it via environment variable.
  • Keep ClockSkew = TimeSpan.Zero if you want strict token lifetimes.
  • Avoid committing production connections.json with secrets; move secrets to environment variables and use [env:...] placeholders.