Todo en ASP.NET

Blog dedicado a la programación con Visual Studio .NET….. especialmente desarrollo Web

Posts etiquetados ‘asp.net’

[ASP.NET MVC] Introducción a Single Page Applications

Publicado por Julio Avellaneda en 03/26/2013

Hola amigos, hace poco tuce la dicha de dar una pequeña charla sobre Single Page Applications, así que ahora les comparto el material, espero les sirva y como comente en el video, 1 hora es muy poco tiempo, así que escribiré al respecto.

Descargar el webcast!

Saludos!

Publicado en ASP.net, ASP.NET MVC, Javascript | Etiquetado: , , | 2 Comentarios »

[ASP.NET] Hands On Labs Web Forms Y MVC

Publicado por Julio Avellaneda en 02/27/2013

Hola a todos, hoy simplemente les quiero compartir unos hands on labs tanto para ASP.NET Web Forms como para ASP.NET MVC los cuales tenemos disponibles ahora en el sitio oficial de ASP.NET, se que como a mi les serán de gran ayuda, los links son:

Hands On Labs Web Forms

Hands On Labs MVC

Saludos.

Publicado en ASP.net, ASP.NET MVC | Etiquetado: , | 1 comentario

[ASP.NET Web API] Filtros de validación

Publicado por Julio Avellaneda en 02/19/2013

Realmente ando muy contento trabajando con Web API, sobretodo por su facilidad de uso, sin embargo, unos de los puntos que debemos tener presente cuando creando servicios REST con Web API es la seguridad y la creación de filtros para no exponer sin consideración las acciones de nuestros servicios, para solucionar dicho problema es posible crear filtros y realizar todas esas validaciones necesarias.

Los filtros pueden ser aplicados en diferentes niveles:

  • A nivel de clase
  • A nivel de acción
  • A nivel global

Para crear un filtro, se debe crear una clase que herede de ActionFilterAttribute y luego sobrescribir el método OnActionExecuting, para ver el tema en acción crearemos un filtro para validar que el dominio del cual están realizando la petición sea conocido, por lo tanto creamos la clase FilterDomainAttribute:

public class FilterDomainAttribute : ActionFilterAttribute
{
	public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
	{
		var domain = "dominio";
		if (!string.Equals(actionContext.Request.RequestUri.Host, domain, StringComparison.OrdinalIgnoreCase))
		{
			actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
				{
					Content = new StringContent("Petición no autorizada")
				};
		}
	}
}

Entonces, creamos la clase FilterDomainAttribute la cual hereda de ActionFilterAttribute, luego hacemos un override al método OnActionExecuting y allí lo que hacemos es obtener el dominio con actionContext.Request.RequestUri.Host y se compara en este caso con el valor de la variable domain, en caso de no ser un dominio válido retornamos el mensaje “Petición no autorizada” con el estado de no autorizado HttpStatusCode.Unauthorized.

Ahora, creamos un controller (muy sencillo) para el manejo de clientes, entonces la clase Client:

public class Client
{
	public int ClientId { get; set; }
	public string Name { get; set; }
	public string Twitter { get; set; }
}

Y el controlador:

public class ClientController : ApiController
{
	private readonly IEnumerable<Client> clients = new List<Client>() {
		new Client (){ ClientId = 1, Name = "Julio", Twitter = "@julitogtu"},
		new Client (){ ClientId = 2, Name = "Juan", Twitter = "@JuanKRuiz"},
		new Client (){ ClientId = 3, Name = "Nicolas", Twitter = "@nicolocodev"},

	};

	public IEnumerable<Client> GetAll()
	{
		return clients;
	}

	public Client GetById(int id)
	{
		return new Client() { ClientId = 1, Name = "Julio", Twitter = "@julitogtu" };
	}
}

Para utilizar el filtro a nivel de clase o a nivel de acción lo único que se debe utilizar es decorar bien sea la clase o la acción con el atributo creado (no olvidar referenciar el namespace ActionFilter.Filter):

[FilterDomain]
public class ClientController : ApiController

[FilterDomain]
public IEnumerable GetAll()

Algo interesante es que es posible escribir solo FilterDomain, y recuerden que el nombre de la clase es FilterDomainAttribute.

Y ahora, si se quiere aplicar el filtro a nivel global se debe ir al global.asax y definirlo en el Application_Start:

GlobalConfiguration.Configuration.Filters.Add(new FilterDomainAttribute());

Si quieren ver otros ejemplos relacionados les recomiendo dos post del master Gonzalo:

Les dejo el código del ejemplo: Descarga el ejemplo!

Saludos!

Publicado en ASP.net, ASP.NET MVC, ASP.NET Web API, Rest | Etiquetado: , , , | 1 comentario

[ASP.NET Web API] Respondiendo en JSON

Publicado por Julio Avellaneda en 01/22/2013

Hola, pues este será un mini-post, donde simplemente voy a mostrar como podemos configurar el tipo de respuesta que deseamos den nuestros controladores, más en especifico los métodos que ellos tienen. Si por ejemplo tenemos el siguiente controlador:

public class ClientController : ApiController
{
	private readonly IEnumerable clients = new List() {
		new Client (){ ClientId = 1, Name = "Julio", Twitter = "@julitogtu"},
		new Client (){ ClientId = 2, Name = "Juan", Twitter = "@JuanKRuiz"},
		new Client (){ ClientId = 3, Name = "Nicolas", Twitter = "@nicolocodev"},

	};

	public IEnumerable GetAll()
	{
		return clients;
	}
}

Si por ejemplo, probamos en IE lo que obtenemos es un xml:

image

Y ahora, para trabajar en formato JSON lo que hacemos es eliminar la respuesta en tipo XML, así entonces en el Global.asax:

GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

y si ahora lo probamos de nuevo en IE:

image

Saludos

Publicado en ASP.net, ASP.NET MVC, ASP.NET Web API, Rest | Etiquetado: , , , | 1 comentario

[ASP.NET] Minificación de scripts con Web Essentials

Publicado por Julio Avellaneda en 01/08/2013

