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 images → GeoServer WMS
- Your rasters live in PostGIS and you want catalogs + time → MCLite Grouped
- You need to render DFS2/DFSU files directly → MIKECore
- You want centralized styles shared across services → PostgreSQL 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
MapStylecolors (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]; finalitemarg is [group]- Adds
&time=(yyyy-MM-ddThh:mm:ss.fffZ) ifdateTimepresent
-
MCLite (PostgreSQL rasters) Grouped;
sourceId/itemare unused. Pass provider keys inparameters:rasterid(required): table/raster to drawsrs(used only ifcrsarg is empty)time(optional range string"start\end", either side optional)
-
MIKECore (DFS2/DFSU)
crsmust be"EPSG:3857"(throws otherwise)sourceId= file name when the provider was constructed with a directory; empty if constructed with a fileitem= 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>
×tamp=<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×tamp=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 (
srsvscrs, axis order). - In GetMaps,
parameters["crs"]is used; in GetMap, passcrsargument. - Time param uses 12-hour
hh. If your server expectsHH, customize your template/placeholder.
- Use WMS (not WFS/WMS-PNG mixups). Keep your template consistent with server version (
-
MCLite
- Render/time/stream are PostgreSQL-only; SQLite/SQL Server throw
NotSupportedException. - Required provider key:
rasterid.crswins overparameters["srs"]. - Returns null if view doesn’t intersect the raster overview envelope—handle that in callers.
- Render/time/stream are PostgreSQL-only; SQLite/SQL Server throw
-
MIKECore
- Strict
EPSG:3857only; anything else throws. Convert upstream. itemcan 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).
- Strict
-
PostgreSQL MapStyles
- Table bootstrap creates
public.map_styleif missing; it won’t create schemas for you. - Use a least-privilege DB role; rely on pooling (Npgsql default).
- Table bootstrap creates