Azure Maps 搜索 .NET

azure-maps-search-dotnet
分类数据
作者Agentic Awesome Skills 社区
许可MIT
评分4.30/5
使用4.1K

Azure Maps (.NET)

Azure Maps .NET SDK 提供基于位置的服务:地理编码、路由、渲染、地理定位和天气。

安装

bash
# 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

环境变量

bash
AZURE_MAPS_SUBSCRIPTION_KEY=<your-subscription-key>
AZURE_MAPS_CLIENT_ID=<your-client-id>  # 用于 Entra ID 认证

身份验证

订阅密钥 (共享密钥)

csharp
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 (生产环境推荐)

csharp
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)

csharp
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);

客户端层级

code
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() → 恶劣天气警报

code
## 核心工作流

1. 地理编码 (地址转坐标)

csharp using Azure; using Azure.Maps.Search;

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}");
}

code
### 2. 批量地理编码
csharp
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)}");
}
}

code
### 3. 逆地理编码 (坐标转地址)
csharp
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}");
}

code
### 4. 获取边界多边形
csharp
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}");

code
### 5. 路线指引
csharp
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)

code
// 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)

csharp
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)

csharp
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)

csharp
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)

csharp
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)

csharp
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)

csharp
using Azure;
using Azure.Core.GeoJson;
using
Azure.Maps.Weather;

var 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}%");
}

code
## 关键类型参考

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)

错误处理

csharp try { Response<GeocodingResponse> result = client.GetGeocoding(address); } catch (RequestFailedException ex) { Console.WriteLine($"Status: {ex.Status}"); Console.WriteLine($"Error: {ex.Message}"); switch (ex.Status) { case 400: // 请求参数无效 break; case 401: // 身份验证失败 break; case 429: // 触发速率限制 - 实现退避机制 break; } } ``

相关 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/ |

使用场景

本技能适用于执行概览中所描述的工作流或操作。

局限性

  • 仅在任务明确符合上述范围时使用此技能。
  • 不要将输出结果视为针对特定环境的验证、测试或专家评审的替代方案。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止操作并寻求澄清。