如何从 C# 代码调用 Google 地理编码服务

Posted

技术标签:

【中文标题】如何从 C# 代码调用 Google 地理编码服务【英文标题】:How to call Google Geocoding service from C# code 【发布时间】:2013-04-29 08:42:28 【问题描述】:

我有一个 C# 类库。从那里我必须调用 Google 服务并获取纬度和经度。

我知道如何在页面上使用 AJAX,但我想直接从我的 C# 类文件中调用 Google 地理编码服务。

有什么方法可以做到这一点,或者我可以使用其他任何服务。

【问题讨论】:

到目前为止你有没有尝试过? 看看HttpWebRequest @SonerGönül 我试图在本教程中这样做friism.com/c-and-google-geocoding-web-service-v3 【参考方案1】:

你可以这样做:

string address = "123 something st, somewhere";
string requestUri = string.Format("https://maps.googleapis.com/maps/api/geocode/xml?key=1&address=0&sensor=false", Uri.EscapeDataString(address), YOUR_API_KEY);

WebRequest request = WebRequest.Create(requestUri);
WebResponse response = request.GetResponse();
XDocument xdoc = XDocument.Load(response.GetResponseStream());

XElement result = xdoc.Element("GeocodeResponse").Element("result");
XElement locationElement = result.Element("geometry").Element("location");
XElement lat = locationElement.Element("lat");
XElement lng = locationElement.Element("lng");

您还需要验证响应状态并捕获任何 WebExceptions。看看Google Geocoding API。

【讨论】:

确保添加using System.Xml.Linq;(如果缺少相应的引用 - System.Xml.Linq.dll)。 惊讶于这是多么容易。头脑=吹! 这样的问题是,如果你输入无效的地址,它会崩溃。如果您输入无效地址但输入有效城市,它仍会返回近似值 在 SSIS 包中使用 Visual C# 2008 和 .NET 3.5,我必须先将响应加载到 StreamStreamReader,然后将阅读器加载到 XDocument。仅 .NET 4.0+ 支持将流直接加载到 XDcoument 中(来源:msdn.microsoft.com/en-us/library/cc838349(v=vs.110).aspx)。 这不起作用了,你必须获取一个 API 密钥并在查询字符串中使用它。【参考方案2】:

我没有评论的声誉,但只想说 Chris Johnson 的代码就像一个魅力。程序集是:

using System.Net;
using System.Xml.Linq;

【讨论】:

不知道程序集并不愚蠢。很多人都很欣赏有人发布了这个【参考方案3】:

您还可以使用经常与 Asp.Net Web Api 或 Asp.Net 5.0 一起使用的 HttpClient 类。

您还拥有一个免费的 http 状态代码、asyn/await 编程模型和使用 HttpClient 处理异常非常容易。

var address = "paris, france";
var requestUri = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?address=0&sensor=false", Uri.EscapeDataString(address));

using (var client = new HttpClient())

    var request = await client.GetAsync(requestUri);
    var content = await request.Content.ReadAsStringAsync();
    var xmlDocument = XDocument.Parse(content);


【讨论】:

【参考方案4】:

这是一个老问题。但我今天有同样的问题,并提出了这个作为解决方案:C# GeoCoding / Address Validation API(支持包括谷歌地图在内的多个提供商)。

IGeocoder geocoder = new GoogleGeocoder()  ApiKey = "this-is-my-optional-google-api-key" ;

IEnumerable<Address> addresses = await geocoder.GeocodeAsync("1600 pennsylvania ave washington dc");

Console.WriteLine("Formatted: " + addresses.First().FormattedAddress);
// Formatted: 1600 Pennsylvania Ave SE, Washington, DC 20003, USA

Console.WriteLine("Coordinates: " + addresses.First().Coordinates.Latitude + ", " + addresses.First().Coordinates.Longitude);
// Coordinates: 38.8791981, -76.9818437

这里是对应的 NuGet 包:

安装包Geocoding.Google

【讨论】:

【参考方案5】:

您可以调用 Web 服务并使用 json/xml 响应。

http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true

这会返回一个您可以使用的 json 响应。

正如您在使用条款中所读到的,您只有在出示谷歌地图时才能使用他们的网络服务。

在这里您可以找到有关该服务的所有信息:https://developers.google.com/maps/documentation/geocoding/

要了解如何处理 json 响应,请查看此主题:Google Maps v3 geocoding server-side

编辑: 刚找到这篇文章:http://www.codeproject.com/Tips/505361/Google-Map-Distance-Matrix-and-Geocoding-API-V3-we

