From 66a51906ef991a32624544b93c617307fd387e99 Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Wed, 21 Jan 2026 22:33:05 +0100 Subject: [PATCH] Removed default User-Agent header. Using a library's default User-Agent violates OpenStreetMap's tile usage policy: https://operations.osmfoundation.org/policies/tiles/ --- MapControl/Shared/ImageLoader.cs | 16 +++----- SampleApps/AvaloniaApp/MainWindow.axaml | 2 +- SampleApps/AvaloniaApp/MainWindow.axaml.cs | 10 +++-- SampleApps/UniversalApp/MainPage.xaml | 2 +- SampleApps/UniversalApp/MainPage.xaml.cs | 10 +++-- SampleApps/WinUiApp/MainWindow.xaml | 2 +- SampleApps/WinUiApp/MainWindow.xaml.cs | 10 +++-- SampleApps/WpfApplication/MainWindow.xaml | 2 +- SampleApps/WpfApplication/MainWindow.xaml.cs | 39 +++++++++++++++++-- .../WpfApplication/WpfApplication.csproj | 4 ++ 10 files changed, 67 insertions(+), 30 deletions(-) diff --git a/MapControl/Shared/ImageLoader.cs b/MapControl/Shared/ImageLoader.cs index 44f00e60..425f78e4 100644 --- a/MapControl/Shared/ImageLoader.cs +++ b/MapControl/Shared/ImageLoader.cs @@ -23,19 +23,15 @@ namespace MapControl /// /// The System.Net.Http.HttpClient instance used to download images. + /// An application should add a unique User-Agent value to the DefaultRequestHeaders of this + /// HttpClient instance (or the Headers of a HttpRequestMessage used in a HttpMessageHandler). + /// Failing to set a unique User-Agent value is a violation of OpenStreetMap's tile usage policy + /// (see https://operations.osmfoundation.org/policies/tiles/) and results in blocked access + /// to their tile servers. /// public static HttpClient HttpClient { - get - { - if (field == null) - { - field = new HttpClient { Timeout = TimeSpan.FromSeconds(10) }; - field.DefaultRequestHeaders.Add("User-Agent", $"XAML-Map-Control/{typeof(ImageLoader).Assembly.GetName().Version}"); - } - - return field; - } + get => field ??= new HttpClient { Timeout = TimeSpan.FromSeconds(10) }; set; } diff --git a/SampleApps/AvaloniaApp/MainWindow.axaml b/SampleApps/AvaloniaApp/MainWindow.axaml index 850a885b..559c7796 100644 --- a/SampleApps/AvaloniaApp/MainWindow.axaml +++ b/SampleApps/AvaloniaApp/MainWindow.axaml @@ -154,7 +154,7 @@ diff --git a/SampleApps/AvaloniaApp/MainWindow.axaml.cs b/SampleApps/AvaloniaApp/MainWindow.axaml.cs index 9a4b023f..72890242 100644 --- a/SampleApps/AvaloniaApp/MainWindow.axaml.cs +++ b/SampleApps/AvaloniaApp/MainWindow.axaml.cs @@ -13,12 +13,14 @@ namespace SampleApplication { public MainWindow() { + ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Avalonia Sample Application"); + var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug().SetMinimumLevel(LogLevel.Information)); ImageLoader.LoggerFactory = loggerFactory; - //var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); - //TileImageLoader.Cache = tileCache; - //Closed += (s, e) => tileCache.Dispose(); + var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); + TileImageLoader.Cache = tileCache; + Closed += (s, e) => tileCache.Dispose(); InitializeComponent(); AddTestLayers(); @@ -95,7 +97,7 @@ namespace SampleApplication if (start != null) { - measurementLine.Locations = LocationCollection.OrthodromeLocations(start, location); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } } diff --git a/SampleApps/UniversalApp/MainPage.xaml b/SampleApps/UniversalApp/MainPage.xaml index 7aae2766..58f2bb7e 100644 --- a/SampleApps/UniversalApp/MainPage.xaml +++ b/SampleApps/UniversalApp/MainPage.xaml @@ -210,7 +210,7 @@ diff --git a/SampleApps/UniversalApp/MainPage.xaml.cs b/SampleApps/UniversalApp/MainPage.xaml.cs index 2ae5b253..8dfb7141 100644 --- a/SampleApps/UniversalApp/MainPage.xaml.cs +++ b/SampleApps/UniversalApp/MainPage.xaml.cs @@ -16,12 +16,14 @@ namespace SampleApplication { public MainPage() { + ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control UWP Sample Application"); + var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug().SetMinimumLevel(LogLevel.Information)); ImageLoader.LoggerFactory = loggerFactory; - //var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); - //TileImageLoader.Cache = tileCache; - //Unloaded += (s, e) => tileCache.Dispose(); + var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); + TileImageLoader.Cache = tileCache; + Unloaded += (s, e) => tileCache.Dispose(); InitializeComponent(); AddTestLayers(); @@ -93,7 +95,7 @@ namespace SampleApplication if (start != null) { - measurementLine.Locations = LocationCollection.OrthodromeLocations(start, location); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } } diff --git a/SampleApps/WinUiApp/MainWindow.xaml b/SampleApps/WinUiApp/MainWindow.xaml index 5e0eb331..036f9a51 100644 --- a/SampleApps/WinUiApp/MainWindow.xaml +++ b/SampleApps/WinUiApp/MainWindow.xaml @@ -235,7 +235,7 @@ diff --git a/SampleApps/WinUiApp/MainWindow.xaml.cs b/SampleApps/WinUiApp/MainWindow.xaml.cs index 2e11119e..f4764a78 100644 --- a/SampleApps/WinUiApp/MainWindow.xaml.cs +++ b/SampleApps/WinUiApp/MainWindow.xaml.cs @@ -16,12 +16,14 @@ namespace SampleApplication { public MainWindow() { + ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control WinUI Sample Application"); + var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug().SetMinimumLevel(LogLevel.Information)); ImageLoader.LoggerFactory = loggerFactory; - //var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); - //TileImageLoader.Cache = tileCache; - //Closed += (s, e) => tileCache.Dispose(); + var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); + TileImageLoader.Cache = tileCache; + Closed += (s, e) => tileCache.Dispose(); InitializeComponent(); AddTestLayers(); @@ -94,7 +96,7 @@ namespace SampleApplication if (start != null) { - measurementLine.Locations = LocationCollection.OrthodromeLocations(start, location); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } } diff --git a/SampleApps/WpfApplication/MainWindow.xaml b/SampleApps/WpfApplication/MainWindow.xaml index 77617a56..6ab76a16 100644 --- a/SampleApps/WpfApplication/MainWindow.xaml +++ b/SampleApps/WpfApplication/MainWindow.xaml @@ -212,7 +212,7 @@ diff --git a/SampleApps/WpfApplication/MainWindow.xaml.cs b/SampleApps/WpfApplication/MainWindow.xaml.cs index 206f0536..597c84b6 100644 --- a/SampleApps/WpfApplication/MainWindow.xaml.cs +++ b/SampleApps/WpfApplication/MainWindow.xaml.cs @@ -10,16 +10,43 @@ using System.Windows.Input; namespace SampleApplication { + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + class HttpHandler : DelegatingHandler + { + public HttpHandler() +#if NET + : base(new SocketsHttpHandler()) +#else + : base(new HttpClientHandler()) +#endif + { + } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + Debug.WriteLine(request.RequestUri); + + return base.SendAsync(request, cancellationToken); + } + } + public partial class MainWindow : Window { public MainWindow() { + var httpClient = new HttpClient(new HttpHandler()) { Timeout = TimeSpan.FromSeconds(10) }; + httpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Avalonia Sample Application"); + ImageLoader.HttpClient = httpClient; + var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug().SetMinimumLevel(LogLevel.Information)); ImageLoader.LoggerFactory = loggerFactory; - //var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); - //TileImageLoader.Cache = tileCache; - //Closed += (s, e) => tileCache.Dispose(); + var tileCache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder, loggerFactory); + TileImageLoader.Cache = tileCache; + Closed += (s, e) => tileCache.Dispose(); InitializeComponent(); AddTestLayers(); @@ -43,6 +70,10 @@ namespace SampleApplication { map.TargetCenter = map.ViewToLocation(e.GetPosition(map)); } + else if (Keyboard.Modifiers.HasFlag(ModifierKeys.Shift)) + { + map.ProjectionCenter = map.ViewToLocation(e.GetPosition(map)); + } else if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && map.MapLayer is WmsImageLayer wmsLayer) { @@ -83,7 +114,7 @@ namespace SampleApplication if (start != null) { - measurementLine.Locations = LocationCollection.OrthodromeLocations(start, location); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } } diff --git a/SampleApps/WpfApplication/WpfApplication.csproj b/SampleApps/WpfApplication/WpfApplication.csproj index 462dc57d..0765ed41 100644 --- a/SampleApps/WpfApplication/WpfApplication.csproj +++ b/SampleApps/WpfApplication/WpfApplication.csproj @@ -25,6 +25,10 @@ + + + +