viernes, 30 de julio de 2010

Programación acordeón con JQuery

En mi ultimo proyecto desarrollado, para el hotel lagunamar en la isla de margarita; se presento una página interna donde se requería un acordeón para mostrar información. 




Aunque existen varios Plugins  para realizar acordeones como http://docs.jquery.com/UI/Accordion, el código lo desarrolle por mi cuenta ya que es bastante sencillo y un buen proceso de aprendizaje.

Primero veamos el Html completo para un acordeón de 3 tabs:

<div id="acordeon">    

   <div class="headerTabApagado headerTab">

          <div class="verdana14 bold labelApagado labelHeader">

                  Titulo 1

          </div>

          <div class="flechaTab flechaTabAbajo"></div>

   </div>

   <div class="contAcordion verdana12 darkgray">     

           <div style="float:left;width:300px;">

               <img width="256px" height="170px" alt="lagunamar" src="img.jpg" />

           </div>

           <div style="float:left;width:326px;">

                     Et lorem tristique amet integer tristique et integer et, vel amet, porta urna montes sit ut! Ultrices?

           </div> 

   </div>


   <div class="headerTabApagado headerTab">

          <div class="verdana14 bold labelApagado labelHeader">

                  Titulo 1

          </div>

          <div class="flechaTab flechaTabAbajo"></div>

   </div>

   <div class="contAcordion verdana12 darkgray">     

           <div style="float:left;width:300px;">

               <img width="256px" height="170px" alt="lagunamar" src="img.jpg" />

           </div>

           <div style="float:left;width:326px;">

                     pellentesque, purus, amet elementum pid ultrices phasellus! Ultrices amet nu

           </div> 

   </div>   

   <div class="headerTabApagado headerTab">

          <div class="verdana14 bold labelApagado labelHeader">

                  Titulo 1

          </div>

          <div class="flechaTab flechaTabAbajo"></div>

   </div>

   <div class="contAcordion verdana12 darkgray">      

           <div style="float:left;width:300px;">

               <img width="256px" height="170px" alt="lagunamar" src="img.jpg" />

           </div>

           <div style="float:left;width:326px;">

                     Velit enim habitasse duis turpis turpis massa sit cursus e

           </div> 

   </div>

</div>

Simplificando tenemos el código de cada Tab:

<div class="headerTabApagado headerTab">

     <div class="verdana14 bold labelApagado labelHeader">

             Titulo del tab

     </div>

     <div class="flechaTab flechaTabAbajo">

     </div>

</div>

<div class="contAcordion verdana12 darkgray">      

   Contenido del Tab

</div>

Donde tenemos el código del Titulo, área que esta siempre visible:


<div class="headerTabApagado headerTab">

    <div class="verdana14 bold labelApagado labelHeader">

          Título del tab</div>

   <div class="flechaTab flechaTabAbajo">

   </div>

</div>




El contenedor del tab posee dos clases CSS, headerTab que define el estilo general de los tabs:


  .headerTab

  {

      width: 658px;

      height: 42px;

      margin-left: 34px;

      position: relative;

      margin-top: 10px;

      cursor: pointer;

      float: left;

  }
y la clase headerTabApagado, que define el estilo de los tabs que se encuentran cerrados:


  .headerTabApagado

  {

      background-image: url(../Img/FondoGrisAcordeon.png);

      border: 2px solid #8d8d8d;

  }
Dentro de este div tenemos dos contenedores, uno que define el título con las clases CSS labelHeader y labelApagado, que definen los estilos de los títulos en general y de los tabs cerrados respectivamente:







  .labelHeader

  {

      position: absolute;

      top: 12px;

      left: 12px;

  }
   
  .labelApagado

  {

      color: #333333;

  }
Luego tenemos un div con la flecha de la derecha, igualmente con dos clases que representan el estilo general de las flechas, y el especifico de las flechas de los tabs cerrados, flechaTab y flechaTabApagado:





  .flechaTab

  {

      width: 28px;

      height: 28px;

      position: absolute;

      left: 612px;

      top: 7px;

  }   

  .flechaTabAbajo

  {

      background-image: url(../Img/flecha1.png);

  }

Finalmente tenemos el contenido de los Tabs:


  <div class="contAcordion">

      Contenido

  </div>

