GeoArtist 2.0.0
dotnet add package GeoArtist --version 2.0.0
NuGet\Install-Package GeoArtist -Version 2.0.0
<PackageReference Include="GeoArtist" Version="2.0.0" />
<PackageVersion Include="GeoArtist" Version="2.0.0" />
<PackageReference Include="GeoArtist" />
paket add GeoArtist --version 2.0.0
#r "nuget: GeoArtist, 2.0.0"
#:package GeoArtist@2.0.0
#addin nuget:?package=GeoArtist&version=2.0.0
#tool nuget:?package=GeoArtist&version=2.0.0
GeoArtist
A self-contained .NET component for rendering and editing GeoJSON on an OpenStreetMap map using Leaflet.
The project is designed as a plug&play component with out-of-the-box support for:
- ASP.NET Core (
TagHelper/ViewComponent) - WinForms Desktop (
WebView2)
Table of Contents
- Repository contents
- Features
- Project Structure
- Installation for ASP.NET Core
- Asset Loading
- Map and editor modes
- GeoMapOptions
- GeoEditorOptions
- JavaScript Runtime API
- Desktop Hosting
- Used Frameworks and Libraries
Repository contents
| Project | Description |
|---|---|
| GeoArtist | Production library: server-side GeoJSON handling, HTML/bootstrap rendering, modular JS runtime (Leaflet, Geoman) |
| Demos/WebView | ASP.NET Core demo host |
| Demos/Desktop | WinForms + WebView2 demo host |
Features
- ASP.NET Core
TagHelperandViewComponent - WinForms WebView2 adapter
- Shapes displaying and editing modes
- GeoJSON normalization to
FeatureCollection - SRID transformation support
- Leaflet + OpenStreetMap rendering
- Geoman integration
- Dynamic runtime updates from JavaScript API
Project Structure
GeoArtist
- Abstractions
- Contracts
- Core
- Hosting
- Rendering
- wwwroot
Demos
- WebView
- Desktop
Installation for ASP.NET Core
1. Add the component to your application as a project reference
<ProjectReference Include="..\GeoArtist\GeoArtist.csproj" />
2. Register services
Program.cs
using GeoArtist;
builder.Services.AddGeoArtist();
3. Add TagHelper import if you want to use the component as html tag
@addTagHelper *, GeoArtist
4. Render the component
@using GeoArtist.Contracts
<geo-map
map-id = "map-1"
geo-json = "@Model.GeoJson"
height = "400px"
include-assets = "true" />
@{ var mapOptions = new GeoMapOptions { MapId = "map-2", Height = "400px" };
var editorOptions = new GeoEditorOptions { SnapSensitivity = 10, UseGeoJsonTextArea = true }; }
<geo-map
mode = "editor"
map-options = "@mapOptions"
editor-options = "@editorOptions"
include-assets = "true" />
<geo-map mode="editor" />
mode="editor" is used to enable interactive editing (Leaflet-Geoman tools + component's editor pipeline).
Asset Loading
By default the component automatically emits the required CSS/JS assets:
- Leaflet CSS/JS
- GeoArtist CSS/JS
- Geoman CSS/JS (if editor mode)
Multiple component instances on one page:
- It's safe to use
include-assets="true"on all instances. Duplicates are filtered automatically per HTTP request. - Note that asset tags are still taken from the render result of each instance. Map mode doesn't include Geoman paths, so at least one editor instance on the page must keep
include-assets="true"to get Geoman loaded.
Map and editor modes
| Mode | Use case | Runtime/asset profile |
|---|---|---|
| Map | Display-only GeoJSON visualization | Lightweight profile. Leaflet + GeoArtist map runtime |
| Editor | Interactive drawing and geometry editing | Heavier profile. Adds Geoman CSS, JS and editor-specific pipeline |
GeoMapOptions
GeoMapOptions control map layout, Leaflet view, basic styling, and optional coordinate reprojection for the GeoArtist component. Providing options is not strictly required. Default values will be used for omitted options.
GeoEditorOptions
GeoEditorOptions define Geoman editor settings, available tools, edit modes, map/drawing behavior, UI scaling, synced GeoJSON textarea control.
Providing options is not strictly required. Default values will be used for omitted options. These settings apply when the component runs in editor mode (mode="editor" or RenderEditorAsync).
JavaScript Runtime API
The component exposes runtime methods on window.GeoArtist:
window.GeoArtist.UpdateGeoJson(geoJson);
window.GeoArtist.UpdateMapOptions(options);
window.GeoArtist.UpdateEditorOptions(options);
window.GeoArtist.ClearGeoJson();
The map instance is reused between updates.
Desktop Hosting
GeoArtist provides GeoDesktopWebViewAdapter and WebViewHostBridge in GeoArtist.Hosting.Desktop so a desktop host can drive WebView2 without reimplementing virtual-host setup, host.html navigation, or render messaging.
Installation
1. Add project reference
<ProjectReference Include="..\GeoArtist\GeoArtist.csproj" />
2. Register services
using GeoArtist;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddGeoArtistDesktop(options =>
{
// Optional host customization
// options.HostName = "geoartist.local";
});
using var serviceProvider = services.BuildServiceProvider();
3. Create the adapter on your main form
Inject the IServiceProvider into your main window and initialize the GeoDesktopWebViewAdapter using your WebView2 control instance.
using GeoArtist.Contracts;
using GeoArtist.Hosting.Desktop;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Web.WebView2.WinForms;
public partial class Form : Form
{
private readonly GeoDesktopWebViewAdapter _geoAdapter;
public Form(IServiceProvider services)
{
InitializeComponent();
// Resolve dependencies and bind to the WebView2 control
var bridge = services.GetRequiredService<WebViewHostBridge>();
var hostOptions = services.GetRequiredService<GeoDesktopHostOptions>();
_geoAdapter = new GeoDesktopWebViewAdapter(webView, bridge, hostOptions);
}
}
4. Initialize the host page
After the form is constructed, before the first render:
private async void Form_Load(object? sender, EventArgs e)
{
await _geoAdapter.EnsureReadyAsync();
}
5. Render the map
The adapter provides two methods to update the UI. Each call sends a fresh payload to the existing host.html and triggers GeoArtist.initialize, which rebuilds the layers or editor state from the supplied GeoJSON.
private async Task ShowMapAsync()
{
var mapOptions = new GeoMapOptions { MapId = "map-1", Height = "100%" };
await _geoAdapter.RenderMapAsync("""{"type":"FeatureCollection","features":[]}""", mapOptions);
}
private async Task ShowEditorAsync()
{
var mapOptions = new GeoMapOptions();
var editorOptions = new GeoEditorOptions { SnapSensitivity = 10, UseGeoJsonTextArea = true };
await _geoAdapter.RenderEditorAsync("""{"type":"FeatureCollection","features":[]}""", mapOptions, editorOptions);
}
The WebView document stays loaded for the lifetime of the host page. Each call refreshes the Leaflet layers from the payload and, in editor mode, rebuilds editor state—without navigating away from
host.html.
6. Disposal
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Cleanup the adapter and its internal WebView2 hooks
_geoAdapter.Dispose();
// Standard WinForms container for non-visual components (Timer, ImageList, etc.)
components?.Dispose();
}
base.Dispose(disposing);
}
Asset management & build workflow
The desktop adapter maps a virtual HTTPS origin to the wwwroot folder next to the host executable (AppContext.BaseDirectory).
How assets are served
- Source: static files ship with the
GeoArtistproject underGeoArtist/wwwroot/. - Deployment: building the host copies them into its output directory, usually
bin/<Configuration>/<TargetFramework>/wwwroot/(for WebView2 on Windows,<TargetFramework>is a*-windowsTFM). - Runtime: WebView2 loads
host.htmland dependencies from that output folder, not from the GeoArtist source tree.
Data flow
Server-side C# builds a GeoArtistPayload JSON in memory. WebViewHostBridge wraps it; GeoDesktopWebViewAdapter sends it with CoreWebView2.PostWebMessageAsJson to the page loaded from host.html when RenderMapAsync or RenderEditorAsync runs.
Used Frameworks and Libraries
- ASP.NET Core
- Razor (
TagHelper,ViewComponent) - NetTopologySuite
- ProjNET
- Leaflet
- Leaflet-Geoman
- OpenStreetMap
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net8.0-windows7.0 is compatible. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- NetTopologySuite (>= 2.6.0)
- NetTopologySuite.IO.GeoJSON (>= 4.0.0)
- ProjNET (>= 2.1.0)
-
net8.0-windows7.0
- NetTopologySuite (>= 2.6.0)
- NetTopologySuite.IO.GeoJSON (>= 4.0.0)
- ProjNET (>= 2.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0 | 147 | 4/16/2026 |