Wednesday, October 27, 2010

Integración Facebook - ASP.NET con Graph API (II)

Como comentaba en la primera parte de este post sobre la Graph API de Facebook, para poder recuperar cualquier tipo de dato es necesario obtener un AccessToken de Facebook. Recordemos que existen 2 tipos de token, uno público y otro privado.

Lo primero que haremos en este post una vez tengamos los datos de nuestra aplicación residente en nuestro perfil de Developer de Facebook (appId, appSecret, GroupId,...), será la llamada al siguiente método de la API para C# que hemos modificado convenientemenre y que será con la que trabajaremos.



///
/// Gets the access token for public access.
///

/// The app id.
/// The app secret.
/// Public access token.
public static string GetAccessToken(string appId, string appSecret)
{
if (string.IsNullOrEmpty(appId) string.IsNullOrEmpty(appSecret))
{
return null;
}

var url = string.Format(
"https://graph.facebook.com/oauth/access_token?type=client_cred&client_id={0}&client_secret={1}",
appId,
appSecret);

string accessTokenValue = null;
var request = WebRequest.Create(url) as HttpWebRequest;

try
{
if (request != null)
{
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback (CertificateValidationCallBack);

using (var response
= request.GetResponse() as HttpWebResponse)
{
if (response != null)
{
var reader = new StreamReader(response.GetResponseStream());
accessTokenValue = reader.ReadToEnd().Replace("access_token=", string.Empty);
}
}
}
}
catch (WebException e)
{
throw new FacebookAPIException("Server Error", e.Message);
}

return accessTokenValue;
}


Como veis, este método static de la API lo que hace es únicamente crear un WebRequest a la dirección https://graph.facebook.com/oauth, y recuperar el parámetro access_token que devuelve dicha llamada. Ése será nuestro public AccessToken a partir de ahora, almacenado en PublicToken al hacer la siguiente llamada:


this.PublicToken = FacebookAPI.GetAccessToken(AppId, AppSecret);


Las consultas públicas las haremos a través de la Graph API, pasando este PublicToken siempre como parámetro. Así, en cada nueva consulta de, por ejemplo, el muro de un grupo de Facebook del cual tenemos su identificador (GroupId), instanciamos un nuevo objeto FacebookAPI y asignamos los datos recuperados a un objeto JSON.


///
/// Gets or sets the feed.
///

/// The wall's feed.
public JSONObject Feed
{
get
{
return this.feed;
}
set
{
this.feed = value;
}
}



// API call and get data from Facebook
var api = new FacebookAPI(this.Token);

// Format url
var url = string.Format("/{0}/feed", GroupId);

// Format args - get all data
var args = new Dictionary
{
{ "metadata", "1" }
};
this.Feed = api.Get(url, args);


Lo que la llamada a api.Get("/[GroupId]/feed") devuelve es el objeto JSON del que tendremos que hacer el DataBind con el control web que hemos incluído en nuestra aplicación. En mi caso es un Repeater.



///
/// Handles the ItemDataBound event of the rptDataWall control.
///

/// The source of the event.
/// The instance containing the event data.
protected void RptDataWallItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item e.Item.ItemType == ListItemType.AlternatingItem)
{
var apiItem = new FacebookAPI(this.Token);

// Get controls
var lbCreatedTime = (Label)e.Item.FindControl("lbCreatedTime");
var lbFrom = (Label)e.Item.FindControl("lbFrom");
var lbMessage = (Label)e.Item.FindControl("lbMessage");
var imgUserPic = (Image)e.Item.FindControl("imgUserPic");
var rptDataWallReply = (Repeater)e.Item.FindControl("rptDataWallReply");

// Databind
lbCreatedTime.Text = ((JSONObject)e.Item.DataItem).Dictionary["created_time"].DateTime.ToShortDateString() + " @ " + ((JSONObject)e.Item.DataItem).Dictionary["created_time"].DateTime.ToShortTimeString();
lbFrom.Text = ((JSONObject)e.Item.DataItem).Dictionary["from"].Dictionary["name"].String;
lbMessage.Text = ((JSONObject)e.Item.DataItem).Dictionary["message"].String;

// Get profile picture
var urlPictureProfile = string.Format("/{0}/picture", ((JSONObject)e.Item.DataItem).Dictionary["from"].Dictionary["id"].String);
imgUserPic.ImageUrl = apiItem.GetProfilePicture(
urlPictureProfile,
null).AbsoluteUri;

// Replies - FB restriction: only show when logged
if (((JSONObject)e.Item.DataItem).Dictionary.ContainsKey("comments"))
{
rptDataWallReply.ItemDataBound += new RepeaterItemEventHandler(this.RptDataWallReplyItemDataBound);
rptDataWallReply.DataSource = ((JSONObject)e.Item.DataItem).Dictionary["comments"].Dictionary["data"].Array;
rptDataWallReply.DataBind();
}
}
}


Así, estamos mostrando en el Repeater una cadena de posts de un wall de un grupo de Facebook. Algo del estilo como la siguiente imagen.




Y ya tenemos un muro más parecido al Notepad que al Facebook al que estamos habituados ;)

En la siguiente parte del post nos centraremos en obtener un token privado y en cómo sacarle rendimiento (obtener comentarios de comentarios, postear en el muro de un grupo, etc...).

Saturday, October 23, 2010

Integración Facebook - ASP.NET con Graph API (I)