Hola, este será un pequeño post en donde quiero mostrar como podemos generar nuestros archivos JavaScript más compactos, esto va a permitir que el nuevo archivo sea mas liviano y su descarga se más rápida, lo primero que debemos hacer es utilizando Nuget añadir Web Essentials:

image

Una vez instalada se tiene que reiniciar Visual Studio para que la herramienta quede disponible, ahora, para el ejemplo vamos a usar el siguiente archivo JavaScript (algo muy simple):

var operaciones = {
    Suma: function (a,b)
    {
        return a + b;
    },
    Resta: function (a,b)
    {
        return a - b;
    },
    Multiplicacion: function (a, b)
    {
        return a * b;
    },
    Division: function (a, b)
    {
        return a / b;
    }
};

Ese código lo he creado en un archivo con nombre Test.js, y sobre dicho archivo damos click derecho Web Essentials –> Minify JavaScript file(s), y se generan dos nuevos archivos, el primero Test.min.js y el segundo Test.min.js.map:

image

En el archivo .min.js se tiene el código JavaScript minificado, y en .min.js.map se tiene información sobre el archivo minificado, es importante que la minificación solo debe realizarse la primera vez, ya que si cambiamos el archivo normal, automáticamente vamos a tener esos cambios reflejados en el archivo .min.

Si observamos el archivo minificado:

var operaciones={Suma:function(n,t){return n+t},Resta:function(n,t){return n-t},Multiplicacion:function(n,t){return n*t},Division:function(n,t){return n/t}};
//@ sourceMappingURL=Test.min.js.map

Espero les haya gustado este pequeño post, que es más un tip de productividad.

Publicado en ASP.net, Javascript | Etiquetado: , | 3 Comentarios »

[JavaScript] Un poco más sobre variables y funciones

Publicado por Julio Avellaneda en 11/02/2012

Hola, últimamente he visto como cada vez se desarrolla mucho más en el lado cliente, y no es para menos, JavaScript ha tomado mucha fuerza y ahora tiene características muy buenas, además se ha visto un crecimiento exponencial en los framework/librerías que como base o ha sido construidas sobre JavaScript, sin embargo, este punto tiene algo en contra y es que los desarrollamos estamos dejando de lado la escuelita clásica (JavaScript puro) y nos dejamos seducir por las bondades de esos frameworks, y en un primer vistazo no es posible ver el problema, pero cuando nuestras aplicaciones van creciendo, el manejo de JavaScript no cambia, y llegamos a un punto en donde el ya solo usar un framework con algunos widgets muy cool realmente no aportan a crear aplicaciones escalables.

Ahora, quiero en este post dar una pequeña explicación de algunas particularidades que tiene JavaScript sobre el trabajo con funciones y variables, que aunque al parecer algo muy simple realmente envuelve algunos temas que muchas veces son desconocidos.

Pero antes de iniciar quiero decirles que no soy un experto en JavaScript pero que de verdad espero que este post aclare muchas dudas… y ahora si, menos charla y más acción.

Además, no quiero hacer este post con términos muy técnicos, la idea es dar ejemplos y entender el funcionamiento, ya luego pueden ir más a fondo y revisar la teoría en detalle.

Variables

Bueno este tema puede sonar un poco simple, pero es importante, iniciemos primero con la forma en que podemos declarar una variable:

   1:  var i = 1; //Declaración con var
   2:  x = 2; //Declaración sin var
   3:  alert(i); //Muestra 1
   4:  alert(x); //Muestra 2

Como podemos ver en el ejemplo anterior, no es obligatorio usar var en la declaración, pero existe diferencia? pues si, y mucha, así que vamos a realizar otro ejemplo:

   1:  function Mensaje1()
   2:  {
   3:     var nombre = "Julio Avellaneda";
   4:     email = "julito_gtu@hotmail.com";
   5:  }
   6:   
   7:  function Mensaje2()
   8:  {
   9:      alert(email);
  10:      alert(nombre);
  11:  }
  12:   
  13:  Mensaje1();
  14:  Mensaje2();

Bueno, si miramos el código anterior podríamos pensar que en la función Mensaje2 vamos a obtener un error, ya que las variables email y nombre solamente existen en el contexto de Mensaje1, sin embargo al ejecutar ese sencillo código nos llevamos una gran sorpresa, y es que el alert de email SI esta funcionando (y efectivamente muestra mi correo), pero… ummm como así que funciona?? bueno, pues sencillamente la razón es que cuando se declara una variable sin var el ámbito de esa variable es global.

Les recomiendo que le den un ojo al post del maestro José Manuel Alarcon: Closures en JavaScript: una herramienta muy útil.

Funciones

Bueno, el tema de funciones es bastante extenso, y se que alguna que otra cosita se me quedará por fuera, pero espero los puntos que se traten sean de gran interés.

1. Declaración de funciones

Lo primero a comentar es que existen varias formas de declarar una función, así que miremos el siguiente ejemplo:

   1:  function Mensaje1()
   2:  {
   3:     alert('Funcion mensaje 1');
   4:  }
   5:   
   6:  var fun = {
   7:     Mensaje2 : function(){
   8:          alert('Funcion mensaje 2');
   9:     }
  10:  }
  11:   
  12:  Mensaje1();
  13:  fun.Mensaje2();

Y las dos formas funcionan correctamente, pero que pasaría si ahora cambiamos las líneas 12 y 13 de lugar y las dejamos al inicio? es decir:

   1:  Mensaje1();
   2:  fun.Mensaje2();
   3:   
   4:  function Mensaje1()
   5:  {
   6:     alert('Funcion mensaje 1');
   7:  }
   8:   
   9:  var fun = {
  10:     Mensaje2 : function(){
  11:          alert('Funcion mensaje 2');
  12:     }
  13:  }

En este caso solo funciona correctamente Mensaje1, y para el otro llamado se obtiene el error TypeError: fun is undefined, y la explicación es simple, cuando declaramos una función de forma declarativa (como Mensaje1) dichas funciones son evaluadas por el navegador antes que las demás expresiones, y acá ya nos damos cuenta que realmente la ejecución de JavaScript no es tan lineal como pensábamos.

2. Argumentos en funciones

