2016-08-11 21 views
0

Xamarinを使用しているアンドロイドアプリケーションでAPIから情報を取得しようとしています。APIリクエストはアプリケーションで失敗しますが、ブラウザで動作します

そしてそれは火格子で動作します!生成されたリンクをChromeに貼り付けるか、Chrome拡張機能Postmanを使用すると正確に必要な情報が得られますが、アプリケーションでは機能しません。

アプリケーションは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は、基本的には単なる文字列として応答を取得OnLocationChanged、内部で呼び出さbeeingて-method :

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

Hey!ここのAPI作家の一人。私もこのケースの最下部に行きたいです。私はこの時点であなたのXamarinコードを実行することができませんが、プログラミングの参考にしたいと思います。 Javaプラットフォーム用のオープンソースクライアントを公開しました。ソースコードはhttps://github.com/nvdb-vegdata/nvdb-api-client – matsa

+0

@matsaのチップを与えるかもしれないので、私は実際に(最終的に) 'Accept:application/json'をリクエスト。しかし、 'request'Headers.Add(HttpRequestHeader.Accept、" application/json ")'が動作しなかったので、私は 'Get'メソッドで' HttpWebRequest'を使用しなければなりませんでした(私は有効なプロパティ値Enum/Const(?)HttpRequestHeader.Acceptの代わりに文字列値 "accept"を使ってみましたが、 'HttpWebRequest'は' accept'を以下のようにプロパティとして公開しています: 'request.Accept = "アプリケーション/ json"。最初のurlには必要ありませんでした – Nemeas

答えて

0

[OK]を試してみると、1トンの試行錯誤の末、問題がヘッダーが欠落していることがわかりました。 accept: application/json(これはこのapi(?)のv2の場合にすぎないようです)。私はWebRequestを使ってヘッダーを追加しようとしましたが、ヘッダーが追加される行に到達するたびにエラーが発生しました。ただしがリストではなくプロパティとして公開されているHttpWebRequestと呼ばれるこの別のWebRequestがあります。だから、唯一の変更は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

関連する問題