refactor: flatten Microsoft skills from nested to flat directory structure
Rewrote sync_microsoft_skills.py (v4) to use each SKILL.md's frontmatter 'name' field as the flat directory name under skills/, replacing the nested skills/official/microsoft/<lang>/<category>/<service>/ hierarchy. This fixes CI failures caused by the indexing, validation, and catalog scripts expecting skills/<id>/SKILL.md (depth 1). Changes: - Rewrite scripts/sync_microsoft_skills.py for flat output with collision detection - Update scripts/tests/inspect_microsoft_repo.py for flat name mapping - Update scripts/tests/test_comprehensive_coverage.py for name uniqueness checks - Delete skills/official/ nested directory - Add 129 Microsoft skills as flat directories (e.g. skills/azure-mgmt-botservice-dotnet/) - Move attribution files to docs/ (LICENSE-MICROSOFT, microsoft-skills-attribution.json) - Rebuild skills_index.json, CATALOG.md, README.md (845 total skills)
This commit is contained in:
494
skills/azure-maps-search-dotnet/SKILL.md
Normal file
494
skills/azure-maps-search-dotnet/SKILL.md
Normal file
@@ -0,0 +1,494 @@
|
||||
---
|
||||
name: azure-maps-search-dotnet
|
||||
description: |
|
||||
Azure Maps SDK for .NET. Location-based services including geocoding, routing, rendering, geolocation, and weather. Use for address search, directions, map tiles, IP geolocation, and weather data. Triggers: "Azure Maps", "MapsSearchClient", "MapsRoutingClient", "MapsRenderingClient", "geocoding .NET", "route directions", "map tiles", "geolocation".
|
||||
package: Azure.Maps.Search
|
||||
---
|
||||
|
||||
# Azure Maps (.NET)
|
||||
|
||||
Azure Maps SDK for .NET providing location-based services: geocoding, routing, rendering, geolocation, and weather.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Search (geocoding, reverse geocoding)
|
||||
dotnet add package Azure.Maps.Search --prerelease
|
||||
|
||||
# Routing (directions, route matrix)
|
||||
dotnet add package Azure.Maps.Routing --prerelease
|
||||
|
||||
# Rendering (map tiles, static images)
|
||||
dotnet add package Azure.Maps.Rendering --prerelease
|
||||
|
||||
# Geolocation (IP to location)
|
||||
dotnet add package Azure.Maps.Geolocation --prerelease
|
||||
|
||||
# Weather
|
||||
dotnet add package Azure.Maps.Weather --prerelease
|
||||
|
||||
# Resource Management (account management, SAS tokens)
|
||||
dotnet add package Azure.ResourceManager.Maps --prerelease
|
||||
|
||||
# Required for authentication
|
||||
dotnet add package Azure.Identity
|
||||
```
|
||||
|
||||
**Current Versions**:
|
||||
- `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
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
AZURE_MAPS_SUBSCRIPTION_KEY=<your-subscription-key>
|
||||
AZURE_MAPS_CLIENT_ID=<your-client-id> # For Entra ID auth
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
### Subscription Key (Shared Key)
|
||||
|
||||
```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 (Recommended for Production)
|
||||
|
||||
```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);
|
||||
```
|
||||
|
||||
### Shared Access Signature (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;
|
||||
|
||||
// Authenticate with Azure Resource Manager
|
||||
ArmClient armClient = new ArmClient(new DefaultAzureCredential());
|
||||
|
||||
// Get Maps account resource
|
||||
ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(
|
||||
subscriptionId, resourceGroupName, accountName);
|
||||
MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId);
|
||||
|
||||
// Generate SAS token
|
||||
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);
|
||||
|
||||
// Create client with SAS token
|
||||
var sasCredential = new AzureSasCredential(sas.Value.AccountSasToken);
|
||||
var client = new MapsSearchClient(sasCredential);
|
||||
```
|
||||
|
||||
## Client Hierarchy
|
||||
|
||||
```
|
||||
Azure.Maps.Search
|
||||
└── MapsSearchClient
|
||||
├── GetGeocoding() → Geocode addresses
|
||||
├── GetGeocodingBatch() → Batch geocoding
|
||||
├── GetReverseGeocoding() → Coordinates to address
|
||||
├── GetReverseGeocodingBatch() → Batch reverse geocoding
|
||||
└── GetPolygon() → Get boundary polygons
|
||||
|
||||
Azure.Maps.Routing
|
||||
└── MapsRoutingClient
|
||||
├── GetDirections() → Route directions
|
||||
├── GetImmediateRouteMatrix() → Route matrix (sync, ≤100)
|
||||
├── GetRouteMatrix() → Route matrix (async, ≤700)
|
||||
└── GetRouteRange() → Isochrone/reachable range
|
||||
|
||||
Azure.Maps.Rendering
|
||||
└── MapsRenderingClient
|
||||
├── GetMapTile() → Map tiles
|
||||
├── GetMapStaticImage() → Static map images
|
||||
└── GetCopyrightCaption() → Copyright info
|
||||
|
||||
Azure.Maps.Geolocation
|
||||
└── MapsGeolocationClient
|
||||
└── GetCountryCode() → IP to country/region
|
||||
|
||||
Azure.Maps.Weather
|
||||
└── MapsWeatherClient
|
||||
├── GetCurrentWeatherConditions() → Current weather
|
||||
├── GetDailyForecast() → Daily forecast
|
||||
├── GetHourlyForecast() → Hourly forecast
|
||||
└── GetSevereWeatherAlerts() → Weather alerts
|
||||
```
|
||||
|
||||
## Core Workflows
|
||||
|
||||
### 1. Geocoding (Address to Coordinates)
|
||||
|
||||
```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}");
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Batch Geocoding
|
||||
|
||||
```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)}");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Reverse Geocoding (Coordinates to Address)
|
||||
|
||||
```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}");
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Get Boundary Polygon
|
||||
|
||||
```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}");
|
||||
```
|
||||
|
||||
### 5. Route Directions
|
||||
|
||||
```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), // Seattle
|
||||
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
|
||||
|
||||
```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)
|
||||
},
|
||||
};
|
||||
|
||||
// Synchronous (up to 100 route combinations)
|
||||
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}");
|
||||
}
|
||||
|
||||
// Asynchronous (up to 700 route combinations)
|
||||
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 minutes
|
||||
};
|
||||
|
||||
Response<RouteRangeResult> result = client.GetRouteRange(options);
|
||||
|
||||
// result.Value.ReachableRange contains the polygon
|
||||
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;
|
||||
|
||||
// Convert coordinates to tile index
|
||||
MapTileIndex tileIndex = MapsRenderingClient.PositionToTileXY(
|
||||
new GeoPosition(13.3854, 52.517), zoom, tileSize);
|
||||
|
||||
// Fetch map tile
|
||||
GetMapTileOptions options = new GetMapTileOptions(
|
||||
MapTileSetId.MicrosoftImagery,
|
||||
new MapTileIndex(tileIndex.X, tileIndex.Y, zoom)
|
||||
);
|
||||
|
||||
Response<Stream> mapTile = client.GetMapTile(options);
|
||||
|
||||
// Save to file
|
||||
using (FileStream fileStream = File.Create("./MapTile.png"))
|
||||
{
|
||||
mapTile.Value.CopyTo(fileStream);
|
||||
}
|
||||
```
|
||||
|
||||
### 10. 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}%");
|
||||
}
|
||||
```
|
||||
|
||||
## Key Types Reference
|
||||
|
||||
### Search Package
|
||||
|
||||
| Type | Purpose |
|
||||
|------|---------|
|
||||
| `MapsSearchClient` | Main client for search operations |
|
||||
| `GeocodingResponse` | Geocoding result |
|
||||
| `GeocodingBatchResponse` | Batch geocoding result |
|
||||
| `GeocodingQuery` | Query for batch geocoding |
|
||||
| `ReverseGeocodingQuery` | Query for batch reverse geocoding |
|
||||
| `GetPolygonOptions` | Options for polygon retrieval |
|
||||
| `Boundary` | Boundary polygon result |
|
||||
| `BoundaryResultTypeEnum` | Boundary type (Locality, AdminDistrict, etc.) |
|
||||
| `ResolutionEnum` | Polygon resolution (Small, Medium, Large) |
|
||||
|
||||
### Routing Package
|
||||
|
||||
| Type | Purpose |
|
||||
|------|---------|
|
||||
| `MapsRoutingClient` | Main client for routing operations |
|
||||
| `RouteDirectionQuery` | Query for route directions |
|
||||
| `RouteDirectionOptions` | Route calculation options |
|
||||
| `RouteDirections` | Route directions result |
|
||||
| `RouteLeg` | Segment of a route |
|
||||
| `RouteMatrixQuery` | Query for route matrix |
|
||||
| `RouteMatrixResult` | Route matrix result |
|
||||
| `RouteRangeOptions` | Options for isochrone |
|
||||
| `RouteRangeResult` | Isochrone result |
|
||||
| `RouteType` | Route type (Fastest, Shortest, Eco, Thrilling) |
|
||||
| `TravelMode` | Travel mode (Car, Truck, Bicycle, Pedestrian) |
|
||||
|
||||
### Rendering Package
|
||||
|
||||
| Type | Purpose |
|
||||
|------|---------|
|
||||
| `MapsRenderingClient` | Main client for rendering |
|
||||
| `GetMapTileOptions` | Map tile options |
|
||||
| `MapTileIndex` | Tile coordinates (X, Y, Zoom) |
|
||||
| `MapTileSetId` | Tile set identifier |
|
||||
|
||||
### Common Types
|
||||
|
||||
| Type | Purpose |
|
||||
|------|---------|
|
||||
| `GeoPosition` | Geographic position (longitude, latitude) |
|
||||
| `GeoBoundingBox` | Bounding box for geographic area |
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Entra ID for production** — Prefer over subscription keys
|
||||
2. **Batch operations** — Use batch geocoding for multiple addresses
|
||||
3. **Cache results** — Geocoding results don't change frequently
|
||||
4. **Use appropriate tile sizes** — 256 or 512 pixels based on display
|
||||
5. **Handle rate limits** — Implement exponential backoff
|
||||
6. **Use async route matrix** — For large matrix calculations (>100)
|
||||
7. **Consider traffic data** — Set `UseTrafficData = true` for accurate ETAs
|
||||
|
||||
## Error Handling
|
||||
|
||||
```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:
|
||||
// Invalid request parameters
|
||||
break;
|
||||
case 401:
|
||||
// Authentication failed
|
||||
break;
|
||||
case 429:
|
||||
// Rate limited - implement backoff
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Related SDKs
|
||||
|
||||
| SDK | Purpose | Install |
|
||||
|-----|---------|---------|
|
||||
| `Azure.Maps.Search` | Geocoding, search | `dotnet add package Azure.Maps.Search --prerelease` |
|
||||
| `Azure.Maps.Routing` | Directions, matrix | `dotnet add package Azure.Maps.Routing --prerelease` |
|
||||
| `Azure.Maps.Rendering` | Map tiles, images | `dotnet add package Azure.Maps.Rendering --prerelease` |
|
||||
| `Azure.Maps.Geolocation` | IP geolocation | `dotnet add package Azure.Maps.Geolocation --prerelease` |
|
||||
| `Azure.Maps.Weather` | Weather data | `dotnet add package Azure.Maps.Weather --prerelease` |
|
||||
| `Azure.ResourceManager.Maps` | Account management | `dotnet add package Azure.ResourceManager.Maps --prerelease` |
|
||||
|
||||
## Reference Links
|
||||
|
||||
| Resource | URL |
|
||||
|----------|-----|
|
||||
| Azure Maps Documentation | https://learn.microsoft.com/azure/azure-maps/ |
|
||||
| Search API Reference | https://learn.microsoft.com/dotnet/api/azure.maps.search |
|
||||
| Routing API Reference | https://learn.microsoft.com/dotnet/api/azure.maps.routing |
|
||||
| GitHub Source | https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/maps |
|
||||
| Pricing | https://azure.microsoft.com/pricing/details/azure-maps/ |
|
||||
Reference in New Issue
Block a user