Bien, ahora toquemos un poco el tema de los argumentos en las funciones, y pues como hemos venido trabajado primero un ejemplo:

   1:  var fun = {
   2:      Suma1: function(num1, num2)
   3:      {
   4:          alert(num1 + num2);
   5:      }
   6:  }
   7:   
   8:  fun.Suma1(5,5);
   9:  fun.Suma1(2,2,2,2,2);

Listo, a simple vista podemos ver que el segundo llamado a la función Suma1 esta algo mal no? estamos enviando más parámetros de los definidos en la función, pero….. si, funciona! y lo hace por que JavaScript no tiene en cuenta los demás parámetros, simplemente los ignora, y si, en mi opinión no es algo que se debería permitir.

Y ahora un ejemplo más:

   1:  var fun = {
   2:      Suma: function()
   3:      {
   4:          var total = 0;
   5:          for (var i = 0; i < arguments.length; i++)
   6:          {
   7:              total += arguments[i];
   8:          }
   9:          alert(total);
  10:      }
  11:  }
  12:   
  13:  fun.Suma(2,2,2,2,2,10);

Bueno ya la cosa esta rara acá, la función no le declaramos parámetros, pero en la llamada si se los enviamos, y este caso es muy bueno para mencionar que en cada función JavaScript podemos acceder al objeto arguments el cual tiene como referencia todos los argumentos enviados a la función, por lo tanto haciendo uso de él podemos fácilmente calcular la suma de los números enviados a la función Suma.

3. Funciones y prototipos

Ahora, vamos a ver un poco acerca de los prototipos, así que vamos con el ejemplo:

   1:  Function.prototype.Multi = function()
   2:  {
   3:     var total = 1;
   4:     for (var i = 0; i < arguments.length; i++)
   5:     {
   6:         total *= arguments[i];
   7:     }
   8:     return total;
   9:  };
  10:   
  11:  var fun = function()
  12:      {
  13:          var total = 0;
  14:          for (var i = 0; i < arguments.length; i++)
  15:          {
  16:              total += arguments[i];
  17:          }
  18:          return total;
  19:      }
  20:   
  21:  var result1 = fun(2,2,2,2); // 8
  22:  alert(result1);
  23:  var result2 = fun.Multi(2,2,2,2); // 16
  24:  alert(result2);

Resumiendo entonces, digamos que con Function.prototype.<…> podemos extender las funciones, podríamos incluso hacer la similitud en la programación al concepto de clase base, donde las clases que heredan de esa clase también heredan sus métodos. Luego haré un post donde solo hablaré de este tema.

4. LLamando funciones

Y ahora vamos a revisar como podemos llamar una función, así que vamos con un ejemplo:

   1:  var Persona = function(nombre, email)
   2:      {
   3:          this.nombre = nombre;
   4:          this.email = email;
   5:          return 5;
   6:      }
   7:   
   8:  var per1 = new Persona('Julio', 'julito_gtu@hotmail.com');
   9:  var per2 = Persona('Juan','juan@hotmail.com');
  10:   
  11:  console.log(per1);
  12:  console.log(per2);

Bueno, acá es importante primero mencionar que estamos usando el operador new, entonces para per1, y gracias al uso de new estamos creando un nuevo objeto con dos propiedades (email y nombre) y en este caso el return no es tenido en cuenta, en cambio para el segundo caso, es decir para per2 solo es tenido en cuenta el return, la siguiente imagen muestra los resultados en la consola de Chrome:

image

Bueno, espero que les gusto el post tanto como a mí escribirlo!

Saludos!

Publicado en ASP.net, Javascript | Etiquetado: , | 2 Comentarios »

[ASP.NET] Condicionales y ciclos en JSRender

Publicado por Julio Avellaneda en 10/16/2012

Anteriormente vimos una introducción a JSRender y como podemos cargar los datos utilizando WebAPI (mira el post), y hoy quiero mostrarles dos características adicionales de JSRender para manejar las plantillas y tener una lógica más completa en lugar de solo mostrar datos, y esas dos características son: condicionales y filtros.

Para este ejemplo vamos a seguir utilizando el ejemplo del anterior post, así que te recomiendo le des una mirada primero, te dejo el link:

Cargando datos con WebAPI y JSRender

Lo primero que haremos es añadir una nueva clase al modelo llamada Ciudad:

   1:  public class Ciudad
   2:  {
   3:      public int CiudadId { get; set; }
   4:      public string Nombre { get; set; }
   5:  }

Ahora, vamos a suponer que nuestros clientes han visitado algunas ciudades, así que añadimos una nueva propiedad a la clase Cliente quedando:

   1:  public class Cliente
   2:  {
   3:      public int ClienteId { get; set; }
   4:      public string Nombre { get; set; }
   5:      public string Email { get; set; }
   6:      public bool Activo { get; set; }
   7:      public List<Ciudad> Ciudades { get; set; }
   8:  }

