开发者

Accessing Yelp's OAuth 1.0a API with DotNetOpenAuth

Has anyone had success using DotNetOpenAuth to access Yelp's v2 api using DotNetOpenAuth?

After digging through the examples and the source, this is what I came up with:

public class YelpConnector
{               
    private static readonly string YelpConsumerKey = ConfigurationManager.AppSettings["YelpConsumerKey"];
    private static readonly string YelpConsumerSecret = ConfigurationManager.AppSettings["YelpConsumerSecret"];
    private static readonly string YelpToken = ConfigurationManager.AppSettings["YelpToken"];
    private static readonly string YelpTokenSecret = ConfigurationManager.AppSettings["YelpTokenSecret"];
    private static readonly InMemoryTokenManager tokenManager = new InMemoryTokenManager(YelpConsumerKey, YelpConsumerSecret, YelpToken, YelpTokenSecret);
    private static readonly Uri YelpURLBase = new Uri("http://api.yelp.com/v2/");        
    private static readonly ServiceProviderDescription YelpServiceDescription = new ServiceProviderDescription {
        RequestTokenEndpoint = null,
        UserAuthorizationEndpoint = null,
        AccessTokenEndpoint = null,
        TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
    };

    private static dynamic SearchBase(string queryString)
    {
        if (string.IsNullOrEmpty(queryString))
            throw new ArgumentNullException();
        var searchEndpoint = new MessageReceivingEndpoint(new Uri(YelpURLBase, "search?" + queryString), HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest);
        var consumer = new WebConsumer(YelpServiceDescription, tokenManager);
        try
        {
            using (IncomingWebResponse response = consumer.PrepareAuthorizedRequestAndSend(searchEndpoint, YelpToken))
            {
                string rs = response.GetResponseReader().ReadToEnd();
                dynamic js = SimpleJson.SimpleJson.DeserializeObject(rs);
                return js;
            }
        }
        catch (Exception e)
        {
            ErrorSignal.FromCurrentContext().Raise(e);
            return null;
        }            
    }
    internal class InMemoryTokenManager : IConsumerTokenManager
    {
        private Dictionary<string, string> tokensAndSecrets = new Dictionary<string, string>();

        public InMemoryTokenManager(string consumerKey, string consumerSecret, string token, string secret)
        {
            if (String.IsNullOrEmpty(consumerKey))
            {
                throw new ArgumentNullException("consumerKey");
            }
            this.tokensAndSecrets[token] = secret;
            this.ConsumerKey = consumerKey;
            this.ConsumerSecret = consumerSecret;
        }

        public string ConsumerKey { get; private set; }

        public string ConsumerSecret { get; private set; }

        public string GetTokenSecret(string token)
        {
            return this.tokensAndSecrets[token];
        }

        public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response)
        {
            this.tokensAndSecrets[response.Token] = response.TokenSecret;
        }

        public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret)
        {
            this.tokensAndSecrets.Remove(requestToken);
            this.tokensAndSecrets[accessToken] = accessTokenSecret;
        }

        public TokenType GetTokenType(string token)
        {
            throw new NotImplementedException();
        }           
    }
 }

If I pass in the fo开发者_StackOverflow社区llowing QueryString limit=5&category_filter=movietheaters,bars,cafe,museums,danceclubs,parks&ll=37.78364455,-122.464104, I get an exception saying "Precondition failed.: value != null" and a stacktrace of:

at System.Diagnostics.Contracts.__ContractsRuntime.Requires[TException](Boolean condition, String message, String conditionText)
at DotNetOpenAuth.Messaging.MessagingUtilities.EscapeUriDataStringRfc3986(String value)
at DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementBase.ConstructSignatureBaseString(ITamperResistantOAuthMessage message, MessageDictionary messageDictionary)
at DotNetOpenAuth.OAuth.ChannelElements.HmacSha1SigningBindingElement.GetSignature(ITamperResistantOAuthMessage message)
at DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementBase.ProcessOutgoingMessage(IProtocolMessage message)
at DotNetOpenAuth.OAuth.ChannelElements.SigningBindingElementChain.ProcessOutgoingMessage(IProtocolMessage message)
at DotNetOpenAuth.Messaging.Channel.ProcessOutgoingMessage(IProtocolMessage message)
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.InitializeRequest(IDirectedProtocolMessage request)
at DotNetOpenAuth.OAuth.ConsumerBase.PrepareAuthorizedRequestAndSend(MessageReceivingEndpoint endpoint, String accessToken)
at MeetPpl.Helpers.SocialConnectors.YelpConnector.SearchBase(String queryString)

