API请求在应用程序中失败,但在浏览器中工作

API请求在应用程序中失败,但在浏览器中工作

问题描述:

所以我想从我的Android应用程序中使用Xamarin的API(我无法控制)获取一些信息。API请求在应用程序中失败,但在浏览器中工作

它的工作原理!如果我将生成的链接粘贴到Chrome中,或者使用Chrome扩展邮件管理器,但我无法在我的应用程序中正常工作,我会得到我想要的信息。

应用程序处于poc状态,因此一切都在主它实现了ILocationListener并请求GPS每3秒更新,但在这里活动是代码的有趣的部分:

public void OnLocationChanged(Location location) { 

     var lat = location.Latitude; 
     var lon = location.Longitude; 

     _lat.Text = "lat: " + lat; 
     _lon.Text = "lon: " + lon; 

     // get the vegReference (roadReference) based on the lat & lon 
     var url = "https://www.vegvesen.no/nvdb/api/vegreferanse/koordinat?lon=" + lon.ToString("") + "&lat=" + lat.ToString("") + "&geometri=WGS84"; 

     // ex: https://www.vegvesen.no/nvdb/api/vegreferanse/koordinat?lon=10.399547&lat=63.354658&geometri=WGS84 

     var json = new JSONObject(Get(url)); 

     Log.Debug("url", url); 
     Log.Debug("json", json.ToString()); 

     if (json.GetString("kommuneNr") == "0") return; // bug in API? 

     var kommuneNr = json.GetString("kommuneNr"); 

     var vegReferanse = json.GetString("visningsNavn"); 

     // get the object id 105 (speed limit) on set vegReference 
     // API dok: https://www.vegvesen.no/nvdb/apidokumentasjon/#/get/vegobjekter 
     var url2 = "https://www.vegvesen.no/nvdb/api/v2/vegobjekter/105?vegreferanse=" + vegReferanse.Replace(" ", "") + "&inkluder=lokasjon&segmentering=false"; 

     // ex. https://www.vegvesen.no/nvdb/api/v2/vegobjekter/105?vegreferanse=PV3133HP1m73&inkluder=lokasjon&segmentering=false 

     // this (url2) is the one that fails 

     Log.Debug("url2", url2); 

     var json2 = new JSONObject(Get(url2)); 

     Log.Debug("json2", json2.ToString()); 

     // get the speed limit with the heighest id (this should be the latest one (FYI: speedlimits have changed over the years, all speed limits are in the database for historical reasons(?))) 

     var objs = json2.GetJSONArray("vegObjekter"); 

     var list = new List<JSONObject>(); 


     // getting a list of possible objects based on the kommuneNr (because for some f*ced up reason the result returns objects in other kommunes aswell...) 
     for (int i = 0; i < objs.Length() - 1; i++) 
     { 
      if (objs.GetJSONObject(i).GetJSONObject("lokasjon").GetJSONArray("kommuner").GetString(0) == kommuneNr) 
       list.Add(objs.GetJSONObject(i)); 
     } 

     if (list.Count == 0) return; 

     var url3 = list[list.Count - 1].GetString("href"); 

     // ex. https://www.vegvesen.no/nvdb/api/v2/vegobjekter/105/276790644 

     Log.Debug("url3", url3); 

     var json3 = new JSONObject(Get(url3)); 

     Log.Debug("json3", json3.ToString()); 

     // set the speed-limit to the textview. 

     var res = json3.GetJSONArray("egenskaper").GetJSONObject(0).GetString("verdi"); 
     _tvSl.Text = res + " km/t"; 

    } 

而且Get - 方法beeing称为OnLocationChanged内,基本上只获得响应作为一个字符串:

private string Get(string url) 
     { 
      var request = WebRequest.Create(url); 

      var sb = new StringBuilder(); 
      var response = (HttpWebResponse)request.GetResponse(); 

      using (var sr = new StreamReader(response.GetResponseStream())) 
      { 
       sb.Append(sr.ReadToEnd()); 
      } 
      return sb.ToString(); 
     } 

从URL2-请求的响应是这样的:

System.Net.WebException: The remote server returned an error: (500) Internal Server Error. 

我的问题是;为什么链接(ref url2)在浏览器中运行,而不是在应用程序中运行。

任何帮助或指针在这个问题将不胜感激! 另请参见:链接到GitHub上的项目:https://github.com/Nemeas/alfaOmega

+0

嘿!这里的API作者之一。我也想深入了解这个案例。我无法在这个时候运行你的Xamarin代码,但我想指导你编程参考。我们已经为Java平台发布了一个开源客户端。源代码可能会给你的索姆提示https://github.com/nvdb-vegdata/nvdb-api-client – matsa

+0

@matsa所以我实际上(最终)通过添加'接受:应用程序/ json的工作得到的东西工作请求。但是我不得不在'Get'方法中使用'HttpWebRequest',因为'request.Headers.Add(HttpRequestHeader.Accept,“application/json”)'不起作用(它一直说我必须提供一个有效的属性值,或者类似的东西。还尝试使用字符串值“accept”而不是Enum/Const(?)HttpRequestHeader.Accept),但是'HttpWebRequest'暴露了'accept'作为一个属性,如下所示:'request.Accept = “应用/ JSON”'。这在第一个url中并不需要apiv1 – Nemeas

好吧,经过大量的试验和错误,我发现问题是有一个丢失的标题; accept: application/json(看起来这只是这个api(?)的v2的情况)。我尝试使用WebRequest添加标题,但每当我到达添加标题的行时都会收到错误。然而,还有另一个WebRequest,名为HttpWebRequest,其中accept作为属性而不是通过列表公开,并且这是有效的。所以我必须做的唯一的改变是在Get方法,结果是这样的:

public static string Get(string url) 
    { 
     // casting request to HttpWebRequest to expose Accept as a property 
     var request = (HttpWebRequest)WebRequest.Create(url); 
     request.Accept = "application/json"; 

     var sb = new StringBuilder(); 

     // getting the response 
     var response = (HttpWebResponse)request.GetResponse(); 

     using (var sr = new StreamReader(response.GetResponseStream())) 
     { 
      sb.Append(sr.ReadToEnd()); 
     } 

     var res = sb.ToString(); 

     // returning the response as a string 
     return res; 
    } 
+0

看起来你是对的,一个_missing_ Accept头确实被解释为一个无效的Accept值,而不是默认为*/*。感谢您发现这个错误。 – matsa