Angularjs

El motivo de esta entrada no es otro que informaros que mi gran amigo y compañero @XaviPaper junto con un servidor, nos hemos marcado como meta escribir en desarrolloweb una serie de post de Angularjs, con no otro objetivo que transmitir nuestras experiencias con esta librería, derivado de su utilización en varios proyectos realizados a lo largo de 2013.

Como no soy de escribir esta serie de entradas, lo que voy a hacer es poneros a todos un aperitivo de cuales son nuestros objetivos y por tanto empieza la fiesta……

La realidad que el titulo de este post no debería de ser este sino más bien y fiel a mi estilo este otro.

Server-sent DOM events o más bien con la iglesia hemos topado.

Y porque?, pues sencillo simplemente hay que mirar el siguiente cuadro para darnos cuenta a que me estoy refiriendo.

image 

Referencia original: caniuse.

Aunque está claro que este tipo de tecnologías actualmente las podemos reemplazar con otras más modernas como websocket o con otras más antiguas como Long polling, lo que me gusta de esta frente a websocket no es otra que utilizamos el protocolo http sin más.

Como referencia he utilizado una serie de artículos y sobre todo el confirmar que existe algún que otro pollyfill.

Stream Updates with Server-Sent Events

Introduction to Server-Sent Events

EventSource polyfill

W3C Candidate Recommendation 11 December 2012

Y como con artículos de 2010 y una recomendación de diciembre de 2012 sigue IE sin implementarlo.

Será por algo?. La verdad es que es algo inexplicable y tampoco he encontrado razón alguna que justifique el por que noTriste. Más bien coincido con esta opinión.

http://stackoverflow.com/questions/9397528/server-sent-events-vs-polling.

Y porque me estoy preocupando yo por esto, sencillo todo fue a raíz de este post del amigo @Marc_Rubino y mis comentarios junto a los de los amigos @panicoenlaxbox y @gulnor

Seguridad en aplicaciones SPA.

Si os habéis molestado en leer los comentarios veréis que en uno de ellos yo defiendo la usabilidad más que evidentemente la seguridad que creo que todos los que intervinimos estamos de acuerdo en que este no debe de ser tu mecanismo de seguridad.

Con lo cual vamos manos a la obra y defender con código como a mí me gustaría encontrarme una aplicación.

Para ello lo primero que voy a hacer es plantear que existen dos usuarios (UsuarioA y Admin).

En un principio el UsuarioA no tiene permisos para entrar a una serie de páginas pero a lo largo de la mañana el usuario Admin le da permisos por un momento y se los revoca una vez realizada una tarea.

La pregunta es sencilla os gustaría ser el UsuarioA y entrar a esa opción de la App, pasarte un rato rellenando información y cuando pulses guardar que te diga tu app que no tienes permisos, yo creo que no.

Yo más bien y poniéndome en la piel del UsuarioA, prefiero que me diga directamente que no tengo permisos y no hacerme perder el tiempo.

Para ver todo lo que hay que hacer he creado una SPA con MVC y Angularjs y veréis que se puede hacer para luchar con el problema de la cache en una SPA.

Aplicación de Servidor(MVC).

Aunque os voy a dejar el código completo de la app vamos a explicar el porque de las cosas.

1. Nos encontramos con un controlador “HomeController” donde podemos observar una diferencia notable la acción Index no devuelve un PartialView sino directamente un View. Y por que?.

Sencillo, este es el marco principal del Spa y me sirve para aprovechar la potencia de Razor para insertar en JavaScript algún que otro dato.

image

Como podéis ver en el código. Es en la vista Index donde configuro las rutas que después vamos a consumir en nuestros módulo de Angularjs.

Los motivos son claros.

1. Me permite crear el JavaScript dinámico en función de la información del usuario.

2. Puedo utilizar Url.Action en el servidor para indicar cual es la ruta de mis templates, que algún que otro susto me he llevado con no utilizarlo en MVC.

Los controladores como ya os he dicho devuelven todos PartialView(que a la postre son mis templates de Angular,pero aprovechando la potencia de Razor) excepto el Index.

image

Como podéis ver existen un par de controladores a tener en cuenta aparte de los ya comentados.

Forbidden: Si el usuario no tiene permisos para ver una página se le mostrará este html.

<h2>No tiene permisos para ver la página</h2>

NotFound: Si el usuario va a una ruta que no existe desde angular no me gusta redirigirlo a “/” sino a una página que le diga que no existe.

<h2>La página no se encuentra</h2>

Lo siguiente es hacer un par de modificaciones en el Layout Principal de nuestra app.

1. Agregar un enlace al modulo de Angularjs.