Ahora en nuestro controlador modificamos la lista de clientes y le añadimos algunas ciudades a algunos clientes:

   1:  private readonly List<Cliente> clientes = new List<Cliente>()
   2:  {
   3:      new Cliente{ ClienteId = 1, 
   4:          Nombre = "Julio Avellaneda",
   5:          Email = "julito_gtu@hotmail.com", 
   6:          Activo = true,
   7:          Ciudades = new List<Ciudad>(){
   8:              new Ciudad { CiudadId = 1, Nombre = "Bogotá"},
   9:              new Ciudad { CiudadId = 2, Nombre = "Cali"},
  10:              new Ciudad { CiudadId = 3, Nombre = "Medellin"}
  11:          }},
  12:      new Cliente{ ClienteId = 2, Nombre = "Juan Ruiz", Email = "juanruiz@hotmail.com", Activo = true},
  13:      new Cliente{ ClienteId = 3, Nombre = "Nathalia Torres", Email = "nata@hotmail.com", Activo = false},
  14:      new Cliente{ ClienteId = 1,
  15:          Nombre = "Oscar Torres", 
  16:          Email = "oscart@hotmail.com",
  17:          Activo = false, 
  18:          Ciudades = new List<Ciudad>(){
  19:              new Ciudad { CiudadId = 1, Nombre = "Bogotá"},
  20:              new Ciudad { CiudadId = 2, Nombre = "Cali"},
  21:              new Ciudad { CiudadId = 3, Nombre = "Medellin"},
  22:              new Ciudad { CiudadId = 3, Nombre = "Pereira"},
  23:          }},
  24:      new Cliente{ ClienteId = 5, Nombre = "Juan Ruiz", Email = "juanruiz@hotmail.com", Activo = true},
  25:      new Cliente{ ClienteId = 6, Nombre = "Nathalia Torres", Email = "nata@hotmail.com", Activo = false},
  26:      new Cliente{ ClienteId = 1,
  27:          Nombre = "Sandra Aleman", 
  28:          Email = "s.aleman@hotmail.com",
  29:          Activo = true, 
  30:          Ciudades = new List<Ciudad>(){
  31:              new Ciudad { CiudadId = 1, Nombre = "Bogotá"},
  32:              new Ciudad { CiudadId = 2, Nombre = "Cali"},
  33:          }},
  34:      new Cliente{ ClienteId = 8, Nombre = "Juan Ruiz", Email = "juanruiz@hotmail.com", Activo = true},
  35:      new Cliente{ ClienteId = 9, Nombre = "Nathalia Torres", Email = "nata@hotmail.com", Activo = false}
  36:  };

Ahora,  la idea es realizar dos cambios en la plantilla:

1. Si un cliente esta activo la fila será de un color naranja (o algo parecido) y si no está activo debe ser gris.

2. Si un cliente ha visitado ciudades en la última celda de la fila las listaremos, de lo contrario se colocará el texto  “-”.

