Blog

Tagged by 'facebook'

  • Don’t you love the good ol’ days back when querying API’s provided by social platforms was a straight forward process and at a time when it felt like there were fewer barriers for entry. This thought came to mind when I had to use Instagram’s API feed again recently to output a list of photos for one of my personal projects.

    The last time I carried out any interaction with Instagram's API was back in 2013 where it was a much more simpler affair. All that was required is to generate an access token that never expired, which could then be used against any API endpoint to get data back from Instagram.

    Reading Jamie Maguires really useful three-part blog post on tapping into Instagrams API gave me a good foundation into how the API has changed since I used it last. But the example he used required the profile you wanted to interact with had to be set up as a business user. However, interacting with Instagram’s API requires a lot more effort if you (like most users) do not have a business profile.

    As far as I understand it, if you plan on making any interaction with Instagrams API as a non-business user the process is:

    1. Create Facebook Developer App
    2. Authenticate application by logging into the Instagram account. This will then generate a short-lived token valid for 1 hour.
    3. Exchange the short-lived token for a long-lived token that is valid for 60 days. This token will need to be stored somewhere at the application level.
    4. Ensure the long-lived token is refreshed before it expires within the 60-day window.

    It is very important that we are using the long-lived token and to continually renew it by having some form of background process that carries out this check, whether this is at application or Azure level. We can then use this token to make queries to Instagram API endpoints.

    In this post, I am going to perform very simple integration to output a list of images from an Instagram profile. By demonstrating this, we should then get a fair idea on how to interact with the other API endpoints. Personally, setting everything up the process to acquire an access-token is the part that requires the most effort. So let's get to it!

    Create a Facebook Developer Application

    Since Facebook has taken over Instagram, naturally the application process starts within Facebook's developer site, which can be found at: https://developers.facebook.com/apps/. Once you have logged in using your Facebook credentials, the following steps will need to be carried out:

    • Select "Add New App". In the popup, enter the application name and contact email.
    • You will be presented with a list of products. Select "Instagram" by pressing the "Setup" button.
    • From the left-hand navigation, go to: Settings > Basic. Scroll to the bottom and click on the "Add platform" button. From the popup, select "Website".
    • Enter the website URL. For testing, this will be the URL we set up in the previous section. Ensure this URL is prefixed with https://. Click the "Save" button.
    • Again, from the left-hand navigation (under Products > Instagram), select: "Basic Display". At the bottom of the page, click the "Create New App" button.
    • Enter the following fields (based on our test domain):
    • Valid OAuth Redirect URIs: https://myinstagramapp.surinderbhomra.com/Instagram/Auth
    • Deauthorize Callback URL: https://myinstagramapp.surinderbhomra.com
    • Data Deletion Requests: https://myinstagramapp.surinderbhomra.com
    • Add an Instagram Test user. This can be the clients Instagram profile name.
    • Add instagram_graph_user_media permission, so we can read the profile images.
    • Click "Save Changes" button.

    You will have noticed I have added website URL’s for the OAuth Redirect, Deauthorize Redirect and Deletion Request fields. As these fields are required, you can enter the dummy website URL for local development purposes. Just remember to change this when you move the application to the live domain. In the meantime to utilise those dummy URL’s, your local host file will need to be updated. Please refer to a post I wrote in 2012 for further information. It might be over 8 years old, but the process is the same even if the Facebook Developer interface has changed.

    Once the Developer Application has been set up, grab the App ID and App Secret to be used in our demo application.

    Photo Feed Application

    The Photo Feed application will provide a very simple demonstration of the authentication process and interacting with the API to get back our media objects. From here, you will have the tools to improve and expand on this to delve deeper into other API endpoints Instagram has to offer.

    To start, we have two helper classes that the application will rely on:

    1. InstagramAuthProvider
    2. InstagramMediaProvider

    InstagramAuthProvider

    The InstagramAuthProvider carries out all authentication processes for acquiring both short and long-lived tokens.

    public class InstagramAuthProvider
    {
        #region Json Response Objects
    
        public class AuthenticateRequest
        {
            [JsonProperty("error_type")]
            public string ErrorType { get; set; }
    
            [JsonProperty("code")]
            public int StatusCode { get; set; }
    
            [JsonProperty("error_message")]
            public string ErrorMessage { get; set; }
    
            [JsonProperty("access_token")]
            public string AccessToken { get; set; }
    
            [JsonProperty("user_id")]
            public long UserId { get; set; }
        }
    
        public class LongLivedTokenRequest
        {
            [JsonProperty("access_token")]
            public string AccessToken { get; set; }
    
            [JsonProperty("token_type")]
            public string TokenType { get; set; }
    
            [JsonProperty("expires_in")]
            public long ExpiresInSeconds { get; set; }
        }
    
        #endregion
    
        /// <summary>
        /// Carries out initial authentication approach after user had approved app to Instagram account link.
        /// Returns a short-lived token valid for 1 hour.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static async Task<AuthenticateRequest> GetAccessTokenAsync(string code)
        {
            string authResponse = string.Empty;
    
            if (!string.IsNullOrEmpty(code))
            {
                Dictionary<string, string> parameters = new Dictionary<string, string>
                    {
                        { "client_id", ConfigurationManager.AppSettings["Instagram.ClientID"].ToString() },
                        { "client_secret", ConfigurationManager.AppSettings["Instagram.AppSecret"].ToString() },
                        { "grant_type", "authorization_code" },
                        { "redirect_uri", $"{ConfigurationManager.AppSettings[“Site.Domain"]}{ConfigurationManager.AppSettings["Instagram.AuthRedirectPath"]}" },
                        { "code", code }
                    };
    
                FormUrlEncodedContent encodedParameters = new FormUrlEncodedContent(parameters);
    
                HttpClient client = new HttpClient();
    
                HttpResponseMessage response = await client.PostAsync("https://api.instagram.com/oauth/access_token", encodedParameters);
                authResponse = await response.Content.ReadAsStringAsync();
            }
    
            return JsonConvert.DeserializeObject<AuthenticateRequest>(authResponse);
        }
    
        /// <summary>
        /// Exchanges a short-lived token for a long-lived token that are valid for 60 days.
        /// </summary>
        /// <param name="shortliveAccessToken"></param>
        /// <returns></returns>
        public static async Task<LongLivedTokenRequest> GetLongLifeTokenAsync(string shortliveAccessToken)
        {
            string authResponse = string.Empty;
    
            if (!string.IsNullOrEmpty(shortliveAccessToken))
            {
                HttpClient client = new HttpClient();
    
                HttpResponseMessage response = await client.GetAsync($"https://graph.instagram.com/access_token?client_secret={ConfigurationManager.AppSettings["Instagram.AppSecret"].ToString()}&grant_type=ig_exchange_token&access_token={shortliveAccessToken}");
                authResponse = await response.Content.ReadAsStringAsync();
            }
    
            return JsonConvert.DeserializeObject<LongLivedTokenRequest>(authResponse);
        }
    
        /// <summary>
        /// Refresh a long-lived Instagram User Access Token that is at least 24 hours old but has not expired.
        /// </summary>
        /// <param name="longLivedAccessToken"></param>
        /// <returns></returns>
        public static async Task<LongLivedTokenRequest> RefreshTokenAsync(string longLivedAccessToken)
        {
            string authResponse = string.Empty;
    
            if (!string.IsNullOrEmpty(longLivedAccessToken))
            {
                HttpClient client = new HttpClient();
    
                HttpResponseMessage response = await client.GetAsync($"https://graph.instagram.com/refresh_access_token?grant_type=ig_refresh_token&access_token={longLivedAccessToken}");
                authResponse = await response.Content.ReadAsStringAsync();
            }
    
            return JsonConvert.DeserializeObject<LongLivedTokenRequest>(authResponse);
        }
    }
    

    InstagramMediaProvider

    The InstagramMediaProvider returns media information based on the authentication token.

    public class InstagramMediaProvider
    {
        #region Json Response Objects
    
        public class MediaCollection
        {
            [JsonProperty("data")]
            public List<MediaInfo> Data { get; set; }
        }
    
        public class MediaInfo
        {
            [JsonProperty("id")]
            public string Id { get; set; }
    
            [JsonProperty("caption")]
            public string Caption { get; set; }
    
            [JsonProperty("permalink")]
            public string InstagramUrl { get; set; }
    
            [JsonProperty("media_type")]
            public string Type { get; set; }
    
            [JsonProperty("thumbnail_url")]
            public string VideoThumbnailUrl { get; set; }
    
            [JsonProperty("media_url")]
            public string Url { get; set; }
        }
    
        #endregion
    
        private string _accessToken;
    
        public InstagramMediaProvider(string accessToken)
        {
            _accessToken = accessToken;
        }
    
        /// <summary>
        /// Gets list of all user images.
        /// </summary>
        /// <returns></returns>
        public async Task<List<MediaInfo>> GetUserMedia()
        {
            var mediaInfo = await GetAllMediaAsync();
    
            if (mediaInfo?.Data.Count > 0)
                return mediaInfo.Data;
            else
                return new List<MediaInfo>();
        }
    
        /// <summary>
        /// Outputs information about a single media item.
        /// </summary>
        /// <returns></returns>
        private async Task<MediaCollection> GetAllMediaAsync()
        {
            string mediaResponse = string.Empty;
    
            HttpClient client = new HttpClient();
    
            HttpResponseMessage response = await client.GetAsync($"https://graph.instagram.com/me/media?fields=id,media_type,media_url,thumbnail_url,permalink,caption,timestamp&access_token={_accessToken}");
    
            mediaResponse = await response.Content.ReadAsStringAsync();
    
            if (response.StatusCode != HttpStatusCode.OK)
                return null;
    
            return JsonConvert.DeserializeObject<MediaCollection>(mediaResponse);
        }
    }
    

    Authorisation and Authentication

    The authorisation and authentication functionality will be performed in the InstagramController.

    public class InstagramController : Controller
    {
         /// <summary>
         /// Authorises application with Instagram.
         /// </summary>
         /// <returns></returns>
        public ActionResult Authorise()
        {
            return Redirect($"https://www.instagram.com/oauth/authorize?client_id={ConfigurationManager.AppSettings["Instagram.AppID"].ToString()}&redirect_uri={ConfigurationManager.AppSettings[“Site.Domain"]}{ConfigurationManager.AppSettings["Instagram.AuthRedirectPath"]}&scope=user_profile,user_media&response_type=code");
        }
    
        /// <summary>
        /// Makes authentication request to create access token.
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public async Task<ActionResult> Auth(string code)
        {
            InstagramAuthProvider.AuthenticateRequest instaAuth = await InstagramAuthProvider.GetAccessTokenAsync(code);
    
            if (!string.IsNullOrEmpty(instaAuth?.AccessToken))
            {
                InstagramAuthProvider.LongLivedTokenRequest longTokenRequest = await InstagramAuthProvider.GetLongLifeTokenAsync(instaAuth.AccessToken);
    
                if (!string.IsNullOrEmpty(longTokenRequest?.AccessToken))
                {                
                   // Storing long-live token in a session for demo purposes. 
                   // Store the token in a more permanent place, such as a database.
                    Session["InstagramAccessToken"] = longTokenRequest.AccessToken;
    
                    return Redirect("/");
                }
            }
    
            return Content("Error authenticating.");
        }
    }
    

    Authorise

    Before we can get any of our tokens, the first step is to get authorisation from Instagram against our web application. So somewhere in the application (preferably not publicly visible), we will need an area that will kick this off. In this case, by navigating to /Instagram/Authorise, will cause the Authorise action in the controller to be fired.

    All the Authorise action does is takes you to Instagrams login page and sends over the App ID and Redirect Path. Remember, the Redirect path needs to be exactly as you've set it in your Facebook Developer Application. Once you have successfully logged in, you’ll be redirected back to the application.

    NOTE: I’ll be honest here and say I am not sure if there is a better way to acquire the access token as it seems very odd to me that you have to log in to Instagram first. If any of you know of a better way, please leave a comment.

    Auth

    If the authorise process was successful, you will be redirected back the application and be given an authorisation code. The authorisation code will be parsed to the InstagramAuthProvider.GetAccessTokenAsync() method to be exchanged for our first access-token valid - short-lived valid for 1 hour.

    The last step of the process is to now send the short-lived access token to the InstagramAuthProvider.GetLongLifeTokenAsync() method that will carry out a final exchange to retrieve our long-life token valid for 60 days. It is this token we need to store somewhere so we can use it against any Instagram API endpoint.

    In my example, the long-life token is stored in a Session for demonstration purposes. In a real-world application, we would want to store this in a database somewhere and have a scheduled task in place that will call the InstagramAuthProvider.RefreshTokenAsync() method every 59 days for the long life token to be renewed for another 60 days.

    Photo Feed

    Now we come onto the easy part - use the long-live access token to return a list of photos.

    public class InstagramMediaController : Controller
    {
        /// <summary>
        /// Outputs all user images from Instagram profile.
        /// </summary>
        /// <returns></returns>
        [OutputCache(Duration = 60)]
        public PartialViewResult PhotoGallery()
        {
            if (Session["InstagramAccessToken"] != null)
            {
                InstagramMediaProvider instaMedia = new InstagramMediaProvider(Session["InstagramAccessToken"].ToString());
    
                return PartialView("_PhotoGallery", Task.Run(() => instaMedia.GetUserMedia()).Result);
            }
    
            return PartialView("_PhotoGallery", new List<InstagramMediaProvider.MediaInfo>());
        }
    }
    

    This controller contains a single piece of functionality - a PhotoGallery partial view. The PhotoGallery partial view uses the InstagramMediaProvider.GetUserMedia() method to return a collection of profile photos.

    Final Thoughts

    Before carrying out any Instagram integration, think about what you are trying to achieve. Look through the documentation to ensure the API's you require are available as some permissions and features may require business or individual verification to access live data.

    Also, you may (or may not) have noticed whilst going through the Facebook Development Application setup that I never submitted the application for review. I would advise you to always submit your application to Facebook as you might find your access is revoked. For personal purposes where you're only outputting your own Instagram profile information, you could just leave it "In development" mode. But again, I do not advise this, especially when working with Business accounts.

  • For a site I'm working on, the Facebook's Comments plugin is being utilised on all our article pages. There was a requirement to pull in the latest comments in a listing page for each of these article pages as well as number of comments. Facebook's JavaScript library provides the ability to display a comments counter but not the ability to pull out x number of comments. So we'll have to go server-side and use Graph API to get the data we want.

    In this post, I will show you how you can get back all comments for a page by it's full URL.

    Prerequisites

    Before we get into the main C# logic methods, you need to make sure we have a few things in place:

    • ApiWebRequestHelper Class
    • Newtonsoft Json
    • Facebook App Settings
    • Class Objects

    ApiWebRequestHelper Class

    Whenever I am making a call to Facebook's Graph API endpoints, I will be making references to a "ApiWebRequestHelper" helper class. This is something I developed last month to make it easier for me to deserialize XML or JSON requests to a strongly-typed class object. You can take a look at the full code here.

    Newtonsoft Json

    The Newtonsoft Json library is a key ingredient to any JSON web requests. I'd be surprised if you've never heard or used it. :-) Nevertheless, you can get it here: http://www.newtonsoft.com/json.

    Facebook App Settings

    I haven't created a Facebook App for quite some time and things have changed very slightly in terms of the interface and options presented. The key things you need to get out of your created App is:

    • Application ID
    • Application Secret
    • Client Token

    I set the security settings with the following modes, which can be found in Settings > Advanced >  Security.

    Facebook App Advanced API Settings

    Class Objects

    The following class objects will be used to deserialize Graph API requests into class objects.

    The FacebookPageInfo, FacebookPage and FacebookPageShare objects will get the core information about the queried page, such as the Title and Description, as well as the comments and share counts.

    namespace Site.BusinessObjects.Facebook
    {
        public class FacebookPageInfo
        {
            [JsonProperty("id")]
            public string Id { get; set; }
    
            [JsonProperty("og_object")]
            public FacebookPage Page { get; set; }
    
            [JsonProperty("share")]
            public FacebookPageShare Share { get; set; }
        }
    
        public class FacebookPage
        {
            [JsonProperty("id")]
            public string Id { get; set; }
    
            [JsonProperty("description")]
            public string Description { get; set; }
    
            [JsonProperty("title")]
            public string Title { get; set; }
    
            [JsonProperty("type")]
            public string Type { get; set; }
    
            [JsonProperty("updated_time")]
            public DateTime UpdatedTime { get; set; }
    
            [JsonProperty("url")]
            public string Url { get; set; }
        }
    }
    
    namespace Site.BusinessObjects.Facebook
    {
        public class FacebookPageShare
        {
            [JsonProperty("comment_count")]
            public int CommentCount { get; set; }
    
            [JsonProperty("share_count")]
            public int ShareCount { get; set; }
        }
    }
    

    All comments for a page will be stored in the following objects:

    namespace Site.BusinessObjects.Facebook
    {
        public class FacebookPageCommentInfo
        {
            public int TotalComments { get; set; }
            public List<FacebookCommentItem> Comments { get; set; }
        }
    }
    
    namespace Site.BusinessObjects.Facebook
    {
        public class FacebookCommentItem
        {
            [JsonProperty("id")]
            public string Id { get; set; }
    
            [JsonProperty("created_time")]
            public DateTime CreatedTime { get; set; }
    
            [JsonProperty("from")]
            public FacebookCommentFrom From { get; set; }
    
            [JsonProperty("message")]
            public string Message { get; set; }
        }
    
        public class FacebookCommentFrom
        {
            [JsonProperty("id")]
            public string Id { get; set; }
    
            [JsonProperty("name")]
            public string Name { get; set; }
        }
    }
    

    Facebook Logic Class

    Now that we have the pre-requisites in place, lets get to the code that will perform the required functions:

    namespace Site.BusinessLogic
    {
        public class FacebookLogic
        {
            private string _accessToken;
    
            /// <summary>
            /// Uses default Client ID and Secret as set in the web.config.
            /// </summary>
            public FacebookLogic()
            {
                GetAccessToken(Config.Facebook.ClientId, Config.Facebook.ClientSecret);
            }
    
            /// <summary>
            /// Requires  Client ID and Secret.
            /// </summary>
            /// <param name="clientId"></param>
            /// <param name="clientSecret"></param>
            public FacebookLogic(string clientId, string clientSecret)
            {
                GetAccessToken(clientId, clientSecret);
            }
    
            /// <summary>
            /// Gets page info that has been shared to Facebook.
            /// </summary>
            /// <param name="pageUrl"></param>
            /// <returns></returns>
            public FacebookPageInfo GetPage(string pageUrl)
            {
                return ApiWebRequestHelper.GetJsonRequest<FacebookPageInfo>($"https://graph.facebook.com/{pageUrl}?access_token={_accessToken}");
            }
    
            /// <summary>
            /// Gets comments for a page based on its absolute URL.
            /// </summary>
            /// <param name="pageUrl"></param>
            /// <param name="maxComments"></param>
            public FacebookPageCommentInfo GetPageComments(string pageUrl, int maxComments)
            {
                try
                {
                    // Get page information in order to retrieve page ID to pass to commenting.
                    FacebookPageInfo facebookPage = GetPage(pageUrl);
    
                    if (facebookPage.Page != null)
                    {
                        return new FacebookPageCommentInfo
                        {
                            TotalComments = facebookPage.Share.CommentCount,
                            Comments = GetCommentsByPageId(facebookPage.Page.Id, maxComments).Comments
                        };
                    }
                    else
                    {
                        return null;
                    }
                }
                catch (Exception ex)
                {
                    // NOTE: Log exception here...
    
                    return null;
                }
            }
    
            /// <summary>
            /// Gets comments by Facebook's Page ID.
            /// </summary>
            /// <param name="fbPageId"></param>
            /// <param name="max"></param>
            /// <returns></returns>
            public FacebookCommentInfo GetCommentsByPageId(string fbPageId, int max = 10)
            {
                return ApiWebRequestHelper.GetJsonRequest<FacebookCommentInfo>($"https://graph.facebook.com/comments?id={fbPageId}&access_token={_accessToken}&limit={max}");
            }
    
            /// <summary>
            /// Retrieves Access Token from Facebook App.
            /// </summary>
            /// <param name="clientId"></param>
            /// <param name="clientSecret"></param>
            private void GetAccessToken(string clientId, string clientSecret)
            {
                UriBuilder builder = new UriBuilder($"https://graph.facebook.com/oauth/access_token?client_id={Config.Facebook.ClientId}&client_secret={Config.Facebook.ClientSecret}&grant_type=client_credentials");
    
                try
                {
                    using (WebClient client = new WebClient())
                    {
                        // Get Access Token from incoming response.
                        string data = client.DownloadString(builder.Uri);
    
                        NameValueCollection parsedQueryString = HttpUtility.ParseQueryString(data);
    
                        _accessToken = parsedQueryString["access_token"];
                    }
                }
                catch (Exception ex)
                {
                    // NOTE: Log exception here...
                }
            }
        }
    }
    

    By default, on initiation of the FacebookLogic class, the Application ID and Secret values will be inherited from the web.config, or you can pass in these values directly with the class overload parameters.

    Out of all the methods used here, we're interested in only using one: GetPageComments(). What you will notice from this method is that we cannot get the comments from one API call alone. We first have to make an extra API call to get the ID of the page. This ID is passed to the GetCommentsByPageId() method, to return all comments.

    Usage

    Comments for a page can be returned by adding the following in your code, where you will then be able to access properties to iterate through the comments:

    FacebookLogic fbl = new FacebookLogic();
    
    // Pass in the page URL and number of comments to be returned.
    var pageComments = fbl.GetPageComments("https://www.surinderbhomra.com/", 2);
    

    Whenever you call this piece of code, I would make sure you cache the results for 5 - 10 minutes, so you do not use up your API request limits.

  • It seems there is going to be a growing trend where apps on our mobile devices will open webpages whilst you are inside the app itself instead of using the devices' native browser. A prime example of this is Facebook. In recent updates during the tail end of last year, both their iOS and Android offerings open webpages from within the application.

    This isn't a bad thing. In fact I quite like having webpages opening within the application, since this creates a nice seamless experience. However, the Facebook in-app browser doesn't seem to render a webpage in the same manner as the devices' own native browser (Safari/Chrome). I started noticing this whilst working on a complex website that was very much custom JavaScript driven.

    The only thing I could do is modify specific mark-up or features that affected my website negatively when opened from within Facebook by detecting the user-agent. In my code (using ASP.NET C#), I was required to carry out additional browser checks:

    //User is within Facebook browser.
    if (Request.UserAgent.IndexOf("FBAN") > -1)
    {
        if (Request.UserAgent.Contains("iPhone OS 8_0_2"))
        {
            //You are using iPhone version 8.0.2.
        }
        
        if (Request.UserAgent.Contains("Chrome"))
        {
            //You are in the Facebook App in Android.
        }
    }
    else
    {
        //You are not in Facebook App.
    }
    

    You can modify the code above to create a nice self-contained method to return an enumeration as I ended up doing to be used when required.

  • Today I came across this really interesting tweet on my Twitter timeline today:

    Read about why we’re deleting our Facebook page: facebook.com/limitedpressin… — Limited Run (@limitedrun) July 30, 2012

    Limited Run, posted on their Facebook profile stating that they would be deleting their account due to the amount Facebook is charging for clicks on their advertising. Here’s the interesting part: About 80% of the clicks Facebook charged Limited Run, JavaScript wasn't on. And if the person clicking the ad doesn't have JavaScript, it's very difficult for an analytics service to verify the click. Only 1-2% of people going to their site have JavaScript disabled, not 80% like the clicks coming from Facebook.

    Interesting stuff.

    Before Limited Run takes down their Facebook profile, I’ve attached a screenshot of their post below:

    Limited Pressing Facebook Post

    Reading this post today reminded me on a news article I read on “virtual likes” and how advertising through Facebook doesn’t necessarily mean you’ll be any better off. It all comes down to the level of engagement user’s have with a profile page. If users are just liking the page and not interacting with your posts or general content, those likes are worth nothing. Some companies are wising up to the effectiveness of Facebook’s advertising strategy.

    Limited Run isn’t the first to ditch Facebook ad’s, General Motor’s pulled away from Facebook ad’s earlier this year due to the ad’s Facebook produce do not have the visual impact needed to justify the cost.

    I think certain aspects of Facebook is a joke filled mostly of people looking for attention, not an effective marketing tool.

  • Facebook ConnectIf I need to login and authenticate a Facebook user in my ASP.NET website, I either use the Facebook Connect's JavaScript library or SocialAuth.NET. Even though these two methods are sufficient for the purpose, I don't think it's the most ideal or efficient way.

    The Facebook Connect JavaScript library is quite basic and doesn't have the flexibility required for full .NET integration through FormsAuthentication. Whereas SocialAuth.NET provides full .NET integration and all authentication is done server-side with minimal development.

    I'd say if you are looking for a straight-forward way to integrate social site authentication, SocialAuth.NET is the way to go. It's API can communicate with other social sites such as Twitter, LinkedIn and Gmail.

    Recently, I found a better and more efficient way to authenticate Facebook users on my site using Graph API and Hammock.

    Hammock is a C# a REST library for .NET that greatly simplifies consuming and wrapping RESTful services. This allows us to embrace the social site’s core technology instead of using varied SDK's or API's. There are many community driven frameworks and API's readily available on the Internet, but they can really cause problems if they evolve too quickly or haven’t been thoroughly tested.

    Suddenelfilio, has written a useful blog post on connecting Facebook using Hammock. You will see by his example that you can interact with Facebook anyway you want.

    The same principle could also be applied to other website API's that use REST based services, such as Twitter.

  • Having the ability to run and develop Facebook applications within the comfort of a local environment is a must. Previously, I always thought in order to work on Facebook applications a public facing URL was required to allow Facebook to communicate with your application directly. Fortunately this is not the case.

    All you need to do is set up a server alias in your hosts file and use this alias as an “App Domain” within your Facebook Application settings.

    Quick Example

    I created a new site in Microsoft IIS called: “facebook.surinder-test.com” running under port 8008. Feel free to change the port number to your own choosing. To browse the site we need to add this web address to Windows host file (C:\Windows\System32\drivers\etc):

    # localhost name resolution is handled within DNS itself.
    #    127.0.0.1       localhost
    #    ::1             localhost
    
    127.0.0.1     facebook.surinder-test.com
    127.0.0.1     localhost
    

    This will route all your requests to ”facebook.surinder-test.com” to localhost.

    Next, make the following changes to your Facebook Application settings page:

    FB App Screen

  • Google Plus When I first heard Google were introducing their own social-networking platform, I was intrigued to say the least on what they could offer compared to the other social sites I use: Facebook and Twitter.

    As I stated in one of my earlier posts, I am more of a tweeter since I can share my blog posts easily along with my random ramblings. I think Facebook will have a problem competing alongside Twitter or Google+. Facebook is seen to be more of a personal social network rather than a open professional network and that’s its biggest downfall. It’s quite difficult to cross the boundaries between posting professional/business content alongside personal posts. Thankfully, this is something Google Plus does quite well through its new “circle’s” feature allowing complete control on who see’s what.

    I jumped at the chance of using Google Plus when I was offered an invite during the initial release. I was very impressed. Simple and straight-forward. My posts looked really beautiful within its minimalist user interface. Well what else would you expect from Google? Don’t get me started on the eye-sore that is Facebook’s new interface – I’ll leave that for another blog post.

    For me, Google Plus is like an extension of Twitter with some added benefits such as:

    • Ability to make posts private/public.
    • Follow people by adding them to a circle.
    • No character limit on the length of posts.
    • Nice interoperability with the search-daddy that is Google.

    For a new social networking site, I get a higher click-through-rate to my blog than I ever got compared to tweeting on Twitter. In the process, I managed to get more people adding me to their circle. So take any remarks regarding the inactivity of Google+ with a pinch of salt. I don’t buy it. Google encompasses a big community that you feel part of.

    I briefly touched upon the interoperability factor with Google search. People underestimate the power of having the backing of Google search. For example, what if you wrote an article and linked it to your Google+ profile? This information will be displayed as author information within search results to help users discover great content and learn more about the person who wrote the article.

    One thing that did surprise me is the fact that at this point in time there’s no advertisement. Unlike its predecessors (yes I that’s how confident I am in Google Plus), you always manage to find advertisement in some form or another. I can view my profile page without constantly having an advert rubbing my single relationship status to my face – something Facebook does far too often.

    I trust Google more with my data over Facebook any day. I know Google can’t exactly be trusted either but unlike Facebook they’re not always in the the news on a monthly basis regarding some type of data scandal. At time of writing, it is being reported Facebook is now facing a privacy suit over internet tracking.

    In conclusion, integrating ones self into Google Plus is definitely worth it. I only recently started to make more of an effort on Google+ and I find myself posting my content here over other social-networking sites. The key to making a good start is to make some of your posts public to show others your interests and even connect to these type of people either by adding them to a circle or joining a hangout.

    On a final note, if you have a Google Plus account and like what I post then why not circle me. :-)

  • Definition Of FriendI was a late bloomer when when it came to joining the social networking giant that is Facebook (around late 2007). The only reason I can remember for ever joining the site was just because all people around me were submitting their profiles like crazy. Not wanting to miss out on this new trend, I decided to “pop” my social networking cherry and take the plunge!

    Looking back on my first experience on Facebook I was amazed at how easily I could connect with friends and people I used to know from a past life (school, work etc). Within a few months my Facebook profile spread through the social networking vine in quick haste and found myself receiving friend requests. But it became ever so prevalent that the people who requested me to add them as a friend weren’t people I would necessarily call a friend. I knew of them and that is where my connection ends. So in some ways Facebook has redefined the term “friend”.

    Facebook has broken down the friendship barriers considerably. Its made it really easy. Too easy in fact. It was only a couple days ago when my sister said: “Look! I got more friends than you!”. In all honesty I wasn’t really bothered…ok maybe a little. This is where personal feelings come into play.

    One of the feelings I will call: “Facebook guilt”. Facebook guilt is when you receive a friend request and don’t act on it. You simply ignore it hoping they would just forget or even worse…remove their request altogether. Hoping by not accepting their friend request you haven’t made an enemy or caused emotional discourse.

    Then there is “Facebook rejection”. An example of this is the following conversation I had with with a work mate of mine a few years back:

    Anonymous friend: I’ve sent you a Facebook friend request. Me: Ok cool. Anonymous friend: How come you haven’t approved it yet? Me: Mate, I’ve been on holiday for over a week and haven’t checked Facebook yet. I’ll do it today. Anonymous friend: Thanks Surinder!

    I was surprised that he took not responding to his friend request as a personal hit.

    Social Networking sites have created a trend that makes us more interested in the number of people in our social circles rather than the relationships we have with them.

    So where do I stand in the social networking medium? My Facebook activity has drastically declined over the years. Currently, I have 114 friends with majority of them I know quite well and only a handful of them I haven’t really met. Nowadays, I have become more of a tweeter. I just feel that Twitter has met my social needs over Facebook. Its just more flexible and open. If someone likes you they follow you, if not they don’t.