问题描述:

So I'm basically trying stuff with Foursquare's venue API but getting the strange error whenever I send a API request.

First of all I authenticate with the following code;

var foursquareClient = new FoursquareClient(this);

if(!foursquareClient.IsAuthenticated)

foursquareClient.Authenticate();`

Authentication code;

public void Authenticate()

{

Log.Verbose(Logging.AppTag, "FourSquareClient:Authenticate()");

if (this.IsAuthenticated)

{

Log.Debug(Logging.AppTag, "FourSquareClient is already authenticated! ");

return;

}

this._authenticator = new OAuth2Authenticator(

clientId: ClientId,

scope: "",

authorizeUrl: new Uri("https://foursquare.com/oauth2/authenticate"),

redirectUrl: new Uri("http://www.int6.org"))

{

AllowCancel = false

};

this._authenticator.Completed += (sender, eventArgs) =>

{

if (eventArgs.IsAuthenticated) // auth. completed.

{

this.StoreAccount(eventArgs);

var builder = new AlertDialog.Builder(this.OwnerContext);

builder.SetMessage("auth all good!");

builder.SetPositiveButton("Ok", (o, e) => { });

builder.Create().Show();

return;

}

else // The user cancelled.

{

var builder = new AlertDialog.Builder(this.OwnerContext);

builder.SetMessage("User canncelled!");

builder.SetPositiveButton("Ok", (o, e) => { });

builder.Create().Show();

return;

}

};

// show the authenticator UI and start auth.

var intent = this._authenticator.GetUI(this.OwnerContext);

this.OwnerContext.StartActivity(intent);

}

So if user is authenticated once, it'll store the account on device.

public FoursquareClient(Context context)

{

Log.Verbose(Logging.AppTag, "Init foursquare client..");

this.OwnerContext = context; // make sure we set the owner context before any.

this.RetrieveAccount(); // try to retrieve any existing accounts.

}

Whenever he opens the application again, the account will be loaded back;

private void RetrieveAccount()

{

if (this.IsAuthenticated)

{

Log.Debug(Logging.AppTag, "FourSquareClient is already authenticated! ");

return;

}

var accounts = AccountStore.Create(this.OwnerContext).FindAccountsForService("Foursquare");

var enumerable = accounts as IList<Account> ?? accounts.ToList();

if (enumerable.Any())

{

Log.Info(Logging.AppTag, "Foursquareclient found account data.");

this.IsAuthenticated = true;

this.Account = enumerable.First();

}

else

{

Log.Info(Logging.AppTag, "Foursquareclient no account data found!");

this.IsAuthenticated = false;

this.Account = null;

}

}

So i guess I'm all good with auth stuff but somehow can't make the request;

public string MakeRequest()

{

var @params = new Dictionary<string, string>

{

{"v", "20120321"},

{"ll", "44.3,37.2"}

};

var request = new OAuth2Request("GET", new Uri("https://api.foursquare.com/v2/venues/explore"), @params,

this.Account);

request.GetResponseAsync().ContinueWith(t =>

{

if (t.IsFaulted)

Console.WriteLine(t.Exception.Flatten());

else

{

string json = t.Result.GetResponseText();

Console.WriteLine(json);

}

});

return string.Empty;

}

The request code returns; One or more errors occured

10-02 14:54:31.403 I/mono-stdout( 8641): System.AggregateException:

One or more errors occured ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.

System.AggregateException: One or more errors occured --->

System.Net.WebException: The remote server returned an error: (400)

Bad Request. 10-02 14:54:31.413 I/mono-stdout( 8641): at

System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult

result) [0x00000] in :0 at

System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult

result) [0x00000] in :0 at

System.Net.HttpWebRequest.SetResponseData

(System.Net.WebConnectionData data) [0x00000] in :0

10-02 14:54:31.413 I/mono-stdout( 8641): at

System.Net.HttpWebRequest.SetResponseData

(System.Net.WebConnectionData data) [0x00000] in :0

10-02 14:54:31.413 I/mono-stdout( 8641): --- End of inner exception

stack trace --- --- End of inner exception stack trace --- -->

(Inner exception 0) System.Net.WebException: The remote server

returned an error: (400) Bad Request. 10-02 14:54:31.423

I/mono-stdout( 8641): --> (Inner exception 0)

System.Net.WebException: The remote server returned an error: (400)

Bad Request. 10-02 14:54:31.423 I/mono-stdout( 8641): at

System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult

result) [0x00000] in :0 at

System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult

result) [0x00000] in :0 10-02 14:54:31.423

I/mono-stdout( 8641): at System.Net.HttpWebRequest.SetResponseData

(System.Net.WebConnectionData data) [0x00000] in :0

at System.Net.HttpWebRequest.SetResponseData

(System.Net.WebConnectionData data) [0x00000] in :0

Any ideas on what I'm missing?

网友答案:

I've fixed the problem by using RestSharp instead;

        // https://developer.foursquare.com/docs/venues/explore
    public string GetVenues()
    {
        var @params = new Dictionary<string, string>
            {
                {"v", "20120321"},
                {"ll", "44.3,37.2"}
            };

        var response = this.Request("venues/explore", @params);

        return response;
    }

    private string Request(string endpoint, Dictionary<string, string> @params = null, HttpMethod httpMethod = HttpMethod.GET, bool userless = false)
    {
        var client = new RestClient("https://api.foursquare.com/v2/");            
        var request = new RestRequest(endpoint, Method.GET);

        if (!userless)
        {
            // About userless requests - https://developer.foursquare.com/overview/auth.html - Some of our endpoints that don’t pertain to 
            // specific user information, such as venues search are enabled for userless access (meaning you don’t need to have a user auth your 
            // app for access). To make a userless request, specify your consumer key's Client ID and Secret instead of an auth token in the request URL.

            request.AddParameter("oauth_token", this.Account.Properties["access_token"]);
        }

        if (@params != null)
        {
            foreach (var param in @params)
            {
                request.AddParameter(param.Key, param.Value);
            }
        }

        var response = client.Execute(request);
        var content = response.Content; // raw content as string

        return content;
    }
网友答案:

I just used your very first code, but added the "oauth_token" parameter manually and it works just fine :)

My code looks something like this:

var @params = new Dictionary<string, string>
        {
            {"oauth_token", this.Account.Properties["access_token"]},
            {"v", "20120321"},
            {"ll", "44.3,37.2"}
        };
相关阅读:
Top