JSRender nos provee dos funciones, la primera es if para evaluar una condición y la segunda es for para recorrer una colección (si muy al estilo de C#), entonces modificando un poco la definición de la plantilla para cumplir con los dos requerimientos tenemos:

   1:  <script type="text/x-jsrender" id="DataTemplate">
   2:          {{if Activo}}
   3:              <tr class='active'><td>{{:ClienteId}}</td><td>{{:Nombre}}</td><td>{{:Email}}</td><td>{{:Activo}}</td>
   4:                  <td>
   5:                      {{if Ciudades}}
   6:                          {{for Ciudades}}
   7:                              <p>{{:Nombre}}</p>
   8:                          {{/for}}
   9:                      {{else}}
  10:                          <p>-</p>
  11:                      {{/if}}
  12:                  </td>
  13:              </tr>
  14:          {{else}}
  15:              <tr class='disable'><td>{{:ClienteId}}</td><td>{{:Nombre}}</td><td>{{:Email}}</td><td>{{:Activo}}</td>
  16:                  <td>
  17:                      {{if Ciudades}}
  18:                          {{for Ciudades}}
  19:                              <p>{{:Nombre}}</p>
  20:                          {{/for}}
  21:                      {{else}}
  22:                          <p>-</p>
  23:                      {{/if}}
  24:                  </td>
  25:              </tr>
  26:          {{/if}}
  27:      </script>

Como se puede observar, lo primero que hacemos es evaluar el valor del campo Activo con {{if Activo}} que devuelve true/false según sea, también es posible hacer comparaciones como igual a, mayor o menor, luego para las ciudades de nuevo tenemos un if pero observen el uso del for en {{for Ciudades}}, allí lo que hacemos es recorrer cada elemento dentro de Ciudades y vamos mostrando el nombre. Finalmente si ejecutamos lo que tenemos es algo como (no se fijen mucho en el diseño ya que no es lo mío):

image

Espero les sea de utilidad el post, les dejo el código del ejemplo, saludos!

Descarga el ejemplo!

Publicado en ASP.net, ASP.NET Web API, jquery | Etiquetado: , | 2 Comentarios »

[ASP.NET] Cargando datos con WebAPI y JSRender

Publicado por Julio Avellaneda en 10/06/2012

Hace algún tiempo, realice algunos post sobre las Microsoft jQuery Templates (míralos acá: post I, post II, post III) y en resumen lo que podíamos realizar era obtener datos de alguna fuente como puede ser un servicio y mostrarlos en el cliente, todo esto utilizando JavaScript, lamentablemente ese proyecto se ha quedado atrás… y ahora tenemos una nueva y muy buena alternativa, JSRender, JSRender tiene la misma filosofía de las jQuery Templates pero con mejores características, así que quiero mostrarles un pequeño ejemplo de como lo podemos usar en conjunto con WebAPI.. como ya sabrán WebAPI esta muy de moda y no des para menos, realmente es muy bueno y me ha gustado bastante, así que manos a la obra:

1. El modelo

Como primera medida vamos a crear una clase Cliente que va a actuar como el modelo:

   1:  public class Cliente
   2:  {
   3:      public int ClienteId { get; set; }
   4:      public string Nombre { get; set; }
   5:      public string Email { get; set; }
   6:      public bool Activo { get; set; }
   7:  }

2. El controlador

En este caso vamos a crear un controlador WebAPI, recuerden que WebAPI no solo esta disponible para ASP.NET MVC, también es posible utilizarla con ASP.NET Web Forms. Añadimos un nuevo ítem de tipo Web API Controller y como nombre le damos ClienteController, y allí  para este ejemplo solo vamos a tener una función llamada GetAll la cual retornará todos los clientes existentes.

   1:  public class ClienteController : ApiController
   2:  {
   3:      private readonly List<Cliente> clientes = new List<Cliente>()
   4:      {
   5:          new Cliente{ ClienteId = 1, Nombre = "Julio Avellaneda", Email = "julito_gtu@hotmail.com", Activo = true},
   6:          new Cliente{ ClienteId = 2, Nombre = "Juan Ruiz", Email = "juanruiz@hotmail.com", Activo = true},
   7:          new Cliente{ ClienteId = 3, Nombre = "Nathalia Torres", Email = "nata@hotmail.com", Activo = false},
   8:          new Cliente{ ClienteId = 4, Nombre = "Julio Avellaneda", Email = "julito_gtu@hotmail.com", Activo = true},
   9:          new Cliente{ ClienteId = 5, Nombre = "Juan Ruiz", Email = "juanruiz@hotmail.com", Activo = true},
  10:          new Cliente{ ClienteId = 6, Nombre = "Nathalia Torres", Email = "nata@hotmail.com", Activo = false},
  11:          new Cliente{ ClienteId = 7, Nombre = "Julio Avellaneda", Email = "julito_gtu@hotmail.com", Activo = true},
  12:          new Cliente{ ClienteId = 8, Nombre = "Juan Ruiz", Email = "juanruiz@hotmail.com", Activo = true},
  13:          new Cliente{ ClienteId = 9, Nombre = "Nathalia Torres", Email = "nata@hotmail.com", Activo = false}
  14:      };
  15:   
  16:      public IEnumerable<Cliente> GetAll()
  17:      {
  18:          return clientes;
  19:      }
  20:  }

3. Configurando WebAPI

Una vez que tenemos listo el controlador, lo que necesitamos hacer es configurar el ruteo para poder llamar a los métodos del controllador, así que lo primero que haremos es crear una clase con un método estático y luego llamarlo en el evento Application_Start de el Global.asax:

   1:  public class RouteConfig
   2:  {
   3:      public static void RegisterRoutes()
   4:      {
   5:          RouteTable.Routes.MapHttpRoute(
   6:              name: "DefaultApi",
   7:              routeTemplate: "api/{controller}/{id}",
   8:              defaults: new { id = RouteParameter.Optional }
   9:          );
  10:      }
  11:  }

Y en el Global.asax:

   1:  protected void Application_Start(object sender, EventArgs e)
   2:  {
   3:      RouteConfig.RegisterRoutes();
   4:  }

4. Creando el HTML

Una vez que tenemos todo listo, vamos a crear una página para mostrar los datos:

   1:  <div>
   2:      <h1>Listado de clientes</h1>
   3:      <hr />
   4:      <table id="tblData">
   5:          <thead>
   6:              <tr>
   7:                  <th>Cliente Id</th>
   8:                  <th>Nombre</th>
   9:                  <th>Email</th>
  10:                  <th>Estado</th>
  11:              </tr>
  12:          </thead>
  13:          <tbody></tbody>
  14:      </table>
  15:  </div>

Para el ejemplo tenemos definida una tabla en la cual mostraremos los datos.

5. Referenciando Scripts

Ahora, vamos a añadir referencias a dos archivos JavaScript, uno será jQuery y le otro jsrender, sin embargo acá quiero dejar claro que a diferencia de muchos plugin jsrender NO necesita de jQuery, simplemente lo he añadido ya que me facilita el acceso al DOM y a eventos del lado del cliente:

   1:  <script src="Scripts/jquery-1.8.2.js"></script>
   2:  <script src="Scripts/jsrender.js"></script>

6. Creando la plantilla

Ahora es tiempo de crear la plantilla que usará jsrender para mostrar los datos:

   1:  <script type="text/x-jsrender" id="DataTemplate">
   2:      <tr><td>{{:ClienteId}}</td><td>{{:Nombre}}</td><td>{{:Email}}</td><td>{{:Activo}}</td></tr>
   3:  </script>

Lo primero que se debe tener presente es que el tipo del script debe ser text/x-jsrender, y le debemos definir un id para luego poder referenciarla, el cuerpo de la plantilla simplemente es una pequeña parte del body de una tabla (recuerdan que en el HTML definimos una tabla, paso 4), y con la sintaxis: {{:NOMBRE_CAMPO}} es que se define cual es el dato que se desea mostrar.

7. Enlazando datos:

Finalmente, llego la hora de enlazar la plantilla con los datos proporcionados por WebAPI, para este trabajo nos apoyaremos en jQuery y su facilidad para llamar servicios:

   1:  <script type="text/javascript">
   2:      $(document).on("ready", function () {
   3:          $.getJSON("/api/cliente",
   4:              function (data) {
   5:                  $("#tblData tbody").html($("#DataTemplate").render(data));
   6:          });
   7:      })
   8:  </script>

Como el servicio nos devuelve los datos en formato JSON por brevedad se hace uso de $.getJSON, como primer parámetro le pasamos la URL que debe llamar, y en segundo lugar la función de callback, en dicha función lo que hacemos es cargarle un HTML al cuerpo de la tabla, pero como en este caso es una plantilla lo primero es referenciarla por medio de su ID y luego le decimos los datos a cargar con render(data).

Ahora si ejecutamos la aplicación tenemos:

image

Espero les sea de utilidad, les dejo el código con el ejemplo.

Descarga el ejemplo.

Publicado en ASP.net, ASP.NET Web API | Etiquetado: , | 7 Comentarios »

[ASP.NET] Controles enlazados a datos en ASP.NET 4.5

Publicado por Julio Avellaneda en 09/10/2012

Hola a todos, hoy quiero mostrarles una nueva características que trae ASP.NET 4.5 y es la de realizar binding directamente desde la definición (HTML) del control, en mi opinión una característica bastante cool y que se asemeja a utilizar el patrón MVVM (claro una pequeña aproximación), los que ya han trabajado con WPF o Windows 8 ya les será tema conocido.

Entonces en primer lugar vamos a crear una clase Cliente, con 4 propiedades:

   1:  public class Cliente
   2:  {
   3:      public int ClienteId { get; set; }
   4:      public string Nombre { get; set; }
   5:      public string Apellido { get; set; }
   6:      public string Email { get; set; }
   7:  }

Ahora, para el ejemplos utilizaremos un GridView, y acá viene la primera propiedad nueva, en la definición del Grid vamos a utilizar ItemType, y allí definimos en esta caso la clase Cliente creada…y gracias al querido Visual Studio y su intellisense será muy sencillo:

image

Y ahora vamos para las columnas, en este caso para seguir aprovechando lo nuevo en ASP.NET 4.5 las vamos a definir utilizando TemplateField, y de nuevo tenemos la gran ayuda del intellisense:

image

Bueno y finalmente para el enlace a datos vamos a usar la propiedad SelectMethod, allí debemos colocar el nombre de un método que se encuentre en el code behind de la página, ese método debe ser público, entonces el HTML de GridView finalmente sería:

   1:  <asp:GridView ID="grvClientes" runat="server" AutoGenerateColumns="false" 
   2:      ItemType="Controles_Tipados.model.Cliente" SelectMethod="ObtenerClientes">
   3:      <Columns>
   4:          <asp:TemplateField HeaderText="Cliente Id">
   5:              <ItemTemplate><%# Item.ClienteId %></ItemTemplate>
   6:          </asp:TemplateField>
   7:          <asp:TemplateField HeaderText="Nombre">
   8:              <ItemTemplate><%# Item.Nombre %></ItemTemplate>
   9:          </asp:TemplateField>
  10:          <asp:TemplateField HeaderText="Apellido">
  11:              <ItemTemplate><%# Item.Apellido %></ItemTemplate>
  12:          </asp:TemplateField>
  13:          <asp:TemplateField HeaderText="Email">
  14:              <ItemTemplate><%# Item.Email %></ItemTemplate>
  15:          </asp:TemplateField>
  16:      </Columns>
  17:  </asp:GridView>

Y el code behind de la página:

   1:  private static readonly List<Cliente> clientes = new List<Cliente>(){
   2:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" },
   3:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" },
   4:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" },
   5:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" },
   6:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" },
   7:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" },
   8:      new Cliente { ClienteId = 1, Nombre = "Julio", Apellido = "Avellaneda", Email = "julito_gtu@hotmail.com" }
   9:  };
  10:   
  11:  public List<Cliente> ObtenerClientes()
  12:  {
  13:      return clientes;
  14:  }

En este caso tenemos una lista con datos fijos, pero si se quiere más dinamismo podríamos tener una consulta a base de datos.

Y para profundizar más en el tema: Strongly Typed Data Controls

Espero les haya gustado el post… saludos!

Publicado en ASP.net, gridview | Etiquetado: , | 3 Comentarios »

[ASP.NET] Validaciones no intrusivas en ASP.NET 4.5

Publicado por Julio Avellaneda en 09/02/2012

Hola a todos, volviendo al desarrollo Web, hoy quiero aprovechar este post para mostrar una de las nuevas características de ASP.NET 4.5 que son las validaciones no intrusivas y el error que vamos a obtener cuando creamos una nueva aplicación Web.

Vamos a crear una nueva aplicación Web, agregar una nueva página aspx y allí vamos a tener un formulario para el registro de personas, adicionalmente usaremos algunos validadores que ofrece ASP.NET (si no los conoces revisa este post), entonces el sencillo código que necesitamos es:

   1:  <form id="form1" runat="server">
   2:  <div>
   3:      <table>
   4:          <tr>
   5:              <td>Nombre:</td>
   6:              <td>
   7:                  <asp:TextBox ID="txtNombre" runat="server" Width="300px"></asp:TextBox>
   8:                  <asp:RequiredFieldValidator ID="requiredNombre" runat="server" ControlToValidate="txtNombre" ErrorMessage="*"></asp:RequiredFieldValidator>
   9:              </td>
  10:          </tr>
  11:          <tr>
  12:              <td>Correo:</td>
  13:              <td>
  14:                  <asp:TextBox ID="txtCorreo" runat="server" Width="300px"></asp:TextBox>
  15:                  <asp:RequiredFieldValidator ID="requiredCorreo" runat="server" ControlToValidate="txtCorreo" ErrorMessage="*"></asp:RequiredFieldValidator>
  16:              </td>
  17:          </tr>
  18:          <tr>
  19:              <td>Usuario:</td>
  20:              <td>
  21:                  <asp:TextBox ID="txtUsuario" runat="server" Width="300px"></asp:TextBox>
  22:                  <asp:RequiredFieldValidator ID="requiredUsuario" runat="server" ControlToValidate="txtUsuario" ErrorMessage="*"></asp:RequiredFieldValidator>
  23:              </td>
  24:          </tr>
  25:          <tr>
  26:              <td>Clave:</td>
  27:              <td>
  28:                  <asp:TextBox ID="txtClave" runat="server" Width="300px" TextMode="Password"></asp:TextBox>
  29:                  <asp:RequiredFieldValidator ID="requiredClave" runat="server" ControlToValidate="txtClave" ErrorMessage="*"></asp:RequiredFieldValidator>
  30:              </td>
  31:          </tr>
  32:          <tr>
  33:              <td><asp:Button ID="btnGuardar" runat="server" Text="Guardar" /></td>
  34:          </tr>
  35:      </table>
  36:  </div>
  37:  </form>

Como vemos, el HTML es muy simple, peor ahora si lanzamos la aplicación vamos  a obtener el siguiente error:

error

Extraño no? simplemente creamos una página bastante sencilla (sin nada de código de servidor) y ya está fallando… pero si revisamos un poco el error vemos que dice “WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping…” y ya tenemos una idea del error, lo que pasa es que con ASP.NET 4.5 tenemos una nueva característica la cual reducir la cantidad de código JavaScript necesario, la definición exacta dice:

You can now configure the built-in validator controls to use unobtrusive JavaScript for client-side validation logic. This significantly reduces the amount of JavaScript rendered inline in the page markup and reduces the overall page size.

Y dicha característica viene habilitada por defecto, para deshabilitarla vamos a nuestro Global.asax y en el evento Application_Start le decimos:

   1:  ValidationSettings.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.None;

Y ahora si lanzamos de nuevo la aplicación va a funcionar… pero no estaríamos aprovechando la validación no intrusiva, y si revisamos el HTML que es generado en el cliente tenemos:

   1:  <!DOCTYPE html>
   2:   
   3:  <html xmlns="http://www.w3.org/1999/xhtml">
   4:  <head><title>
   5:      Formulario
   6:  </title></head>
   7:  <body>
   8:      <form method="post" action="index.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">
   9:  <div class="aspNetHidden">
  10:  <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
  11:  <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
  12:  <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="2pkd4JZKXmDyDJwu0HIaaT5x/EzINW3Fmj5ECNYtq721M2fzxgYIW/yLzuVDUpE6C5+JtdW4Mo7Mh7EH1jcQPCiVMtXSlRRYD3i7hJ3zQLM=" />
  13:  </div>
  14:   
  15:  <script type="text/javascript">
  16:  //<![CDATA[
  17:  var theForm = document.forms['form1'];
  18:  if (!theForm) {
  19:      theForm = document.form1;
  20:  }
  21:  function __doPostBack(eventTarget, eventArgument) {
  22:      if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
  23:          theForm.__EVENTTARGET.value = eventTarget;
  24:          theForm.__EVENTARGUMENT.value = eventArgument;
  25:          theForm.submit();
  26:      }
  27:  }
  28:  //]]>
  29:  </script>
  30:   
  31:   
  32:  <script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZAlhwiK26CMjFC_AwUoa5b3ERCspA6cmt_C-L8IOpCe633BVnc0wcDgTvonIIsSvwQ2&amp;t=634776373276709129" type="text/javascript"></script>
  33:   
  34:   
  35:  <script src="/WebResource.axd?d=x2nkrMJGXkMELz33nwnakEDhIJdn4zA9e1UqVq1SVvHhRhIprKEH70Wnr0YNmajC6LdVxQkRSvYza9nzCfZpzIEPGw7MYTdtpXpxdmoJjww1&amp;t=634776373276709129" type="text/javascript"></script>
  36:  <script type="text/javascript">
  37:  //<![CDATA[
  38:  function WebForm_OnSubmit() {
  39:  if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
  40:  return true;
  41:  }
  42:  //]]>
  43:  </script>
  44:   
  45:  <div class="aspNetHidden">
  46:   
  47:      <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="bZYSXvfMEK7zHv9kV0tE+oZEnunr/8QE7gS9ULLQ4JyQa0/rv/1MRHr1bmVesMg6m/hAbEjp+lbFzmo0SV+QBKLDALpSfGJ0DfJ5FA03pkiwbqmguFNLc2gD7rvhbwgkveOk/e6MOPe2FJKM0lEwaBBiTadifQmqoEyokjWDmTbeUzilOBcBLxfc4JnhDC5gTorEWeVaxxVnfEZrKxCLsg==" />
  48:  </div>
  49:      <div>
  50:          <table>
  51:              <tr>
  52:                  <td>Nombre:</td>
  53:                  <td>
  54:                      <input name="txtNombre" type="text" id="txtNombre" style="width:300px;" />
  55:                      <span id="requiredNombre" style="visibility:hidden;">*</span>
  56:                  </td>
  57:              </tr>
  58:              <tr>
  59:                  <td>Correo:</td>
  60:                  <td>
  61:                      <input name="txtCorreo" type="text" id="txtCorreo" style="width:300px;" />
  62:                      <span id="requiredCorreo" style="visibility:hidden;">*</span>
  63:                  </td>
  64:              </tr>
  65:              <tr>
  66:                  <td>Usuario:</td>
  67:                  <td>
  68:                      <input name="txtUsuario" type="text" id="txtUsuario" style="width:300px;" />
  69:                      <span id="requiredUsuario" style="visibility:hidden;">*</span>
  70:                  </td>
  71:              </tr>
  72:              <tr>
  73:                  <td>Clave:</td>
  74:                  <td>
  75:                      <input name="txtClave" type="password" id="txtClave" style="width:300px;" />
  76:                      <span id="requiredClave" style="visibility:hidden;">*</span>
  77:                  </td>
  78:              </tr>
  79:              <tr>
  80:                  <td><input type="submit" name="btnGuardar" value="Guardar" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;btnGuardar&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" id="btnGuardar" /></td>
  81:              </tr>
  82:          </table>
  83:      </div>
  84:      
  85:  <script type="text/javascript">
  86:  //<![CDATA[
  87:  var Page_Validators =  new Array(document.getElementById("requiredNombre"), document.getElementById("requiredCorreo"), document.getElementById("requiredUsuario"), document.getElementById("requiredClave"));
  88:  //]]>
  89:  </script>
  90:   
  91:  <script type="text/javascript">
  92:  //<![CDATA[
  93:  var requiredNombre = document.all ? document.all["requiredNombre"] : document.getElementById("requiredNombre");
  94:  requiredNombre.controltovalidate = "txtNombre";
  95:  requiredNombre.errormessage = "*";
  96:  requiredNombre.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
  97:  requiredNombre.initialvalue = "";
  98:  var requiredCorreo = document.all ? document.all["requiredCorreo"] : document.getElementById("requiredCorreo");
  99:  requiredCorreo.controltovalidate = "txtCorreo";
 100:  requiredCorreo.errormessage = "*";
 101:  requiredCorreo.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
 102:  requiredCorreo.initialvalue = "";
 103:  var requiredUsuario = document.all ? document.all["requiredUsuario"] : document.getElementById("requiredUsuario");
 104:  requiredUsuario.controltovalidate = "txtUsuario";
 105:  requiredUsuario.errormessage = "*";
 106:  requiredUsuario.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
 107:  requiredUsuario.initialvalue = "";
 108:  var requiredClave = document.all ? document.all["requiredClave"] : document.getElementById("requiredClave");
 109:  requiredClave.controltovalidate = "txtClave";
 110:  requiredClave.errormessage = "*";
 111:  requiredClave.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
 112:  requiredClave.initialvalue = "";
 113:  //]]>
 114:  </script>
 115:   
 116:   
 117:  <script type="text/javascript">
 118:  //<![CDATA[
 119:   
 120:  var Page_ValidationActive = false;
 121:  if (typeof(ValidatorOnLoad) == "function") {
 122:      ValidatorOnLoad();
 123:  }
 124:   
 125:  function ValidatorOnSubmit() {
 126:      if (Page_ValidationActive) {
 127:          return ValidatorCommonOnSubmit();
 128:      }
 129:      else {
 130:          return true;
 131:      }
 132:  }
 133:          //]]>
 134:  </script>
 135:  </form>
 136:  </body>
 137:  </html>