Ahora la parte mas interesante, el código JavaScript para realizar el efecto:


  $(function () {

              $('.headerTabApagado').click(prender);

          });

   

          function apagar() {

           $(this).removeClass('headerTabPrendido').addClass('headerTabApagado');

           $(this).next('.contAcordion').slideUp();

           $(this).children('.labelHeader').removeClass('labelPrendido').addClass('labelApagado');


           $(this).children('.flechaTabArriba').removeClass('flechaTabArriba').addClass('flechaTabAbajo');

           $(this).unbind('click');

           $(this).click(prender);

       }

       function prender() {

           apagarByNombre($('.headerTabPrendido'));

           $(this).removeClass('headerTabApagado').addClass('headerTabPrendido');

           $(this).next('.contAcordion').slideDown();

           $(this).children('.labelHeader').removeClass('labelApagado').addClass('labelPrendido');

           $(this).children('.flechaTabAbajo').removeClass('flechaTabAbajo').addClass('flechaTabArriba');

           $(this).unbind('click');

           $(this).click(apagar);

       }

       function apagarByNombre(nombre) {

         $(nombre).removeClass('headerTabPrendido').addClass('headerTabApagado');

         $(nombre).next('.contAcordion').slideUp();

         $(nombre).children('.labelHeader').removeClass('labelPrendido').addClass('labelApagado');

         $(nombre).children('.flechaTabArriba').removeClass('flechaTabArriba').addClass('flechaTabAbajo');

         $(nombre).unbind('click');

         $(nombre).click(prender);

     }

En las primeras 3 líneas agregamos la funcionalidad de prender un tab al momento de hacer click sobre el.


La función prender primero se encarga de cerrar el tab que se encuentre abierto previamente, eso lo realiza llamando a apagarByNombre. Luego remueve y agrega estilos Css para cambiar el estilo del tab (de gris a morado). Después utiliza la animación SlideDown para mostrar el contenido del tab. Finalmente remueve la función que tiene asociado actualmente al evento click (el de abrir tab) con $(this).unbind('click'); y le agrega la funcionalidad de cerrar el tab al evento click, $(this).click(apagar);.

Las funciones de apagar actúan de manera similar, intercambian las clases CSS para modificar el aspecto visual, luego llaman a la funcion slideUp() para ocultar el contenido del tab, y finalmente modifican la funcionalidad del evento click sobre ese tab con $(nombre).unbind('click'); y $(nombre).click(prender);



Al momento de escribir el tutorial la página aun no se encuentra al aire, pero pueden observar una vista previa del funcionamiento de los tabs en http://legendsoft.com.ve/Lagunamar/FAQ







martes, 1 de junio de 2010

#webve encuentro de twitteros del area web y tecnología en Caracas.

Mi amigo Oswaldo de http://www.silverexe.com esta promoviendo una iniciativa muy interesante para un encuentro en caracas para los amantes de la tecnología y el área web totalmente gratis.

Para anotarte a este encuentro simplemente coloca el siguiente mensaje en el twitter "Voy al #webve"

Para mayor informacion visita http://www.silverexe.com/Blog.aspx/Post/4/#webve-encuentro-de-twitteros-del-area-web-y-tecnologia-en-Caracas



martes, 18 de mayo de 2010

Nueva forma en Asp.Net 4 de realizar encoding de datos en paginas asp: <%: %>

Anteriormente hablamos de los ataques XSS y como es uno de los ataques mas comunes y eficientes al momento de atacar una pagina web.
Estos ataques consisten en inyectar código no deseado en una pagina web que luego puede ser ejecutado por otro usuario. Por ejemplo si entro a un foro que tenga poca seguridad, y creo un post nuevo con el siguiente codigo:



<script type="text/javascript"> alert('esto es un aviso no deseado')</script>

las personas que entren en este post les saldra un PopUp con el mensaje, a pesar que esto no fue programado por los creadores del foro.

Para solucionar esto se utiliza el Html encoding, esto es, traducir caracteres especiales de html a códigos los cuales al ser leidos por el explorador este los interpreta como texto, en lugar de interpretarlos como código html.

Por ejemplo, en lugar de escribir < script > alert(); < /script > se utilizan los códigos de los caracteres especiales: 




&lt; script &gt; alert(); &lt; &rasl; script &gt;
.  Este código sera interpretado y traducido al texto original por el explorador, en lugar de ejecutarlo como código de javascript. 


