C# 地址已知时如何获取坐标?

C# 地址已知时如何获取坐标?,c#,geolocation,geocoding,windows-store-apps,openstreetmap,C#,Geolocation,Geocoding,Windows Store Apps,Openstreetmap,我从Adam Freeman的书《Metro启示录:使用XAML和C#构建Windows 8应用程序》中派生/改编了以下代码,以便在坐标已知时获取地址: public static async Task<string> GetAddressForCoordinates(double latitude, double longitude) { HttpClient httpClient = new HttpClient {BaseAddress = new Uri("http:

我从Adam Freeman的书《Metro启示录:使用XAML和C#构建Windows 8应用程序》中派生/改编了以下代码,以便在坐标已知时获取地址:

public static async Task<string> GetAddressForCoordinates(double latitude, double longitude)
{
    HttpClient httpClient = new HttpClient {BaseAddress = new Uri("http://nominatim.openstreetmap.org")};
    HttpResponseMessage httpResult = await httpClient.GetAsync(
        String.Format("reverse?format=json&lat={0}&lon={1}", latitude, longitude));
JsonObject jsonObject = JsonObject.Parse(await httpResult.Content.ReadAsStringAsync());

return jsonObject.GetNamedObject("address").GetNamedString("road");
它只是返回道路;我猜大概是“河滨大道157号”

但对于地理编码(需要两个值,一个经度和一个纬度),我有以下伪代码:

return jsonObject.GetNamedObject("address").GetNamedString("lat"); // <-- what about "lon"?
…还是

更新3 针对提供的地理编码Json代码:

基于原始的反向地理编码,调用不应该更像这样:

public static async Task<string> GetCoordinatesForAddress(string address)
{
    HttpClient httpClient = new HttpClient {BaseAddress = new Uri("http://nominatim.openstreetmap.org")};
    HttpResponseMessage httpResult = await httpClient.GetAsync(
        String.Format("format=json&address={0}", address));

    JsonObject jsonObject = JsonObject.Parse(await httpResult.Content.ReadAsStringAsync());

    return jsonObject.GetNamedObject("address").GetNamedString("lat"); // <-- what about "lon"?
}
HttpClient httpClient = new HttpClient { BaseAddress = new Uri("http://nominatim.openstreetmap.org/") };
var httpResult = await httpClient.GetAsync(
    String.Format("search?format=json&addressdetails={0}", address);
……但无论如何: JArray类型无法识别,但JsonArray无法识别。 JValue类型无法识别,但JsonValue是。 无法识别JsonConverter类型;也许是Json.Net的一部分

我最接近于编译专业代码的方法是:

var result = await httpResult.Content.ReadAsStringAsync();
var r = (JsonArray)JsonConverter.DeserializeObject(result);//<-- JsonConvert[er] not recognized; part of Json.NET?
var latString = ((JsonValue)r[0]["lat"]).ValueType as string;
var longString = ((JsonValue)r[0]["lon"]).ValueType as string;
…我收到此错误消息:“*System.InvalidOperationException未被用户代码处理 HResult=-2146233079 Message=序列不包含任何元素 Source=System.Core 堆栈跟踪: 在System.Linq.Enumerable.First[TSource](IEnumerable`1 source)处 在c:…*”中的SpaceOverlays.SOs_Classes.SOs_Utils.d_u12.MoveNext()处

hereNetResponse的值为:

{"results":{"items":[]},"search":{"context":{"location":{"position":[38.804967,-90.113183],"address":
{"postalCode":"62048","city":"Hartford","stateCode":"IL","county":"Madison","countryCode":"USA","country":"
USA","text":"Hartford IL 62048
USA"}},"type":"urn:nlp-types:place","href":"http://demo.places.nlp.nokia.com/places/v1/places/loc-
dmVyc2lvbj0xO3RpdGxlPUhhcnRmb3JkO2xhdD0zOC44MDQ5Njc7bG9uPS05MC4xMTMxODM7Y2l0eT1IY
XJ0Zm9yZDtwb3N0YWxDb2RlPTYyMDQ4O2NvdW50cnk9VVNBO3N0YXRlQ29kZT1JTDtjb3VudHk9TWFka
XNvbjtjYXRlZ29yeUlkPWNpdHktdG93bi12aWxsYWdl;context=Zmxvdy1pZD02YmUzZDM4Yi0wNGVhLTUyM
jgtOWZmNy1kNWNkZGM0ODI5OThfMTM1NzQyMDI1NTg1M18wXzE2MA?
app_id=F6zpNc3TjnkiCLwl_Xmh&app_code=QoAM_5BaVDZvkE2jRvc0mw"}}}
…所以里面似乎有有效的信息,比如应该返回“哈特福德,伊利诺伊州”


无论如何,一个空白的返回值不应该抛出异常,我认为…

你所问的只是“地理编码”。如果你想特别使用提名,他们称之为“搜索”。这在一定程度上是地址验证;但“验证”的一部分包括坐标(边界框、横向/纵向等;取决于搜索内容和结果类型)。关于结果有很多细节,太多了,不能简单地在这里发布;但这个细节可以在这里找到:(包括examles)

您必须解析结果(XML、JSON或HTML)才能获得您感兴趣的字段

更新1: 至于如何处理实际值:这取决于。如果要查看表单中的坐标,只需将lat和long字符串放入各个控件中即可。如果要将其放在单个控件中,可以使用
string.Format(“{0},{1}”、latString、longString)
。如果要将coords与Windows应用商店应用程序的各种方法/类型一起使用,可能需要使用
Microsoft.Maps.MapControl.Location
类。例如:

  Double latNumber;
  Double longNumber;
  if(false == Double.TryParse(latString, out latNumber)) throw new InvalidOperationException();
  if(false == Double.TryParse(longString, out longNumber)) throw new InvalidOperationException();
  var location = new Location(latNumber, longNumber);
    var httpClient = new HttpClient();
    var httpResult = await httpClient.GetAsync(
        "http://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=json&polygon=1&addressdetails=1");

    var result = await httpResult.Content.ReadAsStringAsync();
    var r = (JArray) JsonConvert.DeserializeObject(result);
    var latString = ((JValue) r[0]["lat"]).Value as string;
    var longString = ((JValue)r[0]["lon"]).Value as string;
以上假设您已经从响应中提取了lat和long,并将它们分别放入
latString
longString

有些接口可能需要lat/long作为单独的双精度值,在这种情况下,只需使用上面的
latNumber
longNumber

除此之外,它确实具体取决于您想要使用的接口。但是,以上内容应该足以让您使用大多数接口

更新2: 如果问题不是“如何获取坐标”,而是“如何解析json对象”,那么我建议使用json.Net获取json结果中的lat/long字符串。例如:

  Double latNumber;
  Double longNumber;
  if(false == Double.TryParse(latString, out latNumber)) throw new InvalidOperationException();
  if(false == Double.TryParse(longString, out longNumber)) throw new InvalidOperationException();
  var location = new Location(latNumber, longNumber);
    var httpClient = new HttpClient();
    var httpResult = await httpClient.GetAsync(
        "http://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=json&polygon=1&addressdetails=1");

    var result = await httpResult.Content.ReadAsStringAsync();
    var r = (JArray) JsonConvert.DeserializeObject(result);
    var latString = ((JValue) r[0]["lat"]).Value as string;
    var longString = ((JValue)r[0]["lon"]).Value as string;

…请参见上面的w.r.t.如何处理
latString
longString
Microsoft Mappoint还包含一个您可以使用的API。它可以返回地理坐标。

如果您正在寻找谷歌地图地理编码,您可以在这里找到它:

例如:

转换为Json,并获取几何体对象

基本上,关于如何从函数返回两个值,在C#中有4个选项:

  • 将两个对象转换为同一类型的单个对象(对于字符串,您只需使用分隔符将它们分隔开,就像您所做的那样),然后将它们解析出来
  • 返回一个列表-在本例中是一个任务(或数组)
  • 创建一个包含这两者的新类/对象(在本例中,您可以将其称为Geometry)
  • 通过要求将一个或两个对象作为函数的引用传递,返回它们。在异步函数中,这肯定是非常棘手的,但这可能取决于调用函数的人和处理结果的人

  • 这是一个我可以使用Bing Maps从windows应用商店应用程序调用的API吗?我不能这么说,但它通常很容易与C#一起使用。实际上,它现在是Bing Maps API,它与windows应用商店应用程序配合得很好。Visual Studio的工具扩展菜单中有一个Bing SDK。下载SDK并将引用添加到项目中。你需要一把钥匙(目前免费),你可以在这里得到我知道的那一页;我需要的是在上面我的帖子的更新中定义的(这是我在提出问题之前添加的)。“如何组合坐标”做什么?我的答案太长,无法发表评论,所以现在是上面的更新2。@ClayShannon你问的有点不清楚,似乎不是“如何获得坐标”,而是“如何解析Json”;因此,我在回答中添加了一些更新。我要问的是,返回第一个字符串中包含纬度、第二个字符串中包含经度的字符串列表,或者字符串中包含分号分隔值的代码应该是什么。顺便说一句,我在更新2中发布的代码可以很好地编译并使用Namingm和Nuget添加JSon.Net。我使用了Javascript+传单,它帮助了我:function getCoordinates(){//query具有搜索文本var query=$(“#query”).val();var url=”“+encodeURIComponent(query);$.getJSON(url,function(data){for(变量i=0;i
    // If address has not been explicitly entered, try to suss it out:
                        address = textBoxAddress1.Text.Trim();
                        lat = textBoxLatitude1.Text.Trim();
                        lng = textBoxLongitude1.Text.Trim();
                        if (string.IsNullOrWhiteSpace(address))
                        {
                            address = await SOs_Classes.SOs_Utils.GetAddressForCoordinates(lat, lng);
                        }
    
    . . .
    
            public async static Task<string> GetAddressForCoordinates(string latitude, string longitude)
            {
                string currentgeoLoc = string.Format("{0},{1}", latitude, longitude);
                string queryString = string.Empty;
                string nokiaAppID = "j;dsfj;fasdkdf";
                object nokiaAppCode = "-14-14-1-7-47-178-78-4";
                var hereNetUrl = string.Format(
                    "http://demo.places.nlp.nokia.com/places/v1/discover/search?at={0}&q={1}&app_id={2}    
    &app_code={3}&accept=application/json",
                        currentgeoLoc, queryString, nokiaAppID, nokiaAppCode);    
                // get data from HERE.net REST API
                var httpClient = new HttpClient();
                var hereNetResponse = await httpClient.GetStringAsync(hereNetUrl);    
                // deseralize JSON from Here.net 
                using (var tr = new StringReader(hereNetResponse))
                using (var jr = new JsonTextReader(tr))
                {
                    var rootObjectResponse = new JsonSerializer    
    ().Deserialize<JsonDOTNetHelperClasses.RootObject>(jr);    
                    var firstplace = rootObjectResponse.results.items.First();
                    return HtmlUtilities.ConvertToText(firstplace.vicinity);
                    // NOTE: There is also a title (such as "Donut Shop", "Fire stations", etc.?) and type (such as "residence" or "business", etc.?)
                }
            }
    
            var firstplace = rootObjectResponse.results.items.First();
    
    {"results":{"items":[]},"search":{"context":{"location":{"position":[38.804967,-90.113183],"address":
    {"postalCode":"62048","city":"Hartford","stateCode":"IL","county":"Madison","countryCode":"USA","country":"
    USA","text":"Hartford IL 62048
    USA"}},"type":"urn:nlp-types:place","href":"http://demo.places.nlp.nokia.com/places/v1/places/loc-
    dmVyc2lvbj0xO3RpdGxlPUhhcnRmb3JkO2xhdD0zOC44MDQ5Njc7bG9uPS05MC4xMTMxODM7Y2l0eT1IY
    XJ0Zm9yZDtwb3N0YWxDb2RlPTYyMDQ4O2NvdW50cnk9VVNBO3N0YXRlQ29kZT1JTDtjb3VudHk9TWFka
    XNvbjtjYXRlZ29yeUlkPWNpdHktdG93bi12aWxsYWdl;context=Zmxvdy1pZD02YmUzZDM4Yi0wNGVhLTUyM
    jgtOWZmNy1kNWNkZGM0ODI5OThfMTM1NzQyMDI1NTg1M18wXzE2MA?
    app_id=F6zpNc3TjnkiCLwl_Xmh&app_code=QoAM_5BaVDZvkE2jRvc0mw"}}}
    
      Double latNumber;
      Double longNumber;
      if(false == Double.TryParse(latString, out latNumber)) throw new InvalidOperationException();
      if(false == Double.TryParse(longString, out longNumber)) throw new InvalidOperationException();
      var location = new Location(latNumber, longNumber);
    
        var httpClient = new HttpClient();
        var httpResult = await httpClient.GetAsync(
            "http://nominatim.openstreetmap.org/search?q=135+pilkington+avenue,+birmingham&format=json&polygon=1&addressdetails=1");
    
        var result = await httpResult.Content.ReadAsStringAsync();
        var r = (JArray) JsonConvert.DeserializeObject(result);
        var latString = ((JValue) r[0]["lat"]).Value as string;
        var longString = ((JValue)r[0]["lon"]).Value as string;