/// <summary>
        /// Gets the login uri.
        /// </summary>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <returns>
        /// Returns the facebook login uri.
        /// </returns>
        /// <remarks>
        /// http://developers.facebook.com/docs/reference/dialogs/oauth
        /// Parameters that can be used:
        ///     client_id     : Your application's identifier. This is called client_id instead of app_id for this particular method to be compliant with the OAuth 2.0 specification. Required, but automatically specified by most SDKs.
        ///     redirect_uri  : The URL to redirect to after the user clicks a button on the dialog. Required, but automatically specified by most SDKs.
        ///     scope         : Optional. A comma-delimited list of permissions.
        ///     state         : Optional. An opaque string used to maintain application state between the request and callback. When Facebook redirects the user back to your redirect_uri, this value will be included unchanged in the response.
        ///     response_type : Optional, default is token. The requested response: an access token (token), an authorization code (code), or both (code_and_token).
        ///     display       : The display mode in which to render the dialog. The default is page on the www subdomain and wap on the m subdomain. This is automatically specified by most SDKs. (For WP7 builds it is set to touch.)
        /// </remarks>
        public Uri GetLoginUrl(IDictionary <string, object> parameters)
        {
            Contract.Ensures(Contract.Result <Uri>() != null);

            var defaultParameters = new Dictionary <string, object>();

            defaultParameters["client_id"]    = AppId;
            defaultParameters["redirect_uri"] = RedirectUri ?? new Uri("http://www.facebook.com/connect/login_success.html");
#if WINDOWS_PHONE
            defaultParameters["display"] = "touch";
#endif
            var mergedParameters = FacebookUtils.Merge(defaultParameters, parameters);

            // check if client_id and redirect_uri is not null or empty.
            if (mergedParameters["client_id"] == null || string.IsNullOrEmpty(mergedParameters["client_id"].ToString()))
            {
                throw new ArgumentException("client_id required.");
            }

            if (mergedParameters["redirect_uri"] == null || string.IsNullOrEmpty(mergedParameters["redirect_uri"].ToString()))
            {
                throw new ArgumentException("redirect_uri required.");
            }

            // seems like if we don't do this and rather pass the original uri object,
            // it seems to have http://localhost:80/csharpsamples instead of
            // http://localhost/csharpsamples
            // notice the port number, that shouldn't be there.
            // this seems to happen for iis hosted apps.
            mergedParameters["redirect_uri"] = mergedParameters["redirect_uri"].ToString();

            var url = "http://www.facebook.com/dialog/oauth/?" + FacebookUtils.ToJsonQueryString(mergedParameters);

            return(new Uri(url));
        }
        /// <summary>
        /// Gets the logout url.
        /// </summary>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <returns>
        /// Returns the logout url.
        /// </returns>
        public Uri GetLogoutUrl(IDictionary <string, object> parameters)
        {
            // more information on this at http://stackoverflow.com/questions/2764436/facebook-oauth-logout
            var uriBuilder = new UriBuilder("http://m.facebook.com/logout.php");

            var defaultParams = new Dictionary <string, object>();

            defaultParams["confirm"] = 1;
            defaultParams["next"]    = RedirectUri ?? new Uri("http://www.facebook.com");

            var mergedParameters = FacebookUtils.Merge(defaultParams, parameters);

            if (mergedParameters["next"] == null)
            {
                mergedParameters.Remove("next");
            }
            else
            {
                mergedParameters["next"] = mergedParameters["next"].ToString();
            }

            uriBuilder.Query = FacebookUtils.ToJsonQueryString(mergedParameters);

            return(uriBuilder.Uri);
        }