La versión de Asp Mvc para c# 3.5 incluye un helper de html que realizaba encoding de cualquier string, el cual se utiliza usualmente en las páginas Asp de la iguiente manera: 

<%= Html.Encode("string") %>



En c# 4.0 para comodidad del programador se ha introducido una nueva manera mas sencilla de realizar encoding, esto es colocando nuestro código c# entre los caracteres

<%: %>
 . Esto funciona de igual manera que 

<%= %>
 , con la diferencia que el string que retorna viene con los caracteres de encoding.







lunes, 3 de mayo de 2010

Validate input en Asp Mvc 2.0 y Asp.Net 4.0

Uno de los ataques a paginas de internet mas conocidos son los ataques XSS (Cross-site scripting) , que consiste en que el usuario inyecta condigo Html o Javascript en la pagina web. Para evitar esto el framework .Net 2.0 analiza los datos enviados en los requests, y si detecta algun codigo malicioso (como tags html), retorna un error al usuario y suspende el resto de la ejecución del request.


Ahora, existen casos en el que si queremos permitir que los usuarios envíen código que pueda parecer malicioso, como en un editor de texto enriquecido, o en en este blog, donde podemos escribir codigo javascript en los posts. 


Para evitar estas validaciones del Framework en Asp mvc, simplemente colocamos el atributo [ValidateInput(false)] en las acciones o controladores que no queramos que validen el texto recibido.


Sin embargo para el caso de Asp.Net 4.0, estas validaciones son realizadas a todos los requests (incluidos web services) antes de la funcion BeginRequest, esto significa que el framework rebota los requests con datos maliciosos antes de que se ejecuten los atributos de los controladores, dejando sin efecto el atributo mostrado previamente. 


Para solucionar esto se le debe indicar al framework que utilice las validaciones de la manera anterior,  colocando dentro del tag en el web.config lo siguiente:



 requestValidationMode="2.0" />



Esperemos que en el futuro exista alguna manera de poder especificar donde queremos usar esta nueva funcionalidad de seguridad y donde no, ya que con la solución actual estamos perdiendo por completo esta nueva funcionalidad.

martes, 13 de abril de 2010

Ya salio el Visual studio 2010.

Visual studio 2010 ya esta aquí, así como el framework 4.0.

Aqui tenemos las diferentes versiones de visual studio.

Visualmente el nuevo visual studio es bastante amigable y viene con varias innovaciones, como el soporte para Dual Monitor, ademas de un debugger muy potente con opciones entre otras cosas, de revisar los request y response que recibe y envía el servidor.

El framework viene con las nuevas versiones para el desarrollo web, Asp.Net 4 y MVC 2. Con MVC 2, tenemos ahora la posibilidad de crear areas dentro de un proyecto, inyectar el resultado de una accion directamente en una vista con , validaciones del lado del cliente integradas con las del servidor y otros Html helpers.

C# 4.0 trae unas cuantas novedades como podemos ver aqui (en ingles), entre las que tenemos tipos de daots totalmente dinamicos, y acceso a un nuevo API de Office, para interactuar con este de manera mucho mas sencilla.

Otras novedades de esta nueva version son F# (un lenguaje de programacion funcional) asi como novedades en C++, Visual Basic, Entity framework 4.0 y windows communication foundation.

Pronto veremos en detalle algunas de estas novedades!

martes, 6 de abril de 2010

Introducción a ASP MVC (parte 2)

¿Porque surge Web Forms?




La tecnologia Web forms fue desarrollada con la intención de asemejar la programación web a la programación de escritorio, principalmente a Windows forms, abstrayendo al programador del protocolo http, como lo es la comunicación por requests. En lugar de trabajar con HTML para crear nuestra interfaz, se utilizan controles ASP.

Estos controles les son asociados propiedades, metodos y eventos de manera similar a los controles de Windows Forms, los cuales son luego traducidos a lenguaje HTML desde el servidor para ser enviados al usuario y mostrarse en el navegador. 


Esta tecnología es muy buena para el desarrollo de paginas de manera rápida, ademas que es muy fácil su aprendizaje para desarrolladores que no estén familiarizados con el desarrollo web, pero tengan experiencia en el desarrollo de aplicaciones de escritorio con Windows Form, e incluso con otras tecnologías.


