This repository was archived by the owner on Jan 28, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 155
Expand file tree
/
Copy pathUsCensusBureauGeocoder.cs
More file actions
98 lines (84 loc) · 3.83 KB
/
UsCensusBureauGeocoder.cs
File metadata and controls
98 lines (84 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace Geocoding.UsCensusBureau
{
/// <summary>
/// refs:
/// - https://geocoding.geo.census.gov/
/// - https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.pdf
/// </summary>
public class UsCensusBureauGeocoder : IGeocoder
{
private readonly int _benchmark;
private readonly string _format;
private readonly HttpClient _client;
public UsCensusBureauGeocoder(int benchmark = 4, string format = "json")
{
_benchmark = benchmark;
_format = format;
_client = new HttpClient { BaseAddress = new Uri(UsCensusBureauConstants.BaseUrl) };
}
public async Task<IEnumerable<Address>> GeocodeAsync(string address, CancellationToken cancellationToken = default(CancellationToken))
{
// Build Query String
var sb = new StringBuilder(UsCensusBureauConstants.OneLineAddressPath);
sb.Append("address=").Append(WebUtility.UrlEncode(address))
.Append("&benchmark=").Append(_benchmark)
.Append("&format=").Append(_format);
// Get Request
var response = await _client.GetAsync(sb.ToString(), cancellationToken);
var content = await response.Content.ReadAsStringAsync();
// Read Result
return GetAddresses(content);
}
public async Task<IEnumerable<Address>> GeocodeAsync(string street, string city, string state, string postalCode, string country, CancellationToken cancellationToken = default(CancellationToken))
{
// Build Query String
var sb = new StringBuilder(UsCensusBureauConstants.AddressPath);
sb.Append("street=").Append(WebUtility.UrlEncode(street))
.Append("&city=").Append(WebUtility.UrlEncode(city))
.Append("&state=").Append(WebUtility.UrlEncode(state))
.Append("&zip=").Append(WebUtility.UrlEncode(postalCode))
.Append("&benchmark=").Append(_benchmark)
.Append("&format=").Append(_format);
// Get Request
var response = await _client.GetAsync(sb.ToString(), cancellationToken);
var content = await response.Content.ReadAsStringAsync();
// Read Result
return GetAddresses(content);
}
public Task<IEnumerable<Address>> ReverseGeocodeAsync(Location location, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotSupportedException();
}
public Task<IEnumerable<Address>> ReverseGeocodeAsync(double latitude, double longitude, CancellationToken cancellationToken = default(CancellationToken))
{
throw new NotSupportedException();
}
private static IEnumerable<UsCensusBureauAddress> GetAddresses(string response)
{
var json = JObject.Parse(response);
var errors = json[UsCensusBureauConstants.ErrorsKey];
if (errors != null)
return new UsCensusBureauAddress[] {};
var result = json[UsCensusBureauConstants.ResultKey];
return result[UsCensusBureauConstants.AddressMatchesKey]
.Select(match =>
{
var matched = match[UsCensusBureauConstants.MatchedAddressKey].ToString();
var coordinates = match[UsCensusBureauConstants.CoordinatesKey];
var x = double.Parse(coordinates[UsCensusBureauConstants.XKey].ToString());
var y = double.Parse(coordinates[UsCensusBureauConstants.YKey].ToString());
return new UsCensusBureauAddress(matched, new Location(y, x));
})
.ToArray();
}
}
}