예제 #3
0
        internal protected virtual void ApiAsync(string path, IDictionary <string, object> parameters, HttpMethod httpMethod, object userToken)
        {
            var mergedParameters = FacebookUtils.Merge(null, parameters);

            if (!mergedParameters.ContainsKey("access_token") && !String.IsNullOrEmpty(AccessToken))
            {
                mergedParameters["access_token"] = AccessToken;
            }

            Uri    requestUrl;
            string contentType;

            byte[] postData = BuildRequestData(path, mergedParameters, httpMethod, out requestUrl, out contentType);

            var tempState = new WebClientStateContainer
            {
                UserState  = userToken,
                Method     = httpMethod,
                RequestUri = requestUrl
            };

            Action <string, Exception> callback =
                (json, ex) =>
            {
                byte[] result = null;

                if (ex == null)
                {
                    result = Encoding.UTF8.GetBytes(json);
                }

                if (httpMethod == HttpMethod.Get)
                {
                    DownloadDataCompleted(this, new DownloadDataCompletedEventArgsWrapper(ex, false, tempState, result));
                }
                else
                {
                    UploadDataCompleted(this, new UploadDataCompletedEventArgsWrapper(ex, false, tempState, result));
                }
            };

            var request = (HttpWebRequest)HttpWebRequest.Create(requestUrl);

            request.Method = FacebookUtils.ConvertToString(httpMethod); // Set the http method GET, POST, etc.

            if (httpMethod == HttpMethod.Post)
            {
                if (path == null && mergedParameters.ContainsKey("batch"))
                {
                    tempState.IsBatchRequest = true;
                }

                request.ContentType = contentType;
                request.BeginGetRequestStream((ar) => { RequestCallback(ar, postData, callback, tempState); }, request);
            }
            else
            {
                request.BeginGetResponse((ar) => { ResponseCallback(ar, callback, tempState); }, request);
            }
        }
예제 #4
0
        internal protected virtual object Api(string path, IDictionary <string, object> parameters, HttpMethod httpMethod, Type resultType)
        {
            var mergedParameters = FacebookUtils.Merge(null, parameters);

            if (!mergedParameters.ContainsKey("access_token") && !string.IsNullOrEmpty(AccessToken))
            {
                mergedParameters["access_token"] = AccessToken;
            }

            Uri    requestUrl;
            string contentType;

            byte[] postData = BuildRequestData(path, mergedParameters, httpMethod, out requestUrl, out contentType);

            var jsonString = MakeRequest(httpMethod, requestUrl, postData, contentType);

            var json = JsonSerializer.Current.DeserializeObject(jsonString);

            FacebookApiException facebookApiException =
                ExceptionFactory.GetGraphException(json) ??
                ExceptionFactory.CheckForRestException(DomainMaps, requestUrl, json);

            if (facebookApiException != null)
            {
                throw facebookApiException;
            }

            return(resultType == null ? json : JsonSerializer.Current.DeserializeObject(jsonString, resultType));
        }
예제 #5
0
        /// <summary>
        /// Internal method for parsing the Facebook oauth ur..
        /// </summary>
        /// <param name="uri">
        /// The url to parse.
        /// </param>
        /// <param name="throws">
        /// Whether to throw the exception or not incase an error occurs.
        /// </param>
        /// <returns>
        /// The <see cref="FacebookOAuthResult"/>.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Throws if cannot parse the specified url.
        /// </exception>
        private static FacebookOAuthResult Parse(Uri uri, bool throws)
        {
            IDictionary <string, object> parameters = null;

            try
            {
                bool found = false;
                if (!string.IsNullOrEmpty(uri.Fragment))
                {
                    // #access_token and expires_in are in fragment
                    var fragment = uri.Fragment.Substring(1);
                    parameters = FacebookUtils.ParseUrlQueryString(fragment);
                    if (parameters.ContainsKey("access_token"))
                    {
                        found = true;
                    }
                }

                // code, state, error_reason, error and error_description are in query
                // ?error_reason=user_denied&error=access_denied&error_description=The+user+denied+your+request.
                var queryPart = FacebookUtils.ParseUrlQueryString(uri.Query);
                if (queryPart.ContainsKey("code") || (queryPart.ContainsKey("error") && queryPart.ContainsKey("error_description")))
                {
                    found = true;
                }

                if (found)
                {
                    parameters = FacebookUtils.Merge(parameters, queryPart);
                    return(new FacebookOAuthResult(parameters));
                }
            }
            catch
            {
                if (throws)
                {
                    throw;
                }

                return(null);
            }

            if (throws)
            {
                throw new InvalidOperationException("Could not parse authentication url.");
            }

            return(null);
        }
        /// <summary>
        /// Gets the login url.
        /// </summary>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <returns>
        /// Returns the Facebook login url.
        /// </returns>
        /// <remarks>
        /// http://developers.facebook.com/docs/reference/dialogs/oauth
        /// Parameters that can be used:
        ///     client_id     : Your application's identifier. This is called client_id instead of app_id for this particular method to be compliant with the OAuth 2.0 specification. Required, but automatically specified by most SDKs.
        ///     redirect_uri  : The URL to redirect to after the user clicks a button on the dialog. Required, but automatically specified by most SDKs.
        ///     scope         : Optional. A comma-delimited list of permissions.
        ///     state         : Optional. An opaque string used to maintain application state between the request and callback. When Facebook redirects the user back to your redirect_uri, this value will be included unchanged in the response.
        ///     response_type : Optional, default is token. The requested response: an access token (token), an authorization code (code), or both (code token).
        ///     display       : The display mode in which to render the dialog. The default is page on the www subdomain and wap on the m subdomain. This is automatically specified by most SDKs. (For WP7 builds it is set to touch.)
        /// </remarks>
        public virtual Uri GetLoginUrl(IDictionary <string, object> parameters)
        {
            var defaultParameters = new Dictionary <string, object>();

            defaultParameters["client_id"]    = AppId;
            defaultParameters["redirect_uri"] = RedirectUri ?? new Uri("http://www.facebook.com/connect/login_success.html");
#if WINDOWS_PHONE
            defaultParameters["display"] = "touch";
#endif
            var mergedParameters = FacebookUtils.Merge(defaultParameters, parameters);

            // check if client_id and redirect_uri is not null or empty.
            if (mergedParameters["client_id"] == null || string.IsNullOrEmpty(mergedParameters["client_id"].ToString()))
            {
                throw new ArgumentException("client_id required.");
            }

            if (mergedParameters["redirect_uri"] == null || string.IsNullOrEmpty(mergedParameters["redirect_uri"].ToString()))
            {
                throw new ArgumentException("redirect_uri required.");
            }

            // seems like if we don't do this and rather pass the original uri object,
            // it seems to have http://localhost:80/csharpsamples instead of
            // http://localhost/csharpsamples
            // notice the port number, that shouldn't be there.
            // this seems to happen for iis hosted apps.
            mergedParameters["redirect_uri"] = mergedParameters["redirect_uri"].ToString();

            var url = "http://www.facebook.com/dialog/oauth/?" + FacebookUtils.ToJsonQueryString(mergedParameters);

            // In order to be compliant with the OAuth spec Facebook have made changes to their auth APIs.
            // As part of this update, they will be deprecating 'code_and_token' and need developers
            // to use 'code%20token'. Everything is identical, just replace '_and_' with encoded
            // <space> '%20'.
            // url = url.Replace("response_type=code+token", "response_type=code%20token");

            return(new Uri(url));
        }