Desventajas de Web Forms
Sin embargo la utilizacion de Web Forms no siempre es la mejor opción, ya que el programador no tiene control directo sobre el html o los javaScripts generados, lo que muchas veces dificulta el realizar interfaces de usuario mas especificas o particulares. Esto se debe en parte a que el funcionamiento interno del manejo del protocolo HTTP por parte de WebForms esta parcialmente oculto al programador, lo que termina dificultando la creación de aplicaciones webs con funcionalidades muy particulares.

A esto de le suma que las paginas generadas por WebForms son mas pesadas y lentas a diferencia de que sea creada completamente por nosotros los programadores

Es por esto que para los programadores experimentados en la web; la tecnología y la forma de ocultar el protocolo HTTP, les resulta mas un estorbo que una solución, y muchas veces evita que personas desarrollando aplicaciones web con WebForms no aprenda como funcionan realmente las paginas webs.

Pensando en esto, Microsoft desarrollo una nueva tecnología para la creación de aplicaciones web, que se acerca mucho mas a la forma en que trabaja el protocolo HTTP, esta tecnología de nombre Asp MVC esta basada en el patrón de ingeniería de software Modelo Vista Controlador, un patrón ya bastante extendido en otras tecnologías de desarrollo como Java, Ruby on rails y diferentes frameworks de php.

La razón de que se use este patrón es que se asemeja al funcionamiento de la web, donde tenemos la vista que representa la interfaz presentada al usuario (Html, Css, Javascript, etc). La capa controlador; clases en el servidor que se encargan de recibir los requests, procesarlos, acceder al modelo si es necesario y retornar una vista al usuario. El modelo se encarga de todo el proceso de negocios de la aplicación, obtener y almacenar datos en la base de datos, comunicarse con web services, etc.

¿Como utilizamos este nuevo framework?
Lo primero es visitar la pagina oficial en http://www.asp.net/mvc/ , ahí se encuentra diferentes recursos de aprendizaje. Para instalarlo, hacemos click en dowmload. Luego veremos en el visual studio nuevas opción para crear proyectos del tipo MVC.

El framework funciona tanto para Visual studio 2008 como para la versión a salir próximamente; la 2010.

Por cierto, el codigo del framework se encuentra bajo licencia Open Source, por lo que podemos bajarlo y modificarlo como nos plazca.

Ya hay en la web varios recursos para aprender por complejo el framework, en particular recomiendo el libro escrito por Steven Sanderson y publicado por Apress  http://tinyurl.com/y8h8yf5 , es muy completo y explica de manera concisa y fácil de entender todo lo relacionado con este nuevo Framework.





domingo, 21 de marzo de 2010

Liquid Page and Resizeable Background Image (Páginas Líquidas)

