DHI.Services.GeoServer for GIS Maps — Internal Developer Guide (WMS → SKBitmap)¶
Audience: devs using
DHI.Services.GIS.Mapswith GeoServer (WMS). For placeholders/auth/time/CRS details, see GeoServer Core.
What this provider gives you¶
MapSource— calls GeoServer WMS and decodes the image into anSKBitmap.MapStyleRepository— manages styles via GeoServer REST/rest/styles.
The package also ships the GIS features repo; see the GIS doc for vectors.
Capabilities & limitations¶
| Operation / Area | Support | Notes |
|---|---|---|
MapSource.GetMap |
✓ | Renders a single WMS image. |
MapSource.GetMaps |
✓ | Batch by Dictionary<DateTime,string>; CRS read from parameters["crs"] (default EPSG:4326). |
MapSource.GetDateTimes |
✗ | Not implemented. |
Styles: Get/Contains/… |
✓ | Backed by REST /rest/styles. |
Styles: Add |
✓ | Either StyleFile=.zip (application/zip) or StyleCode (SLD application/vnd.ogc.sld+xml). |
Styles: Update/Remove |
✓ | PUT/DELETE to REST endpoints. |
| Auth | ✓ | Basic Auth; static HttpClient with global Authorization header. |
| Time | ✓ | Appended as &time=yyyy-MM-ddThh:mm:ss.fffZ (12-hour hh). |
| Tokens | ✓ | [group], [layer], [width], [height], [boundingbox], [crs] (added if missing), [mapstyle]. |
Name vs Id (styles): WMS inserts
MapStyle.Nameinto[mapstyle]. KeepNameequal to the GeoServer style you want.
Your WMS query template (tokens)¶
Example (WMS 1.1.0 – srs):
[group]/wms?service=WMS&version=1.1.0&request=GetMap
&format=image/png
&layers=[group]:[layer]
&bbox=[boundingbox]
&width=[width]&height=[height]
&srs=[crs] // or &crs=[crs] for WMS 1.3.0
&styles=[mapstyle]
Axis order and srs vs crs depend on your WMS version. Keep template consistent with your server.
Using via the Core MapService¶
Single render¶
var mapSvc = new DHI.Services.GIS.Maps.MapService(mapSource, styleSvc /* optional */);
var bbox = BoundingBox.Parse("8,54,13,58");
using var bmp = mapSvc.GetMap(
style: "coast-sld", // Id if style repo plugged in; else treated as StyleCode
crs: "EPSG:4326",
boundingBox: bbox,
width: 1024, height: 768,
sourceId: "myWorkspace", // → [group]
dateTime: null,
item: "coastline", // → [layer]
parameters: DHI.Services.Parameters.Empty);
Time stack (batch)¶
var timeSteps = new Dictionary<DateTime, string> {
[new DateTime(2020,10,21,10,0,0, DateTimeKind.Utc)] = "coastline",
[new DateTime(2020,10,21,11,0,0, DateTimeKind.Utc)] = "coastline"
};
var frames = mapSvc.GetMaps(
style: "coast-sld",
boundingBox: bbox,
size: new SKSizeI(1024, 768),
timeSteps: timeSteps,
item: "myWorkspace", // In this provider, this 'item' arg maps to [group]
parameters: new Parameters { { "crs", "EPSG:4326" } }); // GetMaps reads CRS from parameters
Parameter mapping (watch this):
GetMap:sourceId → [group],item → [layer].GetMaps: the dictionary value is[layer], and the finalitemargument is used as[group].
Wiring¶
A) Connections (WebApi hosts)¶
"geo-map": {
"$type": "DHI.Services.GIS.WebApi.MapServiceConnection, DHI.Services.GIS.WebApi",
"MapSourceConnectionString": "BaseUrl=http://localhost:8080/geoserver/;Query=[group]/wms?service=WMS&version=1.1.0&request=GetMap&format=image/png&layers=[group]:[layer]&bbox=[boundingbox]&width=[width]&height=[height]&srs=[crs];UserName=admin;Password=geoserver",
"MapSourceType": "DHI.Services.Provider.GeoServer.MapSource, DHI.Services.Provider.GeoServer",
"MapStyleConnectionString": "BaseUrl=http://localhost:8080/geoserver/;UserName=admin;Password=geoserver",
"MapStyleRepositoryType": "DHI.Services.Provider.GeoServer.MapStyleRepository, DHI.Services.Provider.GeoServer",
"Name": "GeoServer WMS",
"Id": "geo-map"
}
After startup, an example request:
GET /api/maps?request=GetMap&service=wms&version=1.3.0
&width=1024&height=768
&styles=coast-sld
&layers=geo-map
&crs=EPSG:4326
&bbox=8,54,13,58
&item=coastline
B) Programmatic¶
var styleSvc = new DHI.Services.GIS.Maps.MapStyleService(
new DHI.Services.Provider.GeoServer.MapStyleRepository(
baseUrl: "https://my.geoserver/geoserver/", userName: "admin", password: "geoserver"));
var query =
"[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]";
var mapSource = new DHI.Services.Provider.GeoServer.MapSource(
baseUrl: "https://my.geoserver/geoserver/",
query: query,
userName: "admin", password: "geoserver");
ServiceLocator.Register(new DHI.Services.GIS.Maps.MapService(mapSource, styleSvc), "geo-map");
Managing styles¶
// Add via SLD string
styleSvc.Add(new MapStyle("coast-sld", "Coastline (SLD)") {
StyleCode = File.ReadAllText(@"C:\styles\coastline.sld")
});
// Or via zipped style package
styleSvc.Add(new MapStyle("rain", "Rain SLD") {
StyleFile = @"C:\styles\rain.zip" // must be .zip
});
// Get / Contains / Count / Update / Remove
var ok = styleSvc.Contains("coast-sld");
var one = styleSvc.Get("coast-sld"); // Maybe<MapStyle>
var cnt = styleSvc.Count();
styleSvc.Update(new MapStyle("coast-sld", "Coastline (updated)") { StyleCode = "<new sld xml>" });
styleSvc.Remove("coast-sld");
Notes (matching code)
MapStyleRepository.Get(id)calls/rest/styles/{id}.json(i.e.,{id}.json).Remove/Updatetarget/rest/styles/{id}(no.json).Addrequires eitherStyleFile(.zip) orStyleCode(SLD). If both empty, it throws.
Troubleshooting¶
- Blank/gray image — check axis order vs WMS version and
srs/crsname; ensure layer is visible at that scale. - Style not applied — WMS uses
MapStyle.Name; make sure it matches the GeoServer style name exactly. - CRS ignored in batch —
GetMapsreads CRS fromparameters["crs"]. - Time not honored — confirm layer supports
&time=and your server acceptshh(12-hour).
Design notes (under the hood)¶
MapSourcebuilds the query via string replacement; if[crs]is absent, it appends&crs=<value>.- On
DateTime, appends&time=yyyy-MM-ddThh:mm:ss.fffZ(12-hour). - Static
HttpClientwith globalAuthorization. Avoid mixing hosts/creds.
Copy-paste snippets¶
Minimal map endpoint (ASP.NET Core)
[HttpGet("map")]
public IActionResult GetMap([FromQuery] double xmin, double ymin, double xmax, double ymax)
{
var src = new MapSource(
"http://localhost/geoserver/",
"[group]/wms?service=WMS&version=1.1.0&request=GetMap&format=image/png&layers=[group]:[layer]&bbox=[boundingbox]&width=[width]&height=[height]&srs=[crs]",
"admin", "geoserver");
var bmp = src.GetMap(
new MapStyle("default","default"), "EPSG:4326",
new BoundingBox(xmin,ymin,xmax,ymax), 800, 400,
"topp", null, "states", Parameters.Empty);
using var image = bmp.Encode(SKEncodedImageFormat.Png, 90);
return File(image.ToArray(), "image/png");
}
Final navigation¶
- Core: placeholders, auth, time/CRS, shared behavior → GeoServer Core
- GIS (features/WFS): this page
- GIS.Maps (raster/WMS): the Maps page above