Logging Out of Facebook with C# SDK

1

Posted by Cynic | Posted in .NET, C#, Software, Solutions to Problems, Super Simple | Posted on 22-06-2011

Tags:

FacebookLogging out of Facebook programmatically turns out to be much more problematic that you would think.

I posted the question at StackOverflow asking if anyone knew of a way to get it done. The only answer, other than mine, turned up the same results I’d been having, i.e. You just can’t logout easily.

So, I was forced to resort to nasty, dirty, hacky, ugly measures to get the job done. Using the FacebookOAuthClient.GetLogoutUrl() method didn’t work. I tried and tried and tried. I manually constructed URLs in many different combinations and permutations, and nothing worked.

The problem, as it turns out, isn’t limited to C# though, as many other developers using different SDKs and languages have had similar problems.

The general answer seems to be to use the Facebook JavaScript SDK. Huh? Well, when you’re not developing a web page, it’s kind of tough to use that SDK, and any attempt would be pretty hacky and ugly and time consuming. And then again, there’s no guarantee that it would work either.

As such, I resorted to browser automation… Ick. Yucky. It’s prone to breakage and just all-round icky. So, here’s the basics on how I am logging out of Facebook…

private void wbrFacebookAuth_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
   if (_logout)
   {
    HtmlElementCollection hec = wbrFacebookAuth.Document.GetElementsByTagName("a");
    foreach (HtmlElement elem in hec)
    {
        // the logout link has a data-sigil="logout" attribute:
        string datasigil = elem.GetAttribute("data-sigil").ToLower();
        if (datasigil == "logout")
        {
          wbrFacebookAuth.Navigate(elem.GetAttribute("href"));
          break;
        }
    }
   }
}

The code finds all the links in the page, then iterates through them to find the logout link, and then navigates to it. It works. But that’s all I can say about it.

It’s really rather unfortunate as the Facebook API documentation is simply some of the poorest I’ve ever seen. There are many comments from developers in every section of the documentation asking for better docs as the documentation available right now doesn’t answer much of anything.

They don’t have any low-level documentation that would allow you to simply look up an issue, then create a solution for it. If there were, I would have been able to quickly write something that wasn’t a horrendous hack like the abomination above.

I suppose that in some ways I’ve simply got more of a desktop/server mentality now, and just don’t have that hoodoo magic needed to divine WTF comes next in the web world.

Maybe I should head out to see if I can buy some chickens to sacrifice… Maybe that will help…

But for now, the Facebook functionality in the Super Simple Photo Resizer is working.

Cheers,

Ryan

Getting the Album ID with the Facebook C# SDK

3

Posted by Cynic | Posted in .NET, Alcohol, C#, Software, Solutions to Problems, Super Simple | Posted on 09-06-2011

Tags: ,

I really shouldn’t drink & post like last night… Anyways, cynicism and rantiness wane as sobriety returns, and here’s some code that illustrates uploading a photo to a specific album:


// This is directly out of the Facebook C# SDK sample code (FacebookInfoDialog.cs)
private void btnPostPicture_Click(object sender, EventArgs e)
{
    var ofd = new OpenFileDialog
                  {
                      Filter = "JPEG Files|*.jpg",
                      Title = "Select picture to upload"
                  };
    if (ofd.ShowDialog() == DialogResult.OK)
    {
        var picture = File.ReadAllBytes(ofd.FileName);

        var fb = new FacebookClient(_accessToken);

        fb.PostCompleted +=
            (o, args) =>
            {
                if (args.Error == null)
                {
                    FacebookClient tmpClient = (FacebookClient)o;
                    Console.WriteLine(args.GetResultData().ToString());
                    JsonObject jo = (JsonObject)args.GetResultData();

                    Console.WriteLine((string)jo["link"]);

                    MessageBox.Show("Picture posted to wall successfully.");
                }
                else
                {
                    MessageBox.Show(args.Error.Message);
                }
            };

        dynamic parameters = new ExpandoObject();
        parameters.caption = txtMessage.Text;
        parameters.method = "facebook.photos.upload";
        // See below for how to get the album ID value:
        parameters.aid = "123456"; // <== This is the album ID.

        var mediaObject = new FacebookMediaObject
                              {
                                  FileName = Path.GetFileName(ofd.FileName),
                                  ContentType = "image/jpeg"
                              };
        mediaObject.SetValue(picture);
        parameters.source = mediaObject;

        fb.PostAsync(parameters);
    }
}

// PARTIAL SNIPPET
// This shows a quick & dirty way to get the album ID:

