Skip to content

GIS Maps Providers – Guide & Recipes

Applies to GeoServer (WMS), MCLite (PostgreSQL rasters), MIKECore (DFS2/DFSU), plus MapStyle backends. Use this page to pick a provider fast, and wire it up. Deep dives are linked.


See for more details


Quick map of the providers (the big picture)

Map sources (what renders your bitmap)

Provider Kind R/W “Layers” mean… Where data lives Best for / notes
GeoServer WMS → SKBitmap Ungrouped Read <workspace>:<layer> GeoServer WMS Tokenized WMS template → image; optional Basic Auth; time param appended (hh).
MCLite GroupedMapSource Grouped Read MCLite groups / raster ids PostGIS rasters (PostgreSQL) Postgres-only for render/time/stream; catalog works across DBs.
MIKECore Dfs2MapSource / DfsuMapSource Ungrouped Read A file (.dfs2 / .dfsu) DFS files on disk Contouring engine; requires EPSG:3857; supports time stacks & palettes.

Style repositories (where styles are stored)

Provider What it stores Typical consumer Notes
GeoServer MapStyleRepository (REST) SLDs on the GeoServer host GeoServer WMS Add via zipped style or raw SLD XML.
PostgreSQL MapStyleRepository Arbitrary StyleCode text MIKECore, custom renderers, WMS too Simple table (id,name,style_code).
In-process MapStyleRepository (JSON, etc.) Local JSON Any Handy for dev; swap later for PostgreSQL.

Which one should I pick?

  • You have GeoServer and want WMS imagesGeoServer WMS
  • Your rasters live in PostGIS and you want catalogs + timeMCLite Grouped
  • You need to render DFS2/DFSU files directlyMIKECore
  • You want centralized styles shared across servicesPostgreSQL MapStyle

Capabilities at a glance

Capability / API GeoServer (WMS) MCLite (PG) MIKECore (DFS2/DFSU)
GetMap (single image)
GetMaps (time stack)
GetDateTimes(id)
Catalog (GetAll, groups, etc.)
ASCII/aux stream ✓ (AAI)
Style via GeoServer
Style via PostgreSQL ✓*
Auth Basic (opt) DB creds
  • MCLite render ignores MapStyle colors (pipeline is DB-driven), but you can still use a style repo for legends/UI.

IDs & parameters — mental model (cheat-sheet)

Common MapService.GetMap(...) signature

(style, crs, bbox, width, height, sourceId, dateTime, item, parameters)
  • GeoServer (WMS) Template tokens: [group] (workspace), [layer], [bbox], [crs], [width], [height], [mapstyle]. Mapping:

    • GetMap: sourceId → [group], item → [layer], style → [mapstyle]
    • GetMaps: dictionary value is [layer]; final item arg is [group]
    • Adds &time= (yyyy-MM-ddThh:mm:ss.fffZ) if dateTime present
  • MCLite (PostgreSQL rasters) Grouped; sourceId/item are unused. Pass provider keys in parameters:

    • rasterid (required): table/raster to draw
    • srs (used only if crs arg is empty)
    • time (optional range string "start\end", either side optional)
  • MIKECore (DFS2/DFSU)

    • crs must be "EPSG:3857" (throws otherwise)
    • sourceId = file name when the provider was constructed with a directory; empty if constructed with a file
    • item = item name or number (string "3")
    • parameters (optional): includevector, isoline, vectorcolor, scale, coloringtype, shadingtype, etc.

Registering providers (minimal wiring)

Programmatic (ServiceLocator)

// GeoServer WMS
var wmsQuery = "[group]/wms?service=WMS&version=1.1.0&request=GetMap&format=image/png" +
               "&layers=[group]:[layer]&bbox=[boundingbox]&width=[width]&height=[height]&srs=[crs]&styles=[mapstyle]";
ServiceLocator.Register(
  new DHI.Services.GIS.Maps.MapService(
    new DHI.Services.Provider.GeoServer.MapSource("https://gs/geoserver/", wmsQuery, "user","pass"),
    new DHI.Services.GIS.Maps.MapStyleService(
      new DHI.Services.Provider.GeoServer.MapStyleRepository("https://gs/geoserver/","user","pass"))),
  "geo-map");

// MCLite (PostgreSQL rasters)
ServiceLocator.Register(
  new DHI.Services.GIS.Maps.GroupedMapService(
    new DHI.Services.Provider.MCLite.GroupedMapSource(
      "dbflavour=PostgreSQL;host=localhost;port=5432;database=ws;user id=...;password=...;workspace=workspace1"),
    mapStyleService: null),
  "mclite");

// MIKECore DFS2 / DFSU
ServiceLocator.Register(
  new DHI.Services.GIS.Maps.MapService(
    new DHI.Services.Provider.MIKECore.Dfs2MapSource(@"C:\data\dfs2\R20141001.dfs2"),
    mapStyleService: null),
  "dfs2-map");
ServiceLocator.Register(
  new DHI.Services.GIS.Maps.MapService(
    new DHI.Services.Provider.MIKECore.DfsuMapSource(@"C:\data\dfsu"),
    mapStyleService: null),
  "dfsu-map");