Como vemos son 137 líneas de código y en la parte final bastante código JavaScript.

Ahora vamos a habilitar la validación no intrusiva (recuerden en el Global.asax):

   1:  ValidationSettings.UnobtrusiveValidationMode = System.Web.UI.UnobtrusiveValidationMode.WebForms;

Y para solucionar el error simplemente adicionamos la librería jQuery, pero lo debemos hacer de nuevo en el Global.asax de la siguiente manera:

   1:  ScriptManager.ScriptResourceMapping.AddDefinition("jquery",
   2:      new ScriptResourceDefinition
   3:      {
   4:          Path = "/Scripts/jquery-1.8.0.js"
   5:      }
   6:  );

En Path especificamos la ruta de la librería, y ahora si volvemos a lanzar la aplicación y a revisar el HTML generado tenemos:

   1:  <!DOCTYPE html>
   2:   
   3:  <html xmlns="http://www.w3.org/1999/xhtml">
   4:  <head><title>
   5:      Formulario
   6:  </title></head>
   7:  <body>
   8:      <form method="post" action="index.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">
   9:  <div class="aspNetHidden">
  10:  <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
  11:  <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
  12:  <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="alparljtLhNy2xupYlZBZObSGVyvyxxogr8jThTTwWgWjbCJGZlWBvzpy1msUcxlr7zmHWThPw30eTwgrEBC9jxViHQKMQdl97MNwbdtIyg=" />
  13:  </div>
  14:   
  15:  <script type="text/javascript">
  16:  //<![CDATA[
  17:  var theForm = document.forms['form1'];
  18:  if (!theForm) {
  19:      theForm = document.form1;
  20:  }
  21:  function __doPostBack(eventTarget, eventArgument) {
  22:      if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
  23:          theForm.__EVENTTARGET.value = eventTarget;
  24:          theForm.__EVENTARGUMENT.value = eventArgument;
  25:          theForm.submit();
  26:      }
  27:  }
  28:  //]]>
  29:  </script>
  30:   
  31:   
  32:  <script src="/WebResource.axd?d=pynGkmcFUV13He1Qd6_TZAlhwiK26CMjFC_AwUoa5b3ERCspA6cmt_C-L8IOpCe633BVnc0wcDgTvonIIsSvwQ2&amp;t=634776373276709129" type="text/javascript"></script>
  33:   
  34:   
  35:  <script src="/Scripts/jquery-1.8.0.js" type="text/javascript"></script>
  36:  <script src="/WebResource.axd?d=x2nkrMJGXkMELz33nwnakEDhIJdn4zA9e1UqVq1SVvHhRhIprKEH70Wnr0YNmajC6LdVxQkRSvYza9nzCfZpzIEPGw7MYTdtpXpxdmoJjww1&amp;t=634776373276709129" type="text/javascript"></script>
  37:  <script type="text/javascript">
  38:  //<![CDATA[
  39:  function WebForm_OnSubmit() {
  40:  if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
  41:  return true;
  42:  }
  43:  //]]>
  44:  </script>
  45:   
  46:  <div class="aspNetHidden">
  47:   
  48:      <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="+364tW9Dc7pDt6plQ90xe5FouuoNJLAEzbosO0J1tGmDKGpwQcxZ1kdqIV/tRvjZENOFLgzZM85V7T0z3t6I607wioiuB8cTrjZfCFSxHIPE/QbqekiEkZw9CeWGtKKGd2SzLZyMEXvyjxGP4xzOcHDDG0s00+EWD0Gay9W4uDXNzzVdNiwpoNp6dSj21Rvzuttb/+4L1dlkpikZJVdSig==" />
  49:  </div>
  50:      <div>
  51:          <table>
  52:              <tr>
  53:                  <td>Nombre:</td>
  54:                  <td>
  55:                      <input name="txtNombre" type="text" id="txtNombre" style="width:300px;" />
  56:                      <span data-val-controltovalidate="txtNombre" data-val-errormessage="*" id="requiredNombre" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>
  57:                  </td>
  58:              </tr>
  59:              <tr>
  60:                  <td>Correo:</td>
  61:                  <td>
  62:                      <input name="txtCorreo" type="text" id="txtCorreo" style="width:300px;" />
  63:                      <span data-val-controltovalidate="txtCorreo" data-val-errormessage="*" id="requiredCorreo" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>
  64:                  </td>
  65:              </tr>
  66:              <tr>
  67:                  <td>Usuario:</td>
  68:                  <td>
  69:                      <input name="txtUsuario" type="text" id="txtUsuario" style="width:300px;" />
  70:                      <span data-val-controltovalidate="txtUsuario" data-val-errormessage="*" id="requiredUsuario" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>
  71:                  </td>
  72:              </tr>
  73:              <tr>
  74:                  <td>Clave:</td>
  75:                  <td>
  76:                      <input name="txtClave" type="password" id="txtClave" style="width:300px;" />
  77:                      <span data-val-controltovalidate="txtClave" data-val-errormessage="*" id="requiredClave" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>
  78:                  </td>
  79:              </tr>
  80:              <tr>
  81:                  <td><input type="submit" name="btnGuardar" value="Guardar" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;btnGuardar&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" id="btnGuardar" /></td>
  82:              </tr>
  83:          </table>
  84:      </div>
  85:      </form>
  86:  </body>
  87:  </html>

Lo primero que observamos es que solo tenemos 87 líneas en contra de las 137 anteriores (bastantes menos no?), lo segundo es que ya no tenemos tanto código JavaScript y lo tercero es que aparecen nuevos atributos en los span, y esos atributos son los que ahora determinan las validaciones. Inicialmente el HTML de un span era:

   1:  <span id="requiredNombre" style="visibility:hidden;">*</span>

Y luego con la validación no intrusiva lista:

   1:  <span data-val-controltovalidate="txtNombre" data-val-errormessage="*" id="requiredNombre" data-val="true" data-val-evaluationfunction="RequiredFieldValidatorEvaluateIsValid" data-val-initialvalue="" style="visibility:hidden;">*</span>

Como se puede ver, se han generado nuevos atributos del tipo data-val-<…> los cuales determinan como se realizará la validación.

Espero les sea de utilidad este post, saludos!

Publicado en ASP.net | Etiquetado: | 2 Comentarios »

 
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 1.644 seguidores