dynamic jobj = arraySerializer.Deserialize(json, typeof(object));
int counter = 0;
Dictionary<string, string> albums = new Dictionary<string, string>();
// This loop is a sin, but don't get side-tracked.
while (true)
{
    try
    {
        // The link to the album has it's ID:
        string link = Convert.ToString(jobj.data[counter].link);
        // Convert that to a URI:
        Uri url = new Uri(link);
        // Get the query string:
        string query = url.Query;
        // Put the query string into a quick & easy collection:
        NameValueCollection nvc = HttpUtility.ParseQueryString(query);
        // Extract the album ID using the literal variable name, "aid":
        string aid = nvc["aid"]; // <== The correct album ID.
        // Add the album ID (aid) and the album name to a dictionary:
        albums.Add(aid, jobj.data[counter].name);
        // If you were to do this, you wouldn't have an album ID that you can use
        // because the "id" in the JSON doesn't return the album:
        // albums.Add(jobj.data[counter].id, jobj.data[counter].name);
    }
    catch
    {
        break;
    }
    counter++;
}

It’s not hard at all. But the lack of decent documentation makes it painful at best.

I’ve been harping on this for a long time: In software components, the real product isn’t *just* the component… It’s the documentation.  The best software in the world is no better than the worst if you can’t use it effectively. That’s what documentation is for.

I hope that helps save someone some time.

Cheers,

Ryan

WTF is an ID for?

0

Posted by Cynic | Posted in .NET, C#, Software | Posted on 09-06-2011

Tags: ,

I’m a complete and total bigot. Unmitigated, complete, total bigot. The web sucks. And web APIs suck too. Especially when the documentation is non-existant or confusing or wrong. That sets me off.

You see, I hate shit. It smells. I don’t smear shit all over the walls in my house, and it kind of pisses me off when companies smear techno-shit all over my computer.

But there is a point to this all. And some real substance. Below addresses a retarded problem that just shouldn’t arise.

So let’s take the Facebook API and a simple example for uploading a photo to an album. Seems pretty simple, eh? Hardly.

This is the page for the Facebook Graph API: http://developers.facebook.com/docs/reference/api/

In there, you’ll see a line like this:

Photo Albums: https://graph.facebook.com/me/albums?access_token=…

Click that link and it will take you to a page of JSON that lists all of the albums you have for your photos on Facebook. The JSON looks something like this:

{
"data": [
{
"id": "12345678901234567",
"from": {
"name": "Ryan Smyth",
"id": "0987654321"
},
"name": "Some album name here",
"description": "Some album description here",
"link": "http://www.facebook.com/album.php?aid=123456&id=0987654321",
"cover_photo": "01234567898765432",
"privacy": "everyone",
"count": 53,
"type": "normal",
"created_time": "2011-01-02T01:16:33+0000",
"updated_time": "2011-02-03T14:49:02+0000"
},
{
"id": "01234567890123456",
"from": {
"name": "Ryan Smyth",
"id": "0987654321"
},
"name": "Another album name here",
"link": "http://www.facebook.com/album.php?aid=234567&id=0987654321",
"cover_photo": "12345678909876543",
"privacy": "custom",
"count": 1,
"type": "normal",
"created_time": "2011-01-23T11:43:40+0000",
"updated_time": "2011-04-23T11:45:21+0000"
},

Simple enough. JSON is basically crippled, wounded, lame, retarded XML, so it should be pretty easy.

Well, there’s an “id” field there, and this is the albums, so, that must be the album ID, right? Hardly…

I really have no clue WTF that “id” field is, but it isn’t the ID for the album.

After farting around and wasting massive amounts of time experimenting with every conceivable permutation  of the path variable, e.g. “/me/albumid/photo/”, and just generally getting jack-all done, I finally figured out that the actual album ID that you need to post to is in the “link” value as the “aid” variable’s value. So you need to divine the actual variable name, i.e. “aid”, and set that to the proper value.

So the variable name and the proper value are both obfuscated. Huh? Like, really… WTF?

Just how bloody hard would it be to put that in the docs? Oh, that’s right… Web APIs don’t have docs… Duh~? How stupid of me.

So, instead of putting the ID in the “id” field, which would make sense, I now need to muck around in the “link” field to extract the ID for the album.

That nonsense would never fly anywhere else except in the PHP and web world where sanity doesn’t rule the day.

There must be some kind of reasoning there somewhere, but I just can’t see it for the life of me. Maybe I should drop more acid…

Anyways, I hope my babbling rant has helped to solve some pain for someone. I’ll try to remember to post some code once I’m done farting around with it.

Grrr. Argh.

Ryan