(Creador: Freddy Torres.

¿Qué se quiere lograr?


Hace un par de meses se presento un requerimiento por parte de un cliente. Deseaba poder mostrar sus fotos en pantalla, y que las mismas ocuparan lo largo y ancho del explorador en su totalidad. Incluido esta el requerimiento de evitar que la misma se deforme, porque de no ser así, bastaría con colocar un código como este:


El problema con el código anterior es que no se preserva el radio de aspecto de la imagen de fondo (http://en.wikipedia.org/wiki/Aspect_ratio_(image)), por ejemplo: Supongamos que tenemos una imagen de tamaño 1280 x 800 (ar: 16:9 universal to high-definition television and European digital television), y nuestro explorador se encuentra en resolución 800 x 600 (ar: 4:3 universal for standard-definition video formats). El resultado sería una imagen deformada, ajustada de su tamaño original hacia 800 x 600, obviamente no es el resultado deseado.

¿Cómo lo solucioné?

La solución requiere realizar un cálculo en tiempo real que detecte el tamaño actual del explorador, y escale la imagen proporcionalmente a la mayor de las dimensiones del mismo. (WTF…?). Sencillo, que no deforme la foto, y que ocupe la mayor cantidad de pantalla posible.

¿Qué herramientas me apoyan?

Obviamente se necesitan algunas librerías de javascript que permitan gestionar y consultar las dimensiones del explorador. Aquí entra el grandioso JQUERY FRAMEWORK, mas específicamente la librería “jquery.dimensions.min.js”, que permite realizar un par de operaciones escenciales:

- $(window).width();
- $(window).height();

Por consiguiente, es necesaria la librería del propio framework “jquery-1.4.2.min.js”

Luego el algoritmo va como sigue……

El HTML:


********* IMPORTANTE **********
El identificador de la imagen (id=”liquidImage”) debe ser tomado en cuenta para el javascript que sigue.



EL JAVASCRIPT:

$(document).ready(function() {
Liquify();
$(window).bind("resize", function() {
Liquify();
});
});

Function Liquify(){
// dimensiones del explorador
var $winwidth = $(window).width();
var $winheight = $(window).height();

// dimensiones originales de la imagen
var $x = 1024; // cambiar de acuerdo al requerimiento o pasar por parametro
var $y = 768; // cambiar de acuerdo al requerimiento o pasar por parametro
var $dx = 4; // radio de aspecto x
var $dy = 3; // radio de aspecto y

// algoritmo
var $p = $winwidth / $dx;
var $coef = 0;
var $newwidth = 0;
var $newheight = 0;

// calculamos la mayor de las dimensiones del explorador
if (($winheight / $dy) > $p) {
// height predomina
$coef = $winheight / $y;
$newheight = $winheight;
$newwidth = $x * $coef;
} else {
// width predomina
$coef = $winwidth / $x;
$newwidth = $winwidth;
$newheight = $y * $coef;
}

// seteamos las dimensiones deseadas a la imagen de background
$("#liquidImage").attr({
width: $newwidth
});
$("#liquidImage").attr({
height: $newheight
});
}

¿Qué defectos tiene?

1. Las variables de dimensiones originales de la imagen están hard-coded en el javascript, y deben ser cambiadas de acuerdo al requerimiento. Lo ideal es hacer un pluing de jquery que reciba estas variables por parámetro, y tenga algunas seteadas por defecto.

lunes, 8 de marzo de 2010

z-index, position: absolute e Internet explorer

Hace poco estaba haciendo un menu el cual abria un div sobre el resto del contenido de la pagina con JQuery, el codigo es algo asi:









<div class="Container">
<div class="bar fl">
<a href="#" id="btn1">
            <img src="<%=Url.Content("~/Content/Imagenes/img1.jpg") %>" alt="<%=Resources.buscarPorCine %>" />
        </a><a href="#" id="btn2">
            <img src="<%=Url.Content("~/Content/Imagenes/img2.jpg") %>" alt="<%=Resources.buscarPorPelicula %>" />
</div>
<div class="Buscador" id="Buscador1">    
            contenido    
        </div>
<div class="Buscador" id="Buscador2">
            contenido
        </div>

</div>

<style type="text/css">
.bar
{
    width: 100%;
    height: 44px;
    background: url(Imagenes/bar.jpg) repeat-x;   
    z-index: 5;
}

.Buscador
{
    background-color: #483456;
    border-color: #483456;
    height: 500px;
    width: 946px;
    z-index: 5;   
    position: absolute;
    top: 365px;
    display:none;   
}
</style>

<script type="text/javascript" language="javascript">
    $(document).ready(function() {
        $("#btn1").click(function() {
            $("#Buscador2").slideUp();

            $("#Buscador1").delay(1000).slideDown();
           
        });

        $("#btn2").click(function() {
            $("#Buscador1").slideUp();
            $("#Buscador2").delay(1000).slideDown();
           
        });
    });
</script>







Básicamente dos links programados por JQuery para animar el menú, y el resto CSS con z-index y position absolute para mostrar el div encima del contenido.

Este código funciona perfecto en la mayoría de los exploradores, menos por supuesto en IE 6 y 7, donde el menu en lugar de colocarse encima del contenido se colocaba a la derecha de la pagina, destruyendo todo.
Bueno, el problema tiene algo que ver con la forma de manejar el Z-Index de IE 7, el cual al dibujar los elementos con esta propiedad "genera una nueva pila de contexto", 
y aunque aun no entiendo muy bien lo que esto significa, la solución consiste en colocar un div por encima del que queremos que aparezca encima del contenido,
 con un z-index mayor, veamos el código:






<div class="Container">
<div style="z-index: 7;">
        <div class="Buscador" id="Buscador1">     
            contenido     
        div>
div>
<div style="z-index: 7;">
     <div class="Buscador" id="Buscador2">
            contenido
     div>
div>
<div class="bar fl">
<a href="#" id="btn1">
            <img src="" alt="" />
        a><a href="#" id="btn2">
            <img src=""     alt="" />
div>


<style type="text/css">
.bar
{
    width: 100%;
    height: 44px;
    background: url(Imagenes/bar.jpg) repeat-x;    
    z-index: 5;
}

.Buscador
{
    background-color: #483456;
    border-color: #483456;
    height: 500px;
    width: 946px;
    z-index: 5;    
    position: absolute;
    top: 365px;
    display:none;    
}
style>

<script type="text/javascript" language="javascript">
    $(document).ready(function() {
        $("#btn1").click(function() {
            $("#Buscador2").slideUp();

            $("#Buscador1").delay(1000).slideDown();
            
        });

        $("#btn2").click(function() {
            $("#Buscador1").slideUp();
            $("#Buscador2").delay(1000).slideDown();
            
        });
    });
script>

Adicionalmente tuve que mover los dos divs del menú a la parte superior del código.

sábado, 6 de marzo de 2010

Introduccion a Asp MVC (parte 1)




De un año para acá Microsoft a desarrollado una alternativa a Web Forms para el desarrollo de páginas y aplicaciones web en el framework asp .Net, este nuevo Framework está basado en MVC (Modelo - Vista - Controlador), un patrón de ingeniería de software bastante utilizado en otras tecnologías webs como Ruby on Rails (construido totalmente en base a MVC) y frameworks para Java y PHP.

¿Porque este cambio de dirección por parte de Microsoft, y que beneficios puede traer la utilización de esta tecnología con respecto a Web Forms?.

Antes de entrar en detalle, repasemos un poco el funcionamiento de las paginas web



Http (Hypertext transfer protocol)


Es el protocolo utilizado para la transferencia de datos entre el cliente (el Browser en nuestro caso) y el servidor. La comunicación entre ambos se produce con dos objetos, el request que consiste en una petición del cliente, y el response, la respuesta que envía.


El request es la petición del cliente al servidor para que ejecute alguna accion, tipicamente pedir informacion o realizar cambios (guardar, actualizar o eliminar datos).


El request puede ser de varios tipos, de los cuales nos enfocaremos en el Get y Post


El Get es utilizado para la petición de recursos al servidor. Este tipo de peticiones no debe ser utilizado para peticiones que causen ningún tipo de cambio, como lo puede ser la eliminación de registros en una base de datos, esto debido a la facilidad con las que pueden ser realizadas estas peticiones. Por ejemplo, veamos la siguiente tabla:




El boton eliminar es un link < a > a un URL, cuando se realiza una petición a este URL se elimina el dato. Ahora, si esta pagina tiene acceso público, el robot de google podría ingresar a ella en cualquier momento y realizar peticiones a los links encontrados, eliminando los datos de la pagina sin que nos demos cuenta.


La petición de tipo Post permite enviar datos en el cuerpo del request para que sean procesados por el servidor, como lo es crear, actualizad o eliminar registros de una base de datos.





Html (Hypertext markup language)


Es el principal lenguaje utilizado para estructurar las paginas webs. Los navegadores interpretan los documentos Html para generar la vista a mostrar al usuario.


Los documentos Html pueden incluir adicionalmente documentos del tipo Css para agregar estilos a la pagina, y scrips, tipicamente en lenguaje JavaScript, que agregan funcionalidades a la pagina del lado del cliente.


Estas 3 tecnologías (html, css y javascript) son las tecnologías del lado del cliente mas utilizadas.





Http, Html y el navegador


Como vimos, las paginas Webs son usualmente documentos Html con Css y Javascripts, mostrados por un navegador, el cual se comunica con un servidor a través del protocolo Http.


Todas las peticiones del cliente al servidor son realizadas a un URL:


www.ejemplo.com/MiPeticion/1?queryString=2


Donde la primera parte (www.example.com) indica la dirección del servidor, y el resto es la petición es interpretada por este para determinar la respuesta o acción a tomar y retornar al cliente. 
En el caso de las peticiones Post, el servidor  recibe adicionalmente los datos enviados en el cuerpo del request. Esto campos son introducidos usualmente por el cliente en un formulario html (< form >).


En la siguiente parte veremos como funciona esto en Web Forms y las diferencia con Asp MVC.