Mitc.Integrations.CensusGeocoder 2.0.0
Mitc.Integrations.CensusGeocoder
A lightweight client over the US Census Bureau geocoder's Find Locations service. Supply one or more addresses, get back coordinates.
Scope
- Find Locations — address in, coordinates out, plus parsed address components (single lookups) and a raw-response escape hatch.
- Distance & route planning — great-circle distance between coordinates, and a brute-force shortest-route optimizer for small stop sets.
- Not covered: Find Geographies (census tract/block lookups), reverse geocoding, and LUCA services.
Usage
services.AddCensusGeocoder();
// Single address
Result<GeocodeMatch> result = await geocoder.GeocodeAsync(
CensusAddress.OneLine("4600 Silver Hill Rd, Washington, DC 20233"));
// On a successful match, the parsed components are available:
// result.Value.AddressComponents.StreetName, .City, .State, .Zip, ...
// Batch — keyed by your own id (int, long, string, or Guid)
var addresses = new Dictionary<int, CensusAddress>
{
[1] = CensusAddress.Parsed("4600 Silver Hill Rd", "Washington", "DC", "20233"),
};
IReadOnlyDictionary<int, Result<BatchGeocodeMatch>> results = await geocoder.GeocodeBatchAsync(addresses);
Raw responses
Need a field the typed model doesn't expose, or want to inspect exactly what the geocoder
returned? Reach for the raw methods. They return the unparsed body as a string and do not
throw on a malformed body. (An HTTP error status — 4xx/5xx — still throws HttpRequestException,
the same as the parsed methods.)
// Single lookup — raw JSON, for any outcome (match / tie / no-match).
string json = await geocoder.GetRawResponseAsync(
CensusAddress.OneLine("4600 Silver Hill Rd, Washington, DC 20233"));
// Batch — raw CSV for the whole upload. The optional formatId controls how each
// key is written so response rows correlate to your ids (defaults to invariant ToString).
string csv = await geocoder.GetRawBatchResponseAsync(addresses);
The single endpoint returns JSON; the batch endpoint returns CSV. Either way it's a string —
the batch (CSV) response carries no parsed address components, which is why BatchGeocodeMatch
has none while GeocodeMatch does.
Upgrading from 1.x
2.0.0 splits the batch result type. GeocodeBatchAsync now returns
IReadOnlyDictionary<TId, Result<BatchGeocodeMatch>> instead of Result<GeocodeMatch>. The
batch (CSV) path has no parsed components, so BatchGeocodeMatch exposes only MatchedAddress
and Coordinates — .AddressComponents is available only on the single-lookup GeocodeMatch.
Single-address calls are otherwise unchanged; the new AddressComponents property and the raw
methods are additive.
Distance & route planning
All coordinate math is pure and synchronous — no API calls, no DI.
// Great-circle distance between two coordinates
Distance d = a.Coordinates.DistanceTo(b.Coordinates);
double miles = d.Miles;
// Shortest order to visit stops from a distribution center (origin).
// Stops are keyed by your own id; the plan returns those ids in visiting order.
// Capped at RoutePlanner.MaxStops (10) — the search is factorial in the stop count.
var stops = new Dictionary<int, Coordinates>
{
[1] = stop1.Coordinates,
[2] = stop2.Coordinates,
};
RoutePlan<int> plan = RoutePlanner.FindShortestRoute(origin, stops, returnToOrigin: true);
// plan.Order -> ids in optimal visiting sequence
// plan.TotalDistance -> Distance for the whole route
Result statuses
The Census three-way outcome is mapped onto Mitc.Support.Results.ResultStatus:
| Census outcome | ResultStatus |
Notes |
|---|---|---|
| Single match | Success |
Value carries the matched address and coordinates. |
| No match | NotFound |
The geocoder reported no match. |
| Tie (multiple matches) | Conflict |
Address is well-formed but ambiguous; closest fit, as the enum has no "ambiguous" member. |
| No row returned (batch only) | Invalid |
The geocoder never answered for that id — distinct from a genuine no-match. |
No packages depend on Mitc.Integrations.CensusGeocoder.
.NET Standard 2.0
- Mitc.Support.Results (>= 1.2.0)
- CsvHelper (>= 33.0.1)
- Flurl (>= 4.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Http (>= 8.0.1)
- System.Text.Json (>= 8.0.5)