我没有对此进行测试,但也许它对你有用:)

EDIT2: codeproject 示例似乎不起作用 :( 那里提到的 url 返回总是相同的,无论输入的地址点是什么... 但是,无论如何您都应该尝试使用 JSON 或 XML 结果,因为这是我想说的最佳实践。

【讨论】:

【参考方案6】:

更新:此处提到的先前软件包已弃用 - 有一个最新版本适合 .Net Core。

这个答案可能为时已晚,但对于那些仍在寻找使用 Google Places 或地理编码 API 的简单方法的人来说,我写了这个简单的 nuget called GuigleCore,它可以像这样使用:

var googleGeocodingApi = new GoogleGeocodingApi("GoogleApiKey");
var address = await googleGeocodingApi.SearchAddressAsync(httpClient, "123 Street, Suburb A");

var googlePlacesApi = new GooglePlacesApi("GoogleApiKey");
var place = await googlePlacesApi.FindPlaces(httpClient, "123 Street, Suburb A"));

您可以像这样为 DI 注册它:

services.AddScoped(typeof(IGooglePlacesApi), x => new GooglePlacesApi(Configuration["GoogleApiKey"]));

我喜欢它的一点是,您可以从 API 响应中获取完整的对象,因此您可以轻松访问所有内容,并且可以使用 Linq 和其他集合助手轻松从中检索数据。

您可以使用 nuget 命令 Install-Package GuigleCore 安装它 或fork it here。

【讨论】:

【参考方案7】:

要完成 JP Hellemons 的回答,请使用 Geocoding.net 并仅检索城市名称,例如:

IGeocoder geocoder = new GoogleGeocoder()  ApiKey = "API_Key" ;
IEnumerable<Address> addresses = await geocoder.GeocodeAsync("address");

foreach(var component in ((GoogleAddress)addresses.First()).Components)

    foreach(var type in component.Types)
    
        if(type == GoogleAddressType.Locality)
        
            return component.LongName;
        
    

【讨论】:

【参考方案8】:

这可能不多,但我只想对@Chris Johnson 代码进行一项改进,如果您只想以双重形式获得 lat 和 lng 值,chris johnson 的 var lat 和 var lng 具有这种格式的价值 ...数字...

所以如果你传递的值是一个字符串来获取数值你必须这样做

  double latitude = Double.Pars(lat.Value)
 double longitude = Double.Pars(lng.Value)

【讨论】:

【参考方案9】:

这是我在 .Net Core API 中使用的方法,在这种情况下,我们只需要 Lat 和 Lng 值来匹配我们的内部 LocationModel:

public async Task<LocationModel> GetAddressLocation(string address)

    try
    
        var targetUrl = $"https://maps.googleapis.com/maps/api/geocode/json" +
            $"?address=address" +
            $"&inputtype=textquery&fields=geometry" +
            $"&key=_apiKey";

        _logger.LogDebug($"GetAddressLocation : targetUrl:targetUrl");

        using var client = new HttpClient();
        using var request = new HttpRequestMessage(HttpMethod.Get, targetUrl);    
        using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
        var stream = await response.Content.ReadAsStreamAsync();

        if (response.IsSuccessStatusCode)
        
            if (stream == null || stream.CanRead == false)
                return null;

            using var sr = new StreamReader(stream);
            var jsonString = sr.ReadToEnd();
            dynamic responseObject = JObject.Parse(jsonString);

            var results = responseObject["results"];

            var lat = results[0]?["geometry"]?["location"]?["lat"];
            var lng = results[0]?["geometry"]?["location"]?["lng"];

            var result = new LocationModel  Latitude = lat, Longitude = lng ;
            return result;
        
        else
        
            await HandleApiError(response, stream);
            throw new DomainException($"UNKNOWN ERROR USING GEOCODING API :: response");
        
    
    catch (Exception ex)
    
        _logger.LogError("ERROR USING Geocoding Service", ex);
        throw;
    

【讨论】:

以上是关于如何从 C# 代码调用 Google 地理编码服务的主要内容,如果未能解决你的问题,请参考以下文章

C# Google 地理编码:即使遵循所需的步骤,也会不断拒绝权限

如何正确限制对 Android 和 iOS 应用程序(用 Flutter 编写)的 Google 地图(地点、地理编码)API 调用?

Google 地理编码服务返回错误 400 错误请求

通过传递Zipcode,从Google地理编码服务中检索城市州和邮政信息

Google 地理编码 API 安全性

为地理编码结果自动寻找合适的缩放比例