Any suggestions? Am I on the right trail?


I struggled with this issue for 1 whole day before giving up on dotnetopenauth. I found a very simple way to search yelp using the oauth library of http://www.twitterizer.net/ . Simply download the lite version of twitterizer and use my sample code below.

Download link is http://www.twitterizer.net/files/Twitterizer2lite-2.3.2.zip

    public static string search()
    {
        string yelpSearchURL = "http://api.yelp.com/v2/search?term=food&location=San+Francisco";
        string yelpConsumerKey = "your key";
        string yelpConsumerSecret = "your secret";
        string yelpRequestToken = "your token";
        string yelpRequestTokenSecret = "your token secret";

        Twitterizer.OAuthTokens ot = new Twitterizer.OAuthTokens();
        ot.AccessToken = yelpRequestToken;
        ot.AccessTokenSecret = yelpRequestTokenSecret;
        ot.ConsumerKey = yelpConsumerKey;
        ot.ConsumerSecret = yelpConsumerSecret;

        string formattedUri = String.Format(CultureInfo.InvariantCulture,
                             yelpSearchURL, "");
        Uri url = new Uri(formattedUri);
        Twitterizer.WebRequestBuilder wb = new Twitterizer.WebRequestBuilder(url, Twitterizer.HTTPVerb.GET, ot);
        System.Net.HttpWebResponse wr = wb.ExecuteRequest();
        StreamReader sr = new StreamReader(wr.GetResponseStream());
        return sr.ReadToEnd();
    }


You can use RestSharp api: https://github.com/JustinBeckwith/YelpSharp in combination with OAuthBase: http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs. In YelpSharp implementation change Yelp.cs class method makeRequest with this:

protected string makeRequest(string area, string id, Dictionary<string, string> parameters)
        {
            // build the url with parameters
            var url = area;

            if (!String.IsNullOrEmpty(id)) url += "/" + HttpUtility.UrlEncode(id);

            if (parameters != null)
            {
                bool firstp = true;
                string[] keys = parameters.Keys.ToArray();
                foreach (string _key in keys)
                {
                    if (firstp) url += "?";
                    else url += "&";

                    firstp = false;
                    //Double URL encode "&" to prevent restsharp from treating the second half of the string as a new parameter
                    parameters[_key] = parameters[_key].Replace("&", "%26");
                    parameters[_key] = parameters[_key].Replace("+", "%2B");
                    parameters[_key] = parameters[_key].Replace(" ", "%2B");

                    url += _key + "=" + parameters[_key]; //HttpUtility.UrlEncode(parameters[_key]);
                }
            }

            var client = new RestClient(rootUri);

            var request = new RestRequest(Method.GET);

            OAuthBase oAuth = new OAuthBase();
            string nonce = oAuth.GenerateNonce();
            string timeStamp = oAuth.GenerateTimeStamp();
            string normalizedUrl;
            string normalizedRequestParameters;

            string sig = oAuth.GenerateSignature(new Uri(string.Format("{0}/{1}", client.BaseUrl, url)),
                options.ConsumerKey, options.ConsumerSecret,
                options.AccessToken, options.AccessTokenSecret,
                "GET", timeStamp, nonce, out normalizedUrl, out normalizedRequestParameters);

            sig = HttpUtility.UrlEncode(sig);

            request.Resource = string.Format(area);

            if (parameters != null)
            {
                foreach (var p in parameters)
                {
                    request.AddParameter(p.Key, p.Value);
                }
            }

            request.AddParameter("oauth_consumer_key", options.ConsumerKey);
            request.AddParameter("oauth_token", options.AccessToken);
            request.AddParameter("oauth_nonce", nonce);
            request.AddParameter("oauth_timestamp", timeStamp);
            request.AddParameter("oauth_signature_method", "HMAC-SHA1");
            request.AddParameter("oauth_version", "1.0");
            request.AddParameter("oauth_signature", sig);

            var response = client.Execute(request);

            return response.Content;
        }

Test like this:

public void testYelp()
{
    string _term = "food";
            string _location = "San Francisco";


            var o = Credentials.GetOptions();
            var y = new Yelp(o);

            var searchOptions = new SearchOptions();
            searchOptions.GeneralOptions = new GeneralOptions()
            {
                term = _term
            };

            searchOptions.LocationOptions = new LocationOptions()
            {
                location = _location
            };


            var results = y.Search(searchOptions);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