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

时间:2016-08-11 21:51:35

标签: android api rest https xamarin.android

所以我试图在我的Android应用程序中使用Xamarin从API(我无法控制)中获取一些信息。

它的作用很棒!如果我将生成的链接粘贴到Chrome中,或者使用Chrome扩展程序Postman,我会得到我想要的信息,但它在我的应用程序中不起作用..

应用程序处于poc状态,因此所有内容都在实现ILocationListener的主活动中,并且每3秒请求一次gps更新,但这是代码中有趣的部分:

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内部调用,基本上只是将响应作为字符串获取:

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-request的响应如下:

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

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

任何有关此事的帮助或指示将不胜感激! 另外:链接到GitHub上的项目:https://github.com/Nemeas/alfaOmega

2 个答案:

答案 0 :(得分:0)

好的,经过大量的试验和错误后,我发现问题在于标题丢失了; 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;
    }

答案 1 :(得分:0)

这可能取决于标头中的 user-agent 值。如果您提供类似于浏览器的用户代理值,它可能会起作用。