Desde hace tiempo las redes sociales van tomando más importancia en nuestro día a día, ya sea en el trabajo o en nuestra vida privada. Tanto Facebook como Tuenti Twitter ofrecen unas estupendas APIs, abiertas a que programadores de todo el mundo incluyan componentes sociales en sus portales, en aplicaciones de escritorio o incluso en aplicaciones para móviles. En este post voy a hablar sobre cómo integrar un muro de un grupo de Facebook y cómo autenticarse y postear desde una página ASP.NET al mismo muro utilizando la nueva Graph API de Facebook.

Antes de nada, recomiendo pasarse por la documentación de la Graph API y por la de OAuth. Como veréis en los enlaces, absolutamente toda la interacción con Facebook (tanto gets como posts) se hace mediante llamadas del estilo https://graph.facebook.com/ID. Cualquier tipo de datos (perfiles de usuario, grupos, imágenes, posts del muro, etc), se obtiene en el objeto JSON que devuelve este tipo de llamadas HTTP. Probad por ejemplo mi perfil: https://graph.facebook.com/guisuraga -ese soy yo en FB! :)-. Otro enlace realmente interesante para entender lo que hacen este tipo de llamadas es el de este ingeniero de Google.

Es necesario que también os registréis con un perfil de Developer en Facebook. Desde esa página debéis añadir una nueva aplicación y configurarla. Guardad los datos del Application ID, Application Secret y API Key porque serán necesarios para hacer las llamadas desde vuestra aplicación. Esta aplicación en Facebook es la encargada de rutear las solicitudes a la Graph API de Facebook, y devolver los datos solicitados por vuestra aplicación.


Ahora que tenemos una idea del potencial de esta API y teniendo en cuenta nuestro objetivo de incluir este componente en una aplicación ASP.NET, lo más rápido (y fácil) es encontrar una buena API en .NET que nos ayude a recuperar los datos y a transformar ese objeto JSON en algo que podamos manejar más fácilmente. Creedme, he probado varias APIs, y ninguna es tan simple y funciona tan bien (con alguna pequeña modificación :P) como la que los propios chicos de Facebook sacaron hace poco para C#. La podéis descargar desde aquí.

Una vez compilada y añadida a nuestro proyecto, la referencia Facebook actúa de intermediario entre nuestra aplicación y Facebook. En cada nueva instancia de un objeto FacebookAPI es necesario pasar por parámetro un AccessToken proporcionado por Facebook al hacer una llamada a la URL https://graph.facebook.com/oauth/authorize. Existen dos tipos de tokens: uno para recuperar datos públicos (datos del muro, datos públicos de perfiles), y otro para recuperar datos de una sesión autenticada (comentarios de posts en el muro, información adicional de perfiles). Para el primero de ellos, es suficiente con proporcionar los datos de nuestra aplicación residente en Facebook. El AccessToken para la parte privada lo intentaré explicar más adelante (cuando nos metamos con OAuth).

En la próxima parte del post me meteré con el código que hace esto.

Friday, October 15, 2010

Configuración de PivotViewer con error 'Element is already the child of another element'

PivotViewer es un control Silverlight para manejar cantidades considerables de datos de una manera gráfica. Parte de la aplicación de Microsoft Labs Pivot, y de los muchos ejemplos de apps que puedes encontrar en internet, confieso que estoy especialmente enamorado de este de la copa de fútbol. En ese enlace, además de pasar las horas muertas con las estadísticas del mundial, os podréis hacer una idea del potencial de la herramienta, y en la web oficial de Pivot y del control PivotViewer podréis aprender un poquito más: www.getpivot.com, www.silverlight.net/learn/pivotviewer/

El caso es que trabajando diariamente con SharePoint 2010, lo primero que viene a la mente de los de arriba es cómo se puede meter esto dentro de un webpart de Silverlight. No es que sea para nada complicado, y más siguiendo paso a paso este post de Tim Heuer. Genial. Te encuentras en la situación en la que lo tienes todo, compila, 0 errores, 0 warnings, F5, se abre la webapp de prueba, vamosvamosvamos... zas: exception at InitializeComponent() - Element is already the child of another element. Buscas en google y te desesperas, porque es uno de los errores más genéricos de Silverlight.

Si revisas tu código te das cuenta de que más simple no puede ser, que tienes la última referencia a System.Windows.Pivot, y que ese error no te va a decir dónde falla tu código... porque tu código simplemente no falla. Lo que pasa es que la configuración de tu servidor no es la correcta. ¿Has podido olvidar instalar alguna de las 'n' tools-sdk-kits-update-whatever que leíste en los pre-requisitos? Aquí viene el listado completo (funcionando para Windows Server 2008 R2, con VS2010 RTM y Silverlight 4, y actualizado a fecha del post):
Sé paciente, las dos primeras tardan. La última instala la SDK en C:\Program Files (x86)\Microsoft SDKs\Silverlight\v4.0\Toolkit\[version], así que revisa que es la DLL que usas al añadirla como referencia en tu proyecto.

Thursday, October 14, 2010

Inauguración del blog

Hola,

Como bien dice mi perfil de blogger.com me llamo Ángel Suárez, algunos me llaman Guisu y otros ANSU. Tengo 28 años y vivo en Barcelona, aunque nací, crecí y estudié en León. Actualmente trabajo en Spenta Consulting como desarrollador de SharePoint y .NET, junto a un equipo de profesionales excepcional.

El caso es que después de más de un año pensando en escribir cosillas interesantes en internet para compartirlas con la comunidad, me he decidido a hacerlo por la vía rápida, es decir, con un blogger de los de toda la vida. Desde aquí intentaré aportar mi granito de arena a este complicado mundo de la tecnología Microsoft.

¡¡¡Sean bienvenidos!!!