Azure Maps 搜索 .NET
Azure Maps (.NET)
Azure Maps .NET SDK 提供基于位置的服务:地理编码、路由、渲染、地理定位和天气。
安装
# Search (地理编码、逆地理编码)
dotnet add package Azure.Maps.Search --prerelease
Routing (路线规划、路由矩阵)
dotnet add package Azure.Maps.Routing --prerelease
Rendering (地图瓦片、静态图像)
dotnet add package Azure.Maps.Rendering --prerelease
Geolocation (IP 定位)
dotnet add package Azure.Maps.Geolocation --prerelease
Weather (天气)
dotnet add package Azure.Maps.Weather --prerelease
Resource Management (账户管理、SAS 令牌)
dotnet add package Azure.ResourceManager.Maps --prerelease
身份验证必需
dotnet add package Azure.Identity当前版本:
Azure.Maps.Search: v2.0.0-beta.5
Azure.Maps.Routing: v1.0.0-beta.4
Azure.Maps.Rendering: v2.0.0-beta.1
Azure.Maps.Geolocation: v1.0.0-beta.3
Azure.ResourceManager.Maps: v1.1.0-beta.2
环境变量
AZURE_MAPS_SUBSCRIPTION_KEY=<your-subscription-key>
AZURE_MAPS_CLIENT_ID=<your-client-id> # 用于 Entra ID 认证身份验证
订阅密钥 (共享密钥)
using Azure;
using Azure.Maps.Search;
var subscriptionKey = Environment.GetEnvironmentVariable("AZURE_MAPS_SUBSCRIPTION_KEY");
var credential = new AzureKeyCredential(subscriptionKey);
var client = new MapsSearchClient(credential);
Microsoft Entra ID (生产环境推荐)
using Azure.Identity;
using Azure.Maps.Search;
var credential = new DefaultAzureCredential();
var clientId = Environment.GetEnvironmentVariable("AZURE_MAPS_CLIENT_ID");
var client = new MapsSearchClient(credential, clientId);
共享访问签名 (SAS)
using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Maps;
using Azure.ResourceManager.Maps.Models;
using Azure.Maps.Search;
// 使用 Azure Resource Manager 进行身份验证
ArmClient armClient = new ArmClient(new DefaultAzureCredential());
// 获取 Maps 账户资源
ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(
subscriptionId, resourceGroupName, accountName);
MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId);
// 生成 SAS 令牌
MapsAccountSasContent sasContent = new MapsAccountSasContent(
MapsSigningKey.PrimaryKey,
principalId,
maxRatePerSecond: 500,
start: DateTime.UtcNow.ToString("O"),
expiry: DateTime.UtcNow.AddDays(1).ToString("O"));
Response<MapsAccountSasToken> sas = mapsAccount.GetSas(sasContent);
// 使用 SAS 令牌创建客户端
var sasCredential = new AzureSasCredential(sas.Value.AccountSasToken);
var client = new MapsSearchClient(sasCredential);
客户端层级
Azure.Maps.Search
└── MapsSearchClient
├── GetGeocoding() → 地址地理编码
├── GetGeocodingBatch() → 批量地理编码
├── GetReverseGeocoding() → 坐标转地址 (逆地理编码)
├── GetReverseGeocodingBatch() → 批量逆地理编码
└── GetPolygon()Azure.Maps.Routing
└── MapsRoutingClient
├── GetDirections() → 路线指引
├── GetImmediateRouteMatrix() → 路线矩阵 (同步, ≤100)
├── GetRouteMatrix() → 路线矩阵 (异步, ≤700)
└── GetRouteRange() → 等时线/可达范围
Azure.Maps.Rendering
└── MapsRenderingClient
├── GetMapTile() → 地图瓦片
├── GetMapStaticImage() → 静态地图图像
└── GetCopyrightCaption() → 版权信息
Azure.Maps.Geolocation
└── MapsGeolocationClient
└── GetCountryCode() → IP 转国家/地区
Azure.Maps.Weather
└── MapsWeatherClient
├── GetCurrentWeatherConditions() → 当前天气
├── GetDailyForecast() → 每日预报
├── GetHourlyForecast() → 每小时预报
└── GetSevereWeatherAlerts() → 恶劣天气警报
## 核心工作流
1. 地理编码 (地址转坐标)
var credential = new AzureKeyCredential(subscriptionKey);
var client = new MapsSearchClient(credential);
Response<GeocodingResponse> result = client.GetGeocoding("1 Microsoft Way, Redmond, WA 98052");
foreach (var feature in result.Value.Features)
{
Console.WriteLine($"Coordinates: {string.Join(",", feature.Geometry.Coordinates)}");
Console.WriteLine($"Address: {feature.Properties.Address.FormattedAddress}");
Console.WriteLine($"Confidence: {feature.Properties.Confidence}");
}
### 2. 批量地理编码using Azure.Maps.Search.Models.Queries;
List<GeocodingQuery> queries = new List<GeocodingQuery>
{
new GeocodingQuery() { Query = "400 Broad St, Seattle, WA" },
new GeocodingQuery() { Query = "1 Microsoft Way, Redmond, WA" },
new GeocodingQuery() { AddressLine = "Space Needle", Top = 1 },
};
Response<GeocodingBatchResponse> results = client.GetGeocodingBatch(queries);
foreach (var batchItem in results.Value.BatchItems)
{
foreach (var feature in batchItem.Features)
{
Console.WriteLine($"Coordinates: {string.Join(",", feature.Geometry.Coordinates)}");
}
}
### 3. 逆地理编码 (坐标转地址)using Azure.Core.GeoJson;
GeoPosition coordinates = new GeoPosition(-122.138685, 47.6305637);
Response<GeocodingResponse> result = client.GetReverseGeocoding(coordinates);
foreach (var feature in result.Value.Features)
{
Console.WriteLine($"Address: {feature.Properties.Address.FormattedAddress}");
Console.WriteLine($"Locality: {feature.Properties.Address.Locality}");
}
### 4. 获取边界多边形using Azure.Maps.Search.Models;
GetPolygonOptions options = new GetPolygonOptions()
{
Coordinates = new GeoPosition(-122.204141, 47.61256),
ResultType = BoundaryResultTypeEnum.Locality,
Resolution = ResolutionEnum.Small,
};
Response<Boundary> result = client.GetPolygon(options);
Console.WriteLine($"Boundary copyright: {result.Value.Properties?.Copyright}");
Console.WriteLine($"Polygon count: {result.Value.Geometry.Count}");
### 5. 路线指引using Azure;
using Azure.Core.GeoJson;
using Azure.Maps.Routing;
using Azure.Maps.Routing.Models;
var client = new MapsRoutingClient(new AzureKeyCredential(subscriptionKey));
List<GeoPosition> routePoints = new List<GeoPosition>()
{
new GeoPosition(-122.34, 47.61), // 西雅图
new GeoPosition(-122.13, 47.64)
// Redmond
};
RouteDirectionQuery query = new RouteDirectionQuery(routePoints);
Response<RouteDirections> result = client.GetDirections(query);
foreach (var route in result.Value.Routes)
{
Console.WriteLine($"Distance: {route.Summary.LengthInMeters} meters");
Console.WriteLine($"Duration: {route.Summary.TravelTimeDuration}");
foreach (RouteLeg leg in route.Legs)
{
Console.WriteLine($"Leg points: {leg.Points.Count}");
}
}
6. 带选项的路线方向 (Route Directions with Options)
RouteDirectionOptions options = new RouteDirectionOptions()
{
RouteType = RouteType.Fastest,
UseTrafficData = true,
TravelMode = TravelMode.Bicycle,
Language = RoutingLanguage.EnglishUsa,
InstructionsType = RouteInstructionsType.Text,
};
RouteDirectionQuery query = new RouteDirectionQuery(routePoints)
{
RouteDirectionOptions = options
};
Response<RouteDirections> result = client.GetDirections(query);
7. 路线矩阵 (Route Matrix)
RouteMatrixQuery routeMatrixQuery = new RouteMatrixQuery
{
Origins = new List<GeoPosition>()
{
new GeoPosition(-122.34, 47.61),
new GeoPosition(-122.13, 47.64)
},
Destinations = new List<GeoPosition>()
{
new GeoPosition(-122.20, 47.62),
new GeoPosition(-122.40, 47.65)
},
};
// 同步请求(最多 100 组路线组合)
Response<RouteMatrixResult> result = client.GetImmediateRouteMatrix(routeMatrixQuery);
foreach (var cell in result.Value.Matrix.SelectMany(row => row))
{
Console.WriteLine($"Distance: {cell.Response?.RouteSummary?.LengthInMeters}");
Console.WriteLine($"Duration: {cell.Response?.RouteSummary?.TravelTimeDuration}");
}
// 异步请求(最多 700 组路线组合)
RouteMatrixOptions routeMatrixOptions = new RouteMatrixOptions(routeMatrixQuery)
{
TravelTimeType = TravelTimeType.All,
};
GetRouteMatrixOperation asyncResult = client.GetRouteMatrix(WaitUntil.Completed, routeMatrixOptions);
8. 路线范围/等时线 (Route Range/Isochrone)
RouteRangeOptions options = new RouteRangeOptions(-122.34, 47.61)
{
TimeBudget = new TimeSpan(0, 20, 0) // 20 分钟
};
Response<RouteRangeResult> result = client.GetRouteRange(options);
// result.Value.ReachableRange 包含多边形数据
Console.WriteLine($"Boundary points: {result.Value.ReachableRange.Boundary.Count}");
9. 获取地图瓦片 (Get Map Tiles)
using Azure;
using Azure.Maps.Rendering;
var client = new MapsRenderingClient(new AzureKeyCredential(subscriptionKey));
int zoom = 10;
int tileSize = 256;
// 将坐标转换为瓦片索引
MapTileIndex tileIndex = MapsRenderingClient.PositionToTileXY(
new GeoPosition(13.3854, 52.517), zoom, tileSize);
// 获取地图瓦片
GetMapTileOptions options = new GetMapTileOptions(
MapTileSetId.MicrosoftImagery,
new MapTileIndex(tileIndex.X, tileIndex.Y, zoom)
);
Response<Stream> mapTile = client.GetMapTile(options);
// 保存到文件
using (FileStream fileStream = File.Create("./MapTile.png"))
{
mapTile.Value.CopyTo(fileStream);
}
10. IP 地理位置 (IP Geolocation)
using System.Net;
using Azure;
using Azure.Maps.Geolocation;
var client = new MapsGeolocationClient(new AzureKeyCredential(subscriptionKey));
IPAddress ipAddress = IPAddress.Parse("2001:4898:80e8:b::189");
Response<CountryRegionResult> result = client.GetCountryCode(ipAddress);
Console.WriteLine($"Country ISO Code: {result.Value.IsoCode}");
11. 当前天气 (Current Weather)
using Azure;
using Azure.Core.GeoJson;
usingvar client = new MapsWeatherClient(new AzureKeyCredential(subscriptionKey));
var position = new GeoPosition(-122.13071, 47.64011);
var options = new GetCurrentWeatherConditionsOptions(position);
Response<CurrentConditionsResult> result = client.GetCurrentWeatherConditions(options);
foreach (var condition in result.Value.Results)
{
Console.WriteLine($"Temperature: {condition.Temperature.Value} {condition.Temperature.Unit}");
Console.WriteLine($"Weather: {condition.Phrase}");
Console.WriteLine($"Humidity: {condition.RelativeHumidity}%");
}
## 关键类型参考
Search 包
| 类型 | 用途 |
|------|---------|
| MapsSearchClient | 搜索操作的主客户端 |
| GeocodingResponse | 地理编码结果 |
| GeocodingBatchResponse | 批量地理编码结果 |
| GeocodingQuery | 批量地理编码查询 |
| ReverseGeocodingQuery | 批量逆地理编码查询 |
| GetPolygonOptions | 多边形检索选项 |
| Boundary | 边界多边形结果 |
| BoundaryResultTypeEnum | 边界类型(Locality, AdminDistrict 等) |
| ResolutionEnum | 多边形分辨率(Small, Medium, Large) |
Routing 包
| 类型 | 用途 |
|------|---------|
| MapsRoutingClient | 路由操作的主客户端 |
| RouteDirectionQuery | 路线方向查询 |
| RouteDirectionOptions | 路线计算选项 |
| RouteDirections | 路线方向结果 |
| RouteLeg | 路线分段 |
| RouteMatrixQuery | 路由矩阵查询 |
| RouteMatrixResult | 路由矩阵结果 |
| RouteRangeOptions | 等时线选项 |
| RouteRangeResult | 等时线结果 |
| RouteType | 路线类型(Fastest, Shortest, Eco, Thrilling) |
| TravelMode | 旅行模式(Car, Truck, Bicycle, Pedestrian) |
Rendering 包
| 类型 | 用途 |
|------|---------|
| MapsRenderingClient | 渲染主客户端 |
| GetMapTileOptions | 地图瓦片选项 |
| MapTileIndex | 瓦片坐标 (X, Y, Zoom) |
| MapTileSetId | 瓦片集标识符 |
通用类型
| 类型 | 用途 |
|------|---------|
| GeoPosition | 地理位置(经度,纬度) |
| GeoBoundingBox | 地理区域的边界框 |
最佳实践
1. 生产环境使用 Entra ID — 优先于订阅密钥
2. 批量操作 — 针对多个地址使用批量地理编码
3. 缓存结果 — 地理编码结果不会频繁更改
4. 使用合适的瓦片尺寸 — 根据显示设备选择 256 或 512 像素
5. 处理速率限制 — 实现指数退避机制
6. 使用异步路由矩阵 — 适用于大规模矩阵计算(>100)
7. 考虑交通数据 — 设置 UseTrafficData = true 以获得准确的预计到达时间 (ETA)
错误处理
相关 SDK
| SDK | 用途 | 安装 |
|-----|---------|---------|
|
Azure.Maps.Search | 地理编码、搜索 | dotnet add package Azure.Maps.Search --prerelease |
| Azure.Maps.Routing | 路线方向、矩阵 | dotnet add package Azure.Maps.Routing --prerelease |
Routing --prerelease ||
Azure.Maps.Rendering | 地图瓦片、图像 | dotnet add package Azure.Maps.Rendering --prerelease ||
Azure.Maps.Geolocation | IP 地理位置 | dotnet add package Azure.Maps.Geolocation --prerelease ||
Azure.Maps.Weather | 天气数据 | dotnet add package Azure.Maps.Weather --prerelease ||
Azure.ResourceManager.Maps | 账户管理 | dotnet add package Azure.ResourceManager.Maps --prerelease |
参考链接
| 资源 | URL |
|----------|-----|
| Azure Maps 文档 | https://learn.microsoft.com/azure/azure-maps/ |
| Search API 参考 | https://learn.microsoft.com/dotnet/api/azure.maps.search |
| Routing API 参考 | https://learn.microsoft.com/dotnet/api/azure.maps.routing |
| GitHub 源码 | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/maps |
| 价格 | https://azure.microsoft.com/pricing/details/azure-maps/ |
使用场景
本技能适用于执行概览中所描述的工作流或操作。局限性
- 仅在任务明确符合上述范围时使用此技能。
- 不要将输出结果视为针对特定环境的验证、测试或专家评审的替代方案。
- 如果缺少必要的输入、权限、安全边界或成功标准,请停止操作并寻求澄清。