DHI.Services.MIKECore for GIS — Internal Developer Guide¶
This guide is the practical how-to for using the MIKECore GIS providers behind
DHI.Services.GIS. It explains what each provider returns, the exact ID grammar you pass in, how to wire them via connections or code. See also: MIKECore Providers for MIKECore details.
What these providers do¶
-
DFS2 → polygons (grid cells) Reads a single time slice from a DFS2 raster and returns one rectangle polygon per cell, with one attribute column per DFS item (float).
-
DFSU → polygons (mesh elements) Reads a DFSU unstructured mesh, returns one closed polygon per element, plus attributes for either all items or one selected item at a chosen time.
Both providers load via the common GisService<string> surface, so your app and Web API can treat them like any other GIS source.
Capabilities & limitations (at a glance)¶
| Operation | DFS2 | DFSU |
|---|---|---|
Get(id) (single collection) |
✓ (requires DateTime) |
✓ |
Get(id, associations, outSpatialReference) |
✓ but ignores both params | ✓ but ignores both params |
Get(id, filter, …) |
✗ (not implemented) | ✓ (method exists) but filter is ignored |
GetAll() |
✗ | ✓ (folder/prefix enumeration of *.dfsu) |
GetEnvelope / GetFootprint / GetIds(filter) |
✗ | ✗ |
| Bounding box filter | ✓ (BoundingBox=…) |
✓ (BoundingBox=…) |
| Per-feature edits | n/a (read model) | n/a (read model) |
Why are some methods “ignored”? The class overrides exist to satisfy the base interface, but the current implementations either don’t support those operations or always compute the full collection (e.g., DFSU doesn’t apply attribute filters yet).
How coordinates are produced¶
-
DFS2 (rotated grid aware) The repository reads the raster’s projection WKT + origin (lon/lat) + orientation and computes cell center coordinates in projected space. It then offsets centers to four corners to make rectangles. If
BoundingBoxis specified, a cell is kept only if all 4 corners are inside the box. -
DFSU (mesh) For each element, the provider builds a polygon from its node coordinates (
X,Y) and closes the ring (repeats the first node at the end). Elements are kept only if all vertices are inside theBoundingBox(strict containment).
outSpatialReferenceis currently accepted but not applied by either provider. You receive coordinates in the native space of the file.
Wiring options¶
A) Using the Connections module (recommended for Web API hosts)¶
Add entries to your connections.json:
"dfs2": {
"$type": "DHI.Services.GIS.WebApi.GisServiceConnection, DHI.Services.GIS.WebApi",
"ConnectionString": "[AppData]dfs2\\R20141001.dfs2",
"RepositoryType": "DHI.Services.Provider.MIKECore.Dfs2FeatureRepository, DHI.Services.Provider.MIKECore",
"Name": "DFS2 reader",
"Id": "dfs2"
},
"dfsu": {
"$type": "DHI.Services.GIS.WebApi.GisServiceConnection, DHI.Services.GIS.WebApi",
"ConnectionString": "[AppData]",
"RepositoryType": "DHI.Services.Provider.MIKECore.DfsuFeatureRepository, DHI.Services.Provider.MIKECore",
"Name": "DFSU reader",
"Id": "dfsu"
}
- For DFS2, the connection points to a specific file.
- For DFSU, the connection points to a folder root (after
[AppData]resolution). The provider will enumerate*.dfsuwhen you callGetAll().
Once registered, your Web API exposes GET /api/featurecollections/{connectionId}/{id} etc.
B) Programmatic registration¶
// DFS2: exact file
ServiceLocator.Register(
new GisService(
new DHI.Services.Provider.MIKECore.Dfs2FeatureRepository(@"C:\data\dfs2\R20141001.dfs2")
),
"dfs2"
);
// DFSU: folder or file prefix – provider can enumerate
ServiceLocator.Register(
new GisService(
new DHI.Services.Provider.MIKECore.DfsuFeatureRepository(@"C:\data\dfsu\")
),
"dfsu"
);
ID grammar (what you put in {id})¶
Both repositories accept a semicolon-separated set of key=value pairs. Keys are case-sensitive and values are culture-invariant (use . as decimal separator).
DFS2 (Dfs2FeatureCollectionId)¶
Required
DateTime=yyyy-MM-ddTHHmmssExact format (no colons in the time part). Example:2014-10-01T120000.
Optional
File=<path>If your connection already points at a specific file, you may omitFileand just pass theDateTime. If you include it, it is appended to the constructor’s prefix (folder/relative root). You may use\or/.BoundingBox=minX,minY,maxX,maxYFilters cells fully contained in the bbox. Example:BoundingBox=12.0,55.0,13.0,56.0.
Examples
DateTime=2014-10-01T120000
File=dfs2\R20141001.dfs2;DateTime=2014-10-01T000000
File=C:\data\R20141001.dfs2;DateTime=2014-10-01T120000;BoundingBox=12.0,55.0,13.0,56.0
If the timestamp doesn’t exist in the file, the repository throws “Matching datetime not found”.
DFSU (DfsuFeatureCollectionId)¶
Optional (but typical)
File=<path>Use when your connection is a folder/prefix. If the connection constructed with a file path,Filecan be omitted.Item=<item name>If omitted, all items are returned as separate attributes.DateTime=<timestamp>You can pass standardDateTime.Parse(...)values (e.g.,2021-09-20T00:00:00) or the compactyyyy-MM-ddTHHmmss. If omitted, the first time step (index 0) is used.BoundingBox=minX,minY,maxX,maxYKeeps only elements fully contained in the bbox.
Reserved (parsed but not used yet)
ContourIntervals=a,b,c→ parsed toList<double>, currently ignored by the repository.
Examples
File=mesh\my.dfsu;Item=Water Level;DateTime=2021-09-20T00:00:00
Item=Salinity
File=C:\data\mesh.dfsu;BoundingBox=12,55,13,56
Unknown keys throw (e.g., using
BBoxinstead ofBoundingBoxwill fail). Use the spellings above.
What a result looks like¶
DFS2¶
- Collection metadata:
Id="DFS2",Name="DFS2"(placeholder naming). - Attributes: one float attribute per DFS item (e.g.,
"Water Level","Wind U"). - Features: rectangle polygon per grid cell (4 corners computed from rotated grid).
- Filters applied: time slice required; optional strict
BoundingBoxcontainment.
DFSU¶
- Collection metadata:
Id=Path.GetFileNameWithoutExtension(file). - Attributes:
"Id"(1-based element index) + one float attribute per selected item (or all items ifItemomitted). - Features: closed polygon ring per element (first node repeated at end).
- Filters applied: optional strict
BoundingBoxcontainment;Item/DateTimeselection.
Example calls via the Web API¶
Assuming you registered the above connections and your host resolves
[AppData].
DFS2 — one time slice, with bbox
GET /api/featurecollections/dfs2/DateTime=2014-10-01T120000;BoundingBox=12.0,55.0,13.0,56.0?api-version=1
Authorization: Bearer <token>
DFSU — item + time
GET /api/featurecollections/dfsu/File=mesh%5Cmesh.dfsu;Item=Water%20Level;DateTime=2021-09-20T00:00:00?api-version=1
Authorization: Bearer <token>
DFSU — enumerate all files (server-side)
Use GetAll() programmatically (not an HTTP route by default):
var svc = Services.Get<GisService<string>>("dfsu");
foreach (var fc in svc.Repository.GetAll()) { /* ... */ }
Using from code (no Web API)¶
var dfs2 = new DHI.Services.Provider.MIKECore.Dfs2FeatureRepository(@"C:\data\dfs2\R20141001.dfs2");
var id = "DateTime=2014-10-01T120000;BoundingBox=12.0,55.0,13.0,56.0";
var fc = dfs2.Get(id, associations:false, outSpatialReference:null).Value;
// Inspect schema
foreach (var a in fc.Attributes) Console.WriteLine($"{a.Name} : {a.DataType.Name}");
// DFSU
var dfsu = new DHI.Services.Provider.MIKECore.DfsuFeatureRepository(@"C:\data\dfsu\");
var fcMesh = dfsu.Get("File=mesh.dfsu;Item=Water Level;DateTime=2021-09-20T00:00:00", associations:false).Value;
Bounding boxes: semantics & helpers¶
- Both providers interpret
BoundingBoxas full containment: a feature is included only if all its vertices are inside the rectangle. - Use the
DHI.Spatial.BoundingBox.Parse("xmin,ymin,xmax,ymax")helper when you build IDs programmatically. - Conversions for WebMercator are available on
BoundingBox(LonLatToGoogle(),GoogleToLonLat()) if you need to translate query UI inputs.
Common pitfalls & troubleshooting¶
- DFS2 DateTime format must be
yyyy-MM-ddTHHmmss(e.g.,2014-10-01T120000). Using colons (e.g.,T12:00:00) will fail to parse. Error:Could not parse id string '...'or laterMatching datetime not found. - DFSU unknown keys throw. Use
BoundingBox=..., notBBox=.... - Items in DFSU: If you pass
Item=...that doesn’t exist, you’ll get an exception listing valid names. - Large datasets: DFS2 grid → many polygons; DFSU large meshes → big payloads. Use
BoundingBoxand select a singleItemandDateTimewhen possible. - Projections: The
outSpatialReferenceparameter is ignored; you get file-native coordinates. - NotImplemented: Envelope, footprint, and certain list/id calls are intentionally unimplemented. Guard calls by provider type/capability.
Reference¶
Dfs2FeatureCollectionId/DfsuFeatureCollectionIdParse and holdFilePath,DateTime, optionalItem/BoundingBox.BoundingBoxImmutable(Xmin,Ymin,Xmax,Ymax)withParse,Contains(Position),Intersects, and WebMercator conversion helpers.FeatureCollection<string>HoldsFeaturesandAttributes(schema).GetInfo()yields metadata only.IGeometry&CoordinateReferenceSystemGeometry interfaces used by the GeoJSON converters (DHI.Spatial.GeoJson).
End-to-end recipe¶
- Register the connection(s) (see Connections section above).
- Build your ID string:
- DFS2:
DateTime=2014-10-01T120000;BoundingBox=12,55,13,56 - DFSU:
File=mesh\mesh.dfsu;Item=Water Level;DateTime=2021-09-20T00:00:00
- DFS2:
- Call
GET /api/featurecollections/{connectionId}/{id}(or use the service directly). - Serialize the result with the GeoJSON converters already included by
DHI.Services.GIS.WebApi.
That’s it. Plug in your UI, keep IDs precise, and lean on BoundingBox + Item/DateTime to keep payloads tight.