<body ng-app=”myApp”>

ngApp

2. Modificar nuestro menu para apuntar directamente a las rutas de Angularjs.

image

3. Si no estoy autenticado para que quiero cargar Angularjs y el resto de JavaScript innecesario.

image

Si yo siempre y por principios Sonrisa voy autenticar contra un servidor y para ello voy a utilizar una vez autenticado el clásico patrón.

http://www.variablenotfound.com/2009/11/el-patron-post-redirect-get.html

http://es.wikipedia.org/wiki/Post/Redirect/Get

Vamos que veo un peligro y no pequeño en poner en mi código JavaScript algo como esto.

if(login()) {….} 

Web Api

Necesitamos crear dos métodos en un controlador.

1. Un GET que es el que se encarga de hacer la magia de Server-sent DOM events.

image

Si observamos este código podemos ver que se inicializa un ManualResetEvents y espera hasta que el administrador cambia los permisos en el siguiente método.

2. Otro controlador PUT que es desde donde el Administrador cambiará los permisos de la aplicación(Ojo que en el código no esta contemplado nada a nivel de roles).

image

Como podéis ver se llama al método Set del ManualResetEvent y se inicializa a un nuevo objeto.

3. Un MediaTypeFormatter que nos permite devolver al cliente un contentType con valor igual a text/event-stream.

image

Y por último vamos a describir que es lo que hemos hecho en el módulo de Angularjs.

Esta no es la forma correcta de organizar el código JavaScript, pero espero que me perdonéis que no es más que una demoSonrisa.

image

1. Definimos un módulo.

var app = angular.module(“myApp”, [“ngRoute”]);

2. Configurar nuestra app.

Primero cargamos todas las rutas que previamente configuramos en nuestra página Index(Razor).

Definimos un decorator para ampliar funcionalidades a $routeProvider (concretamente chequear si el servidor nos informa con un cambio de permisos y refrescar la pagina del cliente).

image

3. Una constante. Que es el identificador de evento asignado al usuario por parte del servidor y que se pasa como parámetro al método GET del controlador de nuestra Api.

4.Un servicio que es el que se encarga de toda la magia de Server-sent DOM events.

image

Si nos fijamos en el código observamos lo siguiente.

1. Se le inyecta a esta función el $routeProvider y la constante event.

2. Creamos al señor de la discordia EventSource.

3. Nos suscribimos al evento del usuario y es aquí una vez que nos llegue la información del servidor la convertimos a Json y chequeamos la ruta con el método checkRoute que previamente incluimos en el config del módulo, concretamente en el decorador de $routeProvider.

4. Por ultimo exportamos las funciones connect y close(una vez que el usuario hace logout se desconecta del servidor.

Si el usuario cierra la pestaña del navegador se cancela automáticamente.

4. Controladores. Poco tienen que explicar… Uno se encarga de cambiar los permisos del usuario y el otro de llamar al método close del apartado anterior.

5. Run. Una vez que se ejecuta nuestro módulo se ejecuta esta función y se llama a suscribeEvents.connect().

image

Pues señores que nos falta simplemente ver esto en ejecución para ello desde Firefox voy a hacer de Administrador y desde Chrome seré el usuario agraciado.

Siento no poder hacer la demo con IE11, pero los motivos son obvios.

image

Una vez que el señor Administrador pulsa en el botón Cambiar Permisos y transcurridos 5 segundos( Thread.Sleep(5000) en el servidor ) el señor “UsuarioA” ve el contenido de la página.

image

Si abrimos cualquiera de las peticiones de la carpeta NetWork podemos ver lo siguiente.

image

El Accept que envía el cliente  con valor text/event-stream y la respuesta del servidor Content-Type con valor text/event-stream.

Código de la aplicación completo

Conclusiones.

Muy breve, simplemente es una pena que de una vez por todas esta lucha sin cuartel de los exploradores no se acabe y que siempre tengamos que luchar con este tipo de cosas, que desde mi punto de vista no conducen a nada.

Por último ya sabéis cual es nuestro destino para escribir de Angularjs  desarrolloweb y espero que esto solo sea eso un aperitivo de lo que vais a ver.

Gracias!!!!

3 comentarios en “Angularjs”

  1. ¿¿¿¿En serio???????????????

    Joder, llevo pensando que tus posts eran una simple broma desde hace tiempo, sobre todo unas cuantas entradas para atrás estando yo en el submitt, al final, se me quitaron las ganas de contestar porque como pensaba que era una broma seguramente era lo que estabas buscando… pero bueno, no se… en este he parada cuando he visto en evento de sincronización y un WaitOne en un controlador

Deja un comentario

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