// Styles in PostgreSQL (optional)
var pgRepo = new DHI.Services.Provider.PostgreSQL.MapStyleRepository(
  "Server=localhost;Port=5432;Database=ProviderTest;User Id=postgres;Password=secret");
ServiceLocator.Register(
  new DHI.Services.GIS.Maps.MapService(
    new DHI.Services.Provider.MIKECore.Dfs2MapSource(@"C:\data\dfs2\R20141001.dfs2"),
    new DHI.Services.GIS.Maps.MapStyleService(pgRepo)),
  "dfs2-map-pgstyle");

Via connections.json (WebApi snapshot)

{
  "geo-map": {
    "$type": "DHI.Services.GIS.WebApi.MapServiceConnection, DHI.Services.GIS.WebApi",
    "MapSourceType": "DHI.Services.Provider.GeoServer.MapSource, DHI.Services.Provider.GeoServer",
    "MapSourceConnectionString": "BaseUrl=https://gs/geoserver/;Query=[group]/wms?...&styles=[mapstyle];UserName=admin;Password=geoserver",
    "MapStyleRepositoryType": "DHI.Services.Provider.GeoServer.MapStyleRepository, DHI.Services.Provider.GeoServer",
    "MapStyleConnectionString": "BaseUrl=https://gs/geoserver/;UserName=admin;Password=geoserver",
    "Name": "GeoServer WMS",
    "Id": "geo-map"
  },
  "mclite": {
    "$type": "DHI.Services.GIS.WebApi.GroupedMapServiceConnection, DHI.Services.GIS.WebApi",
    "MapSourceType": "DHI.Services.Provider.MCLite.GroupedMapSource, DHI.Services.Provider.MCLite",
    "MapSourceConnectionString": "dbflavour=PostgreSQL;host=...;port=5432;database=...;user id=...;password=...;workspace=workspace1",
    "Name": "MCLite (PG)",
    "Id": "mclite"
  },
  "dfs2-map": {
    "$type": "DHI.Services.GIS.WebApi.MapServiceConnection, DHI.Services.GIS.WebApi",
    "MapSourceType": "DHI.Services.Provider.MIKECore.Dfs2MapSource, DHI.Services.Provider.MIKECore",
    "MapSourceConnectionString": "[AppData]dfs2\\R20141001.dfs2",
    "Name": "DFS2",
    "Id": "dfs2-map"
  }
}

If you rely on [AppData], set once at startup:

AppDomain.CurrentDomain.SetData("DataDirectory",
  Path.Combine(builder.Environment.ContentRootPath, "App_Data"));

Using over HTTP (what routes you get)

Typical host exposes a WMS-like endpoint and (for grouped connections) a layer catalog:

GET  /api/maps?request=GetMap&service=wms&version=1.3.0
      &width=1024&height=768
      &styles=<styleIdOrCode>
      &layers=<connectionId>
      &crs=EPSG:4326|EPSG:3857
      &bbox=xmin,ymin,xmax,ymax
      &item=<layerOrItem>
      &timestamp=<ISO>               # GeoServer/MIKECore time
      &rasterid=<name>               # MCLite (forwarded to Parameters)
      &time=<start\end>              # MCLite time window

Examples

  • GeoServer WMS GET /api/maps?...&layers=geo-map&styles=coast-sld&crs=EPSG:4326&bbox=8,54,13,58&item=coastline

  • MCLite (PG) GET /api/maps?...&layers=mclite&crs=EPSG:3857&bbox=1110000,6400000,1130000,6420000&rasterid=RainGrid_1h&time=2024-04-01T00:00:00Z\2024-04-01T06:00:00Z

  • MIKECore (DFS2) GET /api/maps?...&layers=dfs2-map&crs=EPSG:3857&bbox=1110000,6400000,1130000,6420000&item=Water%20Level&timestamp=2014-10-01T10:00:00Z

Grouped catalog (MCLite)

GET /api/maps/mclite/layers?group=workspace1/raster
GET /api/maps/mclite/layers/fullnames?group=workspace1/raster;nonrecursive
GET /api/maps/mclite/datetimes/{fullname}
GET /api/maps/mclite/layers/{fullname}/stream/ascii

Tips

  • GeoServer (WMS)

    • Use WMS (not WFS/WMS-PNG mixups). Keep your template consistent with server version (srs vs crs, axis order).
    • In GetMaps, parameters["crs"] is used; in GetMap, pass crs argument.
    • Time param uses 12-hour hh. If your server expects HH, customize your template/placeholder.
  • MCLite

    • Render/time/stream are PostgreSQL-only; SQLite/SQL Server throw NotSupportedException.
    • Required provider key: rasterid. crs wins over parameters["srs"].
    • Returns null if view doesn’t intersect the raster overview envelope—handle that in callers.
  • MIKECore

    • Strict EPSG:3857 only; anything else throws. Convert upstream.
    • item can be name or index as string (e.g., "3").
    • Dispose every SKBitmap (especially in stacks).
    • Consider the cached connection variant for hot extents (pretiles, zoom levels, TTL).
  • PostgreSQL MapStyles

    • Table bootstrap creates public.map_style if missing; it won’t create schemas for you.
    • Use a least-privilege DB role; rely on pooling (Npgsql default).