예제 #7
0
        /// <summary>
        /// Converts the facebook batch to POST parameters.
        /// </summary>
        /// <param name="batchParameter">
        /// The batch parameter.
        /// </param>
        /// <returns>
        /// The post parameters.
        /// </returns>
        protected IDictionary <string, object> ToParameters(FacebookBatchParameter batchParameter)
        {
            Contract.Requires(batchParameter != null);
            Contract.Ensures(Contract.Result <IDictionary <string, object> >() != null);

            IDictionary <string, object> returnResult = null;

            var defaultParameters = new Dictionary <string, object>();

            defaultParameters["method"] = FacebookUtils.ConvertToString(batchParameter.HttpMethod);

            IDictionary <string, object> parameters = null;

            if (batchParameter.Parameters == null)
            {
                parameters = new Dictionary <string, object>();
            }
            else
            {
                if (batchParameter.Parameters is IDictionary <string, object> )
                {
                    parameters = (IDictionary <string, object>)batchParameter.Parameters;
                }
                else
                {
                    parameters = FacebookUtils.ToDictionary(batchParameter.Parameters);
                }
            }

            var    path        = FacebookUtils.ParseQueryParametersToDictionary(batchParameter.Path, parameters);
            string queryString = string.Empty;

            if (batchParameter.HttpMethod == HttpMethod.Get)
            {
                queryString = FacebookUtils.ToJsonQueryString(parameters);
            }
            else
            {
                defaultParameters["body"] = FacebookUtils.ToJsonQueryString(parameters);
            }

            var relativeUrl = new StringBuilder(path);

            if (!string.IsNullOrEmpty(queryString))
            {
                relativeUrl.AppendFormat("?{0}", queryString);
            }

            defaultParameters["relative_url"] = relativeUrl.ToString();

            var data = batchParameter.Data;

            if (data == null)
            {
                returnResult = defaultParameters;
            }
            else
            {
                if (!(data is IDictionary <string, object>))
                {
                    data = FacebookUtils.ToDictionary(batchParameter.Data);
                }

                returnResult = FacebookUtils.Merge(defaultParameters, (IDictionary <string, object>)data);
            }

            return(returnResult);
        }