Ryan Williams
Ryan Williams

Reputation: 1620

C# FacebookSDK Checking Permissions

I'm using Facebook SDK http://facebooksdk.net/ to upload videos.
My function: EnsureRequiredPermissions() works well, but how can it be written better?

The following C# console application should be able to upload videos to a facebook wall and if you were to substitute "me" for a PageId and use the Page's AuthToken instead it should also be able to upload videos to a Facebook Page too.

Note the work around for the default timeout of 100 seconds.

public void Main()
{
    var facebookClient = new FacebookClient(@"SomeFacebookOAuthToken");

    // Ensure the web request does not time out at 100 seconds.
    facebookClient.SetHttpWebRequestFactory(CreateHttpWebRequest);

    if (!EnsureRequiredPermissions(facebookClient))
    {
        Console.WriteLine(@"Insufficient permissions to continue.");
        return;
    }

    var result = UploadVideo(facebookClient, @"C:\Path\To\Video.mp4", @"Some Title", @"Some Description");
    Console.WriteLine(result);
}

private static bool EnsureRequiredPermissions(FacebookClient facebookClient)
{
    var requiredPermissions = new List<String>
    {
        @"publish_stream"
    };

    dynamic response = facebookClient.Get(@"me/permissions");
    var responseObj = JObject.Parse(response.ToString());
    foreach (JProperty permission in responseObj[@"data"][0].Children())
    {
        if (requiredPermissions.Contains(permission.Name) && permission.Value.ToString() == @"1")
            requiredPermissions.Remove(permission.Name);
    }
    return requiredPermissions.Count == 0;
}

private static object UploadVideo(FacebookClient facebookClient, string path, string title, string description)
{
    var mediaStream = new FacebookMediaStream
    {
        ContentType = @"application/octet-stream",
        FileName = Path.GetFileName(path)
    };

    // Note: FacebookMediaStream supports IDisposable but closes the stream before all bytes are read.
    using (var fileStream = File.OpenRead(path))
    {
        mediaStream.SetValue(fileStream);
        var parameters = new
        {
            description = description,
            title = title,
            mediaStream
        };
        try
        {
            return facebookClient.Post(@"me/videos", parameters);
        }
        catch (FacebookOAuthException unknownError)
        {
            // Facebook are wankers so pretty much every exception
            // will be: "An unknown error has occurred".
            Console.WriteLine(unknownError);
            throw;
        }
    }
}

private static HttpWebRequestWrapper CreateHttpWebRequest(Uri url)
{
    var httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
    var wrapper = new HttpWebRequestWrapper(httpWebRequest)
    {
        Timeout = System.Threading.Timeout.Infinite
    };
    return wrapper;
}

Upvotes: 0

Views: 511

Answers (1)

Benoit
Benoit

Reputation: 1107

i know im late, but here's how i do it: Assembly Facebook.dll, v6.0.10.0

1) Create Models :

public class FbData<T> {
    public IList<T> Data { get; set; }
}
public class UserPermission {
    public string Permission { get; set; }
    public string Status { get; set; }
    [JsonIgnore]
    public bool Granted { get { return Status.ToLower() == "granted"; } }
}

2) Use helper like this:

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Facebook;
using Microsoft.AspNet.Facebook.Client;
using System.Threading.Tasks;
 public class FacebookHelper
{
    public static async Task<IList<T>> GetArrayAsync<T>(Facebook.FacebookClient facebookClient, string path)
    {
        dynamic response = await facebookClient.GetTaskAsync(path);
        var str = response.ToString() as string;
        if (str.IsNullOfEmpty())
            return default(IList<T>);
        var result = await Newtonsoft.Json.JsonConvert.DeserializeObjectAsync<FbData<T>>(str);
        return result.Data;
    }
    public static async Task<bool> EnsureRequiredPermissions(Facebook.FacebookClient facebookClient, params string[] Permissions)
    {
        var requiredPermissions = new List<String>(Permissions);
        var userPerms = await GetArrayAsync<UserPermission>(facebookClient, "me/permissions");
        var allowed = from e in userPerms where e.Granted select e.Permission;
        requiredPermissions.RemoveAll(o => allowed.Contains(o));
        return requiredPermissions.Count == 0;
    }
}

EDIT: Add more exemple If you wish to make one call for example picture, likes and user, you can use something like this:

 public static async Task<T> GetAsync<T>(Facebook.FacebookClient facebookClient, string objectPath, bool AddGetFields = true)
        where T: class
    {
       var path = objectPath + (AddGetFields ? FacebookQueryHelper.GetFields(typeof(T)) : "");
        dynamic response = await facebookClient.GetTaskAsync(path);
        var str = response.ToString() as string;
        if (str.IsNullOfEmpty())
            return default(T);
        return await Newtonsoft.Json.JsonConvert.DeserializeObjectAsync<T>(str);
    }
  public static Task<MyAppUser> GetCurrentLogedUser(Facebook.FacebookClient facebookClient)
    {
        return GetAsync<MyAppUser>(facebookClient, "/me");
    }

and the model will be :

public class MyAppUser
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Link { get; set; }

    [JsonProperty("picture")] // This renames the property to picture.
    [FacebookFieldModifier("type(large)")] // This sets the picture size to large.
    public FacebookConnection<FacebookPicture> ProfilePicture { get; set; }



    //[FacebookFieldModifier("limit(8)")] // This sets the size of the friend list to 8, remove it to get all friends.
    //public FacebookGroupConnection<MyAppUserFriend> Friends { get; set; }

    //[FacebookFieldModifier("limit(16)")] // This sets the size of the photo list to 16, remove it to get all photos.
    //public FacebookGroupConnection<FacebookPhoto> Photos { get; set; }

    public FacebookGroupConnection<Like> Likes { get; set; }
}
public class Like
{
    public string Name { get; set; }
    public string Category { get; set; }
    public string Id { get; set; }
}
public class FacebookPicture
{
    public string Url { get; set; }
}

the FacebookQueryHelper.GetFields(typeof(T)) return a string tell to facebook to return specific field, so if a model have only id, it will not return all field. If the model have a FacebookGroupConnection or FacebookConnection property it will be filled (Like the Likes property). It will also add modifiers, like :[FacebookFieldModifier("limit(16)")] will limit the resutl array to 16

Upvotes: 1

Related Questions