GoogleMapsApi .NET Wrapper

repository·master·Indexed 42 days ago

https://github.com/maximn/google-maps

A strongly-typed, async-first .NET wrapper for Google Maps Web Services. It provides idiomatic C# support for REST APIs including Geocoding, Routes, Directions, Distance Matrix, Places (New), Solar, Aerial View, Air Quality, and Pollen. Features include OpenTelemetry tracing and metrics, Dependency Injection integration via IHttpClientFactory, and a template for scaffolding ASP.NET Core Web API projects.

Tokens
10.9K
Snippets
36
Records
49
Agent score
52%

What's inside GoogleMapsApi

  1. How the NuGet publishing workflow works

    master

    Releases are tag-driven. Pushing a git tag matching v* to origin triggers the .github/workflows/nuget.yml workflow.

    Workflow Lifecycle

    1. Approval Gate: The workflow pauses at the "Review deployments" stage. A human reviewer must approve the release environment deployment before any build or publish steps occur.
    2. Build: The workflow checks out the repo, installs .NET SDKs, and runs dotnet restore, dotnet build -c Release, and dotnet pack -c Release.
    3. Versioning: The package version is derived from the v* tag at build time using MinVer. Tagged builds result in stable versions (e.g., 1.4.6), while untagged commits result in unique prerelease versions (e.g., 1.4.7-alpha.0.3).
    4. Publish: The package is pushed to NuGet.org using dotnet nuget push *.nupkg --api-key $NUGET_API_KEY --skip-duplicate. The --skip-duplicate flag ensures that re-running a workflow for a version already on NuGet is a no-op rather than an error.

    Monitoring

    After pushing a tag, monitor the progress in the GitHub Actions tab: https://github.com/maximn/google-maps/actions

  2. Choose the correct Semantic Versioning (semver) bump type

    master

    When releasing, choose a bump type based on the nature of the changes:

    • patch: Bug fixes, dependency bumps, or internal cleanup. No changes to the public API.
    • minor: New functionality that is backwards-compatible.
    • major: Breaking changes to the public API.
  3. How Cassettes work for offline testing

    master

    The project uses Cassettes to enable offline integration testing. Cassettes are recorded JSON files containing Google API responses. When running tests in the default replay mode, the suite uses these files instead of making real network calls, meaning no API key is required and no costs are incurred.

    If a test makes a request that does not have a corresponding recorded interaction in a cassette, the test will fail loudly to ensure integration coverage is maintained.

  4. Migrate from legacy Places API to Places API (New)

    master

    Version 2.0 removes the legacy (frozen) Places API. All Places functionality must now use the Places API (New).

    Important: FieldMasks Unlike the legacy API, Places (New) requires a FieldMask to specify which fields you want to return. This is used for billing purposes. Each request type exposes a FieldMask property with sensible defaults, but you should override it to request specific fields.

  5. Release a new version using the release script

    master

    The recommended way to publish a new version of the GoogleMapsApi NuGet package is by using the ./release.sh script. This script automates version computation, changelog updates, and tag creation.

    Usage

    Run the script with the desired Semantic Versioning (semver) bump type:

    • Patch bump (e.g., 1.4.5 → 1.4.6): ./release.sh (defaults to patch)
    • Minor bump (e.g., 1.4.5 → 1.5.0): ./release.sh minor
    • Major bump (e.g., 1.4.5 → 2.0.0): ./release.sh major

    Previewing Changes

    You can preview the version bump without making any changes using the --dry-run flag:

    ./release.sh --dry-run
    ./release.sh minor --dry-run

    Workflow Steps

    1. Verification: Checks that the working tree is clean.
    2. Version Computation: Reads the latest v* tag and calculates the next version.
    3. Release Notes: Generates notes from the commit log (using claude -p). You can use --edit to open them in your $EDITOR or --no-notes to skip note generation, changelog updates, and GitHub Releases (useful for hotfixes).
    4. Confirmation: Prompts for y/N before proceeding.
    5. Execution: On confirmation, the script:
      • Updates CHANGELOG.md by moving ## [Unreleased] content to a new version section.
      • Commits CHANGELOG.md with the message chore(release): vX.Y.Z.
      • Creates and pushes an annotated git tag to origin.
      • Creates a GitHub Release.

    Prerequisites

    • Push access to origin.
    • A clean working tree on the latest master branch.
    • The NUGET_API_KEY must be configured as a release environment secret in GitHub.
    • Ability to approve the release environment deployment in GitHub Actions.
    ./release.sh           # patch bump (e.g. 1.4.5 → 1.4.6)
    ./release.sh minor     # minor bump (e.g. 1.4.5 → 1.5.0)
    ./release.sh major     # major bump (e.g. 1.4.5 → 2.0.0)
    
    # Preview without making changes
    ./release.sh --dry-run
    ./release.sh minor --dry-run
    
    # Skip notes/changelog for hotfixes
    ./release.sh --no-notes
  6. Configure GoogleMapsApi using .NET Generic Host and Dependency Injection

    master

    To use GoogleMapsApi within a .NET Generic Host application, use the AddGoogleMaps(IConfiguration) extension method from the GoogleMapsApi.Extensions.DependencyInjection package. This method binds GoogleMapsClientOptions (including the ambient API key) directly from your application's configuration.

    Once registered, you can use constructor injection to request IGoogleMapsClient in any application service. The service will automatically use the configured API key for all requests, meaning you do not need to pass the key manually when constructing DistanceMatrixRequest or other request objects.

    // In your Program.cs or Startup.cs
    builder.Services.AddGoogleMaps(builder.Configuration);
    
    // In your application service
    public class TravelTimeService
    {
        private readonly IGoogleMapsClient _client;
    
        public TravelTimeService(IGoogleMapsClient client)
        {
            _client = client;
        }
    }
  7. Register GoogleMapsApi via Dependency Injection

    master

    The GoogleMapsApi.Extensions.DependencyInjection package provides streamlined registration for IGoogleMapsClient. This registers the client (backed by IHttpClientFactory) and an ambient API key so that individual service calls do not need to repeat the key.

    There are two primary ways to use the extension method:

    1. Using an Options Action: Pass an Action<GoogleMapsClientOptions> to configure the client.
    2. Using IConfiguration: Pass an IConfiguration instance to automatically bind the API key and other settings from your configuration providers.
    // Minimal API style: Using an options action
    builder.Services.AddGoogleMaps(options => {
        options.ApiKey = "..."; // Or rely on environment variables
    });
    
    // Generic Host style: Binding from IConfiguration
    builder.Services.AddGoogleMaps(builder.Configuration);
  8. (Re)record Cassettes

    master

    To record new cassettes or update existing ones, you must run the tests in record mode with a valid API key. Use the following command structure:

    VCR_MODE=record GOOGLE_API_KEY=<key> RUN_BILLABLE_TESTS=true dotnet test

    To record only a specific fixture, use the --filter flag:

    VCR_MODE=record GOOGLE_API_KEY=<key> RUN_BILLABLE_TESTS=true dotnet test --filter "ClassName=<Fixture>"

    Important Rules:

    • Commit to git: Cassettes are offline fixtures and must be committed to the repository.
    • No secrets: The key and signature query parameters are automatically redacted to REDACTED during recording. This allows recordings made with a real key to be replayed using the placeholder keys used in replay mode.
  9. Run the Blazor.Geocoding sample project

    master

    To run the Blazor.Geocoding sample, use the dotnet run command while providing your Google API key via the GOOGLE_API_KEY environment variable. This ensures the key is handled on the server side and not exposed to the client.

    1. Set the GOOGLE_API_KEY environment variable.
    2. Execute the run command pointing to the sample project.
    3. Open the URL provided in the terminal output (e.g., https://localhost:5001).
    GOOGLE_API_KEY=your_api_key dotnet run --project samples/Blazor.Geocoding
  10. Initialize the GoogleMapsClient

    master

    The GoogleMaps static facade was removed in version 2.0.0. You must use the instance-based IGoogleMapsClient or GoogleMapsClient. The client should be constructed with an HttpClient to ensure it is IHttpClientFactory friendly and to allow for proper resource management. For non-DI scenarios, you can instantiate it directly with GoogleMapsClientOptions containing your ApiKey.

    using GoogleMapsApi;
    
    // Manual instantiation
    using var http = new HttpClient();
    var maps = new GoogleMapsClient(http, new GoogleMapsClientOptions { ApiKey = "your-google-maps-api-key" });
  11. Implement Geocoding in Blazor using IGoogleMapsClient

    master

    The Blazor.Geocoding sample demonstrates how to integrate the library into a Blazor Server application using Dependency Injection (DI):

    1. Registration: Register the client in your DI container using AddHttpClient<IGoogleMapsClient, GoogleMapsClient>().
    2. Injection: Inject the IGoogleMapsClient into your services or Blazor components.
    3. Execution: Use the .Geocode method on the client instance.
    4. Data Models: The process utilizes GeocodingRequest for input and GeocodingResponse for the resulting coordinates and address data.
    5. Abstraction: It is a best practice to wrap the library in a custom DI-injected service to be consumed by Blazor components.