Lector de Twitter con ASP.NET MVC y Pure

Hola a todos! El otro día os comentaba lo mucho que me está gustando pure… Hoy, a modo de ejemplo, os presento como realizar fácilmente un lector de Twitter que muestre los últimos tweets…

El proyecto asp.net mvc

No voy a mencionar mucha cosa del proyecto asp.net mvc en general puesto que al final hay un enlace con todo el código. Consta de dos controladores:

  1. Home: Que tiene las acciones Index, Login y Tweets. La acción Index redirige a Login o bien a Tweets en función de si el usuario ha entrado o no login y password de twitter. La acción Login muestra un formulario de login y redirige a la acción tweets, que es la que hace el trabajo.
  2. La acción Tweets se limita a mostrar una vista que es la que hace gran parte del trabajo.

1. La vista Home/Tweets

Esta vista, hace una llamada ajax a la acción List del controlador Tweeter (nuestro segundo controlador). Esta acción debe devolver la información json con los últimos tweets del usuario. El código, es gracias a jquery, trivial:

$(document).ready(function() {
$.getJSON (
"<%= Url.Action("List","Twitter") %>",
function(val)
{
renderPure(val);
});
});

El método renderPure será el que usara Pure para mostrar los datos.

2. El controlador Twitter

Twitter dispone de una fantástica API REST con la cual podemos hacer casi cualquier cosa. Esta API está preparada para devolver datos usando distintos formatos, entre ellos json.

Algunas de las funciones de dicha API son públicas, pero otras (como la  de ver los últimos tweets) requieren que nos autentiquemos en twitter. Hay dos formas de hacerlo: usar OAuth o bien basic authentication.

OAuth es un protocolo de autenticación, pensado para integrar distintas aplicaciones, y una de sus ventajas es que el usuario no debe dar su contraseña en ningún momento, además de que puede granularizar sus permisos (puede dar permisos de lectura pero no de escritura p.ej.). Es sin duda el método recomendado para integrarnos con Twitter. Si usais cualquier cliente Twitter (web o escritorio) que no os haya pedido el password y que además hayais tenido que darle permisos desde la web de twitter, entonces este cliente está usando OAuth.

Basic authentication por otro lado es muy simple: se basa en poner una cabecera en la petición http, con nombre Authorization y cuyo valor sea Basic login:password, donde la cadena “login:password” está en Base64. Es un método totalmente inseguro (salvo que se uso junto con SSL) y además el usuario debe proporcionar su usuario y su contraseña al cliente (lo que bueno… mucha confianza no genera). Pero es muy sencillo de implementar, y es el que yo he usado.

El controlador Twitter tiene una sola acción List que realiza una llamada a la API REST de Twitter y pasa el resultado (json) tal cual:

public ActionResult List()
{
UserModel um = this.Session["user"] as UserModel;
string url = "http://api.twitter.com/1/statuses/friends_timeline.json";

// Realiza la petición a twitter
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Headers.Add("Authorization", string.Format("Basic {0}", um.Base64Data));
req.Method = "GET";
HttpWebResponse res = (HttpWebResponse)req.GetResponse();

string data = null;
if (res.StatusCode == HttpStatusCode.OK)
{
using (StreamReader sr = new StreamReader(res.GetResponseStream()))
{
data = sr.ReadToEnd();
}
}

return !string.IsNullOrEmpty(data) ? (ActionResult)this.RawJson(data) : (ActionResult)View("Error");
}

Fijaos que el código es muy simple: Recojemos un objeto UserModel de la sesión. Ese objeto contiene el login y password de twitter del usuario. Con esos datos construimos una petición a la URL de la API REST de Twitter y añadimos la cabecera Authorization. Finalmente leemos el valor devuelto (una cadena json, salvo error) y lo mandamos tal cual.

El método RawJson es un método mío de extensión que devuelve un objeto RawJsonActionResult:

public static RawJsonActionResult RawJson(this Controller @this, string data)
{
return new RawJsonActionResult() { RawData = data };
}

La clase RawJsonActionResult es un ActionResult mío, que me permite devolver una cadena json. No uso el JsonResult de MVC porque ese está pensado para construir una cadena json a partir de un objeto .NET, y yo ya tengo la cadena json. Como podeis ver, el código es trivial:

public class RawJsonActionResult : ActionResult
{
public string RawData { get; set; }

public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.ContentType = "application/json";
response.Write(RawData);
response.Flush();
}
}

Quizá alguien se pregunta porque hago una llamada a un controlador mío (Twitter) que lo único que hace es consultar a la API REST de Twitter y mandarme el mismo resultado (sin tratar). La respuesta es para evitar problemas de cross-domain: de esta manera desde la vista Home/Tweets la única llamada ajax que hay es una llamada a otro controlador del mismo dominio, lo que seguro que no me va a generar ningún problema.

3. La vista Home/Tweets (ii)

Una vez la vista Home/Tweets recibe el objeto json (resultado de la llamada a la acción List del controlador Twitter), debemos generar el html necesario para “dibujarlo”… Aquí entra en acción PURE.

El objeto json que nos devuelve twitter es bastante grandote (aunque gracias a firebug se puede ver muy fácilmente). Por cada tweet yo voy a mostrar:

  1. El avatar de quien ha hecho el tweet
  2. El texto del tweet
  3. El nombre de usuario y el nombre real

Para ello usaré la siguiente plantilla:

<div id="purecontent" style="display:none">
<div class="tweet">
<img class="picprofile"></img>
<p>
<span id="text"></span>
</p>
<div class="userdata"><span id="user"></span> (<span id="realname"></span>)</div>
</div>
</div>

Dentro del div “purecontent” se generaran tantos div “tweet” como tweets haya… Veamos el código del método renderPure:

function renderPure(data)
{
var directive = {
'div.tweet' : {
'tweet<-': {
'span#text' : 'tweet.text',
'span#text@id+' : 'tweet.id',
'span#user' : 'tweet.user.screen_name',
'span#user@id+' : 'tweet.id',
'span#realname' : 'tweet.user.name',
'span#realname@id+' : 'tweet.id',
'img.picprofile@src' : 'tweet.user.profile_image_url'
}
}
};
$("#purecontent").render(data, directive);
$("#purecontent").toggle();
}

Lo más importante (como no) es la directiva, que le indica a pure como renderizar los datos a partir de la plantilla y el objeto json. En concreto esa plantilla dice lo siguiente:

  1. Por cada elemento del elemento json (tweet<-) haz lo siguiente:
    1. En el span cuyo id es text (span#text) pon el valor de la propiedad text del elemento.
    2. En este mismo span modifica su id para que el nuevo valor sea el id previo (text) más el valor de la propiedad Id del elemento.
    3. Haz lo mismo con los spans user y realname, pero usando las propiedades screen_name y name del objeto user que está dentro del elemento.
    4. Finalmente en el atributo src de la img cuya clase es picprofile (img.picprofile@src) coloca el valor de la propiedad profile_image_url del objeto user que está dentro del elemento.

 

Que… fácil, eh? Al principio igual cuesta acostumbrarse pero una vez se le pilla el truquillo es muy potente y natural.

Finalmente llamamos al método render de PURE y por último hacemos visible el div padre (purecontent) mediante el método toggle de jQuery…

Y este es el resultado (por cierto José M. Aguilar… ponte ya un avatar :p)

image

Os dejo un zip con el proyecto entero para que le echeis un vistazo.

Saludos!!!

5 comentarios en “Lector de Twitter con ASP.NET MVC y Pure”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *