O también se os habrá dado el caso de que necesitéis hacer cambios en un script y os da miedillo subirlo directamente a producción sin haberlo probado antes suficientemente en el entorno real. Esto es un tema especialmente peliagudo si estáis desarrollando una plataforma SaaS en la que cientos de clientes usen en sus páginas web una referencia a vuestro script y cualquier cambio en el mismo puede traer consecuencias graves para el servicio.
Por ejemplo, imaginad que prestamos un servicio similar a Google Analytics, y todos nuestros clientes tienen una referencia en sus páginas a nuestro archivo "analytics.js" para trackear sus visitas. ¿Cómo podríamos introducir cambios en dicho archivo de script para hacer pruebas en sitios donde nos interese, sin que afectara al resto de clientes ni a los visitantes de sus páginas?
A priori no parece haber una respuesta sencilla, pero sí que la hay. Sólo necesitamos Fiddler y tres minutos de nuestro tiempo para conseguirlo :)
Hace sólo unos días veíamos cómo eliminar y personalizar los botones que Internet Explorer 10 añade a nuestros cuadros de edición estándar, pero nos dejábamos por detrás un caso especial: los controles de edición de contraseñas, o sea, los
<input type="password">
de toda la vida.En esta ocasión, IE10 muestra por cortesía un pequeño icono con forma de ojo, que permite visualizar el contenido del campo mientras lo mantenemos pulsado:
Si por cualquier razón queremos eliminar este botón, debemos utilizar una técnica similar a la que vimos en el post anterior, esta vez utilizando el pseudoselector
-ms-reveal
, así:input::-ms-reveal { display: none; }Y por supuesto, podríamos utilizar también este enfoque para personalizarlo y adaptarlo mejor al look de nuestro sitio web:
input::-ms-reveal { color: white; background-color: red; }Con lo que tendríamos un resultado:
Publicado en: Variable not found.
Pues bien, hay veces que a nivel de diseño no nos interesa que se muestre la pequeña “X” en los controles, su posición entra en conflicto con otro elemento visual, o simplemente no queremos aportar esta funcionalidad, por lo que es posible desactivar esta característica de los
<input>
usando CSS:input::-ms-clear{ display: none; }Tan sencillo como eso.
Pero seguro que te estás preguntando, ¿y en vez de eliminarla puedo personalizarla? Pues un poco también ;-) Observad el siguiente código:
input::-ms-clear{ background-color: red; color: white; border: 1px solid #808080; }En tiempo de ejecución, esa discreta e insípida “X” se habría convertido en algo bastante más contundente ;-)
Publicado en: Variable not found.
Sin embargo, nuestras aplicaciones web son muy diferentes cuando el cliente no dispone de una conexión de alta velocidad. Lo que nosotros percibimos en tiempo de desarrollo como una maravilla de agilidad, espectacularidad y facilidad de uso, puede ser un auténtico desastre para el cliente si no hemos tenido en cuenta que no todo el mundo puede disfrutar de conexiones de alta calidad.
Por esta razón, es interesante realizar de vez en cuando pruebas de nuestros sistemas reduciendo de forma artificial el ancho de banda disponible, de forma que podamos detectar en qué puntos podemos mejorar la experiencia del usuario en estos escenarios.
Publicado por José M. Aguilar a las 9:30 a. m.
Etiquetas: depuración, desarrollo, fiddler, trucos, web
Pues bien, hace poco he dado con Lorempixum, un interesante servicio que nos proporciona algo similar sobre el contenido gráfico: un generador de imágenes de relleno. Y es que, durante nuestro trabajo, también nos viene de fábula tener a mano un buen banco de imágenes clasificadas, con distintos tamaños, y sin problemas de licencia, listas para ser utilizadas en prototipos de sitios web.
Lorempixum permite dos vías para generar imágenes. La primera de ellas se basa en acudir al sitio web (http://www.lorempixum.com/) y utilizar el pequeño formulario que aparece para indicar los detalles de la imagen que deseamos generar.
Simplemente introduciendo o seleccionando el ancho, alto, la temática (a elegir entre las once disponibles, tales como gente, tecnología, transporte, naturaleza, etc.), y si deseamos que sea en color o escala de grises, el sistema seleccionará y generará automáticamente una imagen totalmente ajustada a nuestras pretensiones :-)
Otra posibilidad es invocar directamente al generador de Lorempixum utilizando URLs en las que introduciremos los parámetros de la imagen a generar. A continuación se muestran algunos ejemplos de llamadas, y el resultado obtenido:
Imagen aleatoria en color de 200px de ancho por 100px de alto Categoría “Sports” http://lorempixum.com/200/100/sports/ | |
Imagen aleatoria en grises de 200px de ancho por 100px de alto Categoría “Sports” http://lorempixum.com/g/200/100/sports/ (La “g” indica que queremos la imagen en grises) | |
Quinta imagen en color de 200px x 100px Categoría “Fashion” http://lorempixum.com/200/100/fashion/5/ | |
Imagen aleatoria en color de 200px de ancho por 180px de alto Categoría “City” Texto sobreimpreso “Variable not found” http://lorempixum.com/200/180/city/Variable not found/ |
Obviamente, estas direcciones podemos teclearlas directamente en el navegador para obtener las imágenes, o bien introducirlas como origen de los
<img>
de nuestras páginas, por ejemplo así: <img src="http://lorempixum.com/200/180/city" alt=”Ciudad” />
En definitiva, un servicio interesante para no tener que andar por ahí
Publicado en: Variable not found.
En estos eventos, como se puede ver en la agenda, se tratarán temas relacionados con tecnologías y desarrollo para la web:
- Migración a HTML5
- IE9 para desarrolladores
- Buenas prácticas en la detección de navegadores
- El poder de los CMS
- ASP.NET MVC 3
- Barcelona, 22 de marzo
- Valencia, 24 de marzo
- Bilbao, 29 de marzo
- Sevilla, 31 de marzo (hey, juego en casa! ;-))
- Madrid, 5 de abril
¡Espero veros por allí! :-)
Publicado en: Variable not found.
BaseKit es una aplicación totalmente on-line que permite a diseñadores crear sitios web completos sin necesidad de tener conocimientos de HTML, javascript y, si apuramos, incluso ni de CSS, rompiendo así la brecha que tradicionalmente divide el mundo del diseño y del desarrollo web.
Otra ventaja para los que no se sienten cómodos lidiando con compañías de hosting es que el servicio cuenta con su propio alojamiento; en un par de clicks, el sitio web que estemos editando pasará a estar disponible en internet. De hecho, el alojamiento será el único concepto por el que BaseKit cobrará a los usuarios en el futuro.
La primera prueba de la facilidad con la que se pueden crear sitios web la encontramos al comenzar a trabajar con BaseKit, cuando tendremos que decidir cómo queremos crear el sitio web: importando un archivo Photoshop, seleccionando una plantilla base predefinida, o basándonos en un sitio disponible en la galería.
La primera opción permite subir directamente archivos en formato PSD cuyos contenidos y estructura serán utilizados para generar automáticamente la plantilla de la página.
Las siguientes opciones permiten tirar de elementos prediseñados, como plantillas o incluso sitios web completos, disponibles en la galería de BaseKit. Estas galerías todavía no ofrecen gran cantidad de elementos prediseñados, pero se entiende que es debido a que el producto está aún en fase de pruebas.
En cualquier caso, independientemente del modo de inicio lo que tendremos a continuación es un completo editor en el que podremos editar la página de forma visual, en plan drag&drop, de forma realmente sencilla.
De momento hay un buen número de widgets con los que crear los contenidos de la página, y obviamente tienen planes de seguir añadiendo nuevas posibilidades.
Para las pruebas debes utilizar Firefox 3.5.5 o superior; de momento BaseKit no soporta IE, aunque están trabajando en ello.
¡Venga, os espero!
Publicado en: Variable not found.
Publicado por José M. Aguilar a las 7:58 a. m.
Etiquetas: desarrollo, diseño, novedades, servicios on-line, web
En este post resumiré las mejoras introducidas en ASP.NET 4 que pueden ayudarnos en nuestra relación con los motores de búsqueda. No son novedades revolucionarias, puesto que todo lo que nos ofrecen podíamos conseguirlo con las versiones anteriores de ASP.NET de alguna u otra manera, aunque sin duda que nos facilitarán algo las cosas. :-)
Page.MetaDescription y Page.MetaKeywords
ASP.NET 4 incorpora a la clasePage
las propiedades MetaDescription
y MetaKeywords
para facilitarnos el acceso a la metainformación de la página.Con la primera de ellas,
MetaDescription
, podemos especificar en cada página una descripción individualizada, que será utilizada por los buscadores como un resumen de su contenido. Por ejemplo, Google, la incluye como parte de los resultados de las búsquedas.La segunda,
MetaKeywords
, permite añadir tags o palabras clave que puedan ser útiles para clasificar su contenido. Aunque la mayoría de los buscadores no utilizan esta información a efectos de indexado, al parecer algunos sí lo hacen, por lo que sigue siendo costumbre incorporar esta información.En ambos casos podemos establecer su contenido de forma declarativa, en las directivas de la página, así:
<%@ Page Title="Variable not found" Language="C#"
MasterPageFile="~/Blog.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="Variable.Blog"
MetaDescription = "Variable not found. Artículos, noticias, curiosidades,
reflexiones... sobre el mundo del desarrollo de software,
internet, u otros temas relacionados con la tecnología"
MetaKeywords = "desarrollo,programación,.net,c#,asp.net,asp.net mvc,software"
%>
Pero también, y esta posibilidad es bastante más interesante, podemos establecerlas mediante código, por ejemplo en el
Page_Load()
, lo que puede ser útil si por ejemplo tenemos que obtener valores desde una base de datos o similar:protected void Page_Load(object sender, EventArgs e)
{
Product prod = ObtenerProducto(); // Carga el producto
this.Title = prod.Denominacion;
this.MetaDescription = prod.DescripcionBreve;
this.MetaKeywords = prod.Tags;
}
En cualquiera de los casos, el resultado es el mismo. ASP.NET, a la hora de generar la página, añadirá en la sección
<head>
de la página una etiqueta <meta>
con la descripción y etiquetas proporcionadas:<title>NETBOOK ACER ASPIRE ONE D250-0BK</title>
<meta name="description" content="Netbook con procesador Intel® Atom N270 1.6 GHz, 1GB memoria, 160GB disco duro, t. gráfica Intel® GMA 950, pantalla 10.1' LED, webcam y Windows XP." />
<meta name="keywords" content="Netbook, ultraportátil, acer, aspire" />
Ni que decir tiene que la etiqueta
<head>
de la página (o la master que utilice) debe tener el correspondiente runat="server"
para que pueda ser modificada en tiempo de servidor.Response.RedirectPermanent()
Los más viejos del lugar recordarán queResponse.Redirect()
está con nosotros desde los tiempos del ASP tradicional, y desde entonces ha mantenido su función: enviar al agente de usuario un resultado HTTP 302, apuntándole una nueva dirección URL en la que localizar el recurso solicitado. Vamos, lo que toda la vida hemos llamado redirección. :-)Sin embargo, el código de estado 302 definido por el protocolo indica, literalmente, que el recurso solicitado ha sido localizado pero que se encuentra en otra dirección (retornada como información adicional a la respuesta) aunque sólo temporalmente. Por ello se dice que estas redirecciones son transitorias; el navegador (o los robots de búsqueda, en el caso que nos ocupa) no pueden asegurar que la URL indicada sea la ubicación correcta y permanente del recurso.
El código HTTP 301, sin embargo, indica que el recurso solicitado ha sido movido de forma permanente a la dirección que se retorna al agente de usuario. Esto podría ser útil, por ejemplo, si modificamos los dominios sobre los que corre un sitio web, o cambiamos el esquema de URLs que estamos utilizando y, entre otras cosas, quisiéramos aprovechar la información la información que ya tienen los buscadores sobre nuestro sitio.
Pues con este propósito ha sido incluido el método
Response.RedirectPermanent()
cuya forma de utilización es idéntica a las redirecciones habituales:public partial class About: System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Redirigimos About.aspx a AcercaDe.aspx
Response.RedirectPermanent("AcercaDe.aspx"); // 301 al canto!
}
}
¡Direcciones amigables!
¡Ya era hora de que ASP.NET ofreciera un mecanismo integrado para generar URLs amigables! El motor de routing introducido con ASP.NET 3.5 SP1 tan magníficamente aprovechado en el framework MVC, toma ahora su protagonismo también en el mundo de Webforms. Y la forma de usarlo, igual de sencilla. :-)Para que nuestra aplicación soporte friendly urls, tenemos que registrar durante la inicialización del sistema las rutas, o mejor dicho, el patrón del URLs, que vamos a entender. Por ejemplo, imaginemos que nuestra aplicación, un catálogo on-line, debe atender peticiones a direcciones como las siguientes para mostrar la página de detalle de un producto:
Esto podríamos conseguirlo durante la inicialización del sistema, registrando un patrón de ruta de la siguiente forma, en el
global.asax
:void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RegistrarRutas();
}
private void RegistrarRutas()
{
RouteTable.Routes.MapPageRoute(
"DetalleProducto", // Nombre de la ruta
"product/{productCode}", // patrón de URL
"~/product.aspx" // Página que procesará la petición
);
}
Lo que indica la ruta es que las direcciones de tipo
product/{productCode}
serán enviadas a la página física ~/product.aspx
. La porción variable de la URL, el parámetro {productCode}
podremos obtenerlo desde el código de la página para cargar los datos desde el almacén correspondiente, por ejemplo así (en product.aspx.cs
):public partial class Product : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string productCode = RouteData.Values["productCode"] as string;
if (!cargaProducto(productCode))
{
Response.Redirect("ProductNotFound.aspx");
}
}
}
Como puede intuirse, a través de la colección
RouteData.Values
podremos acceder a los parámetros suministrados en el interior de la ruta, es decir, los que forman parte de la URL de la página que introduce el usuario.Al igual que ocurre en ASP.NET MVC, el sistema de rutas es bidireccional, por lo que podremos también generar links ‘amistosos’ hacia recursos del sitio web, como en el siguiente ejemplo:
HyperLinkToAcerAspire.NavigateUrl =
GetRouteUrl("DetalleProducto", new { productCode = "ACER-ASPIRE-ONE-D250-0BK" } );
El método
GetRouteUrl()
genera la URL del producto utilizando el propio motor de routing, para lo que le pasamos el identificador de la ruta y, en un objeto anónimo, el valor para el parámetro requerido (productCode). El resultado para el caso anterior será la dirección: /product/ACER-ASPIRE-ONE-D250-0BK.Mejoras en el marcado
Aunque no vamos a detallarlas, o al menos en este post ;-), aparecen también en ASP.NET 4 un buen conjunto de novedades dirigidas a mejorar la calidad del marcado que enviamos a cliente. Y dado que siempre se ha dicho que un marcado respetuoso con los estándares es bueno para el SEO, estas nuevas capacidades del framework nos ayudarán también a mejorar nuestro posicionamiento.Publicado en: Variable not found.
Por ejemplo, si un servidor recibe esta solicitud:
GET / HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, (...omitido...), */*
Referer: http://www.google.es/search?hl=es&rls=ig&q=variable&btnG=Buscar&meta=&aq=f&oq=
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; (...omitido...) )
Accept-Language: es
Accept-Encoding: gzip, deflate
Host: www.variablenotfound.com
Connection: Keep-Alive
analizando el campo Referer se puede determinar de forma muy sencilla que se trata de un usuario que proviene de Google, y que estaba buscando el término “variable”. Esta característica aporta una información, que aunque no es demasiado fiable (se puede alterar y desactivar muy fácilmente), se utiliza con mucha frecuencia con fines estadísticos, o para adecuar el contenido de la página a las intenciones del usuario.
Sin embargo, como se trata de una característica manejada directamente por el navegador, podemos encontrarnos con que no todos actúan de la misma manera... o en otras palabras, es Internet Explorer es el que actúa de forma diferente al resto ;-)
Si la visita a nuestra página se produce como consecuencia de la ejecución de un script que ha modificado dinámicamente el
location.href
, o ha invocado a location.replace
, Internet Explorer saltará a la nueva dirección, pero no enviará el Referer en los encabezados de la petición, por lo que en el punto de destino no se podrá conocer el origen de la misma.Por tanto, un código como el siguiente hará que la página editar.asp no pueda conocer desde dónde se le ha referenciado:
<input type="button" value="editar" onclick="location.href='editar.asp';">
Dado que Microsoft todavía está considerando modificar este comportamiento, hay que darle un poco las vueltas para conseguirlo provocando el salto hacia la página de destino sin utilizar los mecanismos citados anteriormente.
Una forma muy ingeniosa que he encontrado se basa en crear dinámicamente un tag
<a>
con su correspondiente href
establecido, y simular la pulsación del mismo invocando al evento click:function navigateWithReferrer(url) {
var fakeLink = document.createElement("a");
if (typeof (fakeLink.click) == 'undefined')
location.href = url;
else {
fakeLink.href = url;
document.body.appendChild(fakeLink);
fakeLink.click();
}
}
Visto en: Velocity Reviews
Publicado en: Variable not found
Publicado por José M. Aguilar a las 9:09 a. m.
Etiquetas: asp.net, desarrollo, javascript, scripting, trucos, web
Aunque existen distintas formas para conseguirlo (algunas de ellas descritas en la propia web del producto), hay una que es realmente sencilla, no hay que configurar nada, y es bastante rápida de activar:
Publicado en: Variable not found.
Publicado por José M. Aguilar a las 11:58 p. m.
Etiquetas: asp.net, depuración, desarrollo, fiddler, herramientas, trucos, web
Cada vez que tengo que forzar la validación de los datos de un formulario Webforms mediante javascript me veo obligado a preguntarle a Google, ese que todo lo sabe, cómo era el nombre de la función. Cosas de la edad, supongo ;-)
Así que, a modo de auto-recordatorio y con la intención de que pueda ser útil a alguien más, ahí va: la función se llama Page_ClientValidate()
. Retorna “true” si, una vez evaluados todos los validadores de la página, el valor de los campos es correcto (al menos en cliente; otra cosa son las comprobaciones en servidor, p.e., las definidas en un CustomValidator
).
Y como ejemplo de uso, puede valer el siguiente. Se trata de un botón de envío en un formulario donde se compone un correo electrónico:
1: ...
2: <asp:Button ID="btnEnviar" runat="server" Text="Enviar mail"
3: OnClick="btnEnviar_Click"
4: OnClientClick="return confirmar();"
5: />
6: ...
7:
8: <script type="text/javascript">
9: function confirmar() {
10: if (!Page_ClientValidate()) // Fuerza la validación en cliente
11: return false;
12:
13: return confirm('¿Seguro que desea realizar el envío?');
14: }
15: </script>
Como se puede observar, en el atributo OnClientClick
del botón incluye un script en el que se retorna el valor devuelto por la función confirmar
. Si el retorno es false, se cancela el Postback, evitando así que se invoque al evento btnEnviar_Click
que es el que realiza el envío del mail propiamente dicho.
En el cuerpo de la función confirmar()
, en primer lugar, validamos la página; si ésta no supera el proceso, los validadores habrán mostrado sus mensajes de error y retornamos falso, haciendo que se anule el postback. Si la validación es correcta, solicitamos al usuario que confirme la acción y retornamos su decisión.
Publicado en: Variable not found.
Publicado por José M. Aguilar a las 11:40 p. m.
Etiquetas: .net, asp.net, desarrollo, nivel básico, trucos, validadores, web
Seguro que más de una vez has sufrido de lo lindo al tocar un archivo de hoja de estilos. Suelen estar mal organizados, ser muy extensos, difíciles de mantener, hay declaraciones duplicadas por todas partes… Y seguro que siempre te has preguntado si hay otra forma menos complicada de conseguir lo mismo.
K. Scott Allen nos habla en su post Keeping CSS Files DRY de .Less (dot less), un interesante componente portado del mundo Ruby capaz de “compilar” hojas de estilo que utiliza una notación extendida y mucho más potente del estándar CSS, permitiendo las siguientes características:
- Uso de variables. Less permite declarar y utilizar variables para los valores que utilizaremos frecuentemente en nuestra hoja de estilos, así:
@nice-blue: #5B83AD;
#header { color: @light-blue; }
#footer { color: @light-blue; }
- Operaciones. Podemos utilizar expresiones para obtener valores, por ejemplo:
@base: 5%;
@filler: @base * 2;
@other: @base + @filler;
color: #888 / 4;
background-color: @base-color + #111;
height: 100% / 2 + @filler;
Fijaos en un detalle de lo más interesante: Less es capaz de distinguir cuándo está operando con colores y cuándo con unidades, ofreciendo el resultado correcto en cada caso.
- Mezclas (mixins), otra potente capacidad de Less que seguro que puede venirnos bastante bien, que consiste en incluir dentro de un conjunto de reglas dentro de otro, sólo haciendo referencia a su selector:
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
#menu a {
color: #111;
.bordered;
}
.post a {
color: red;
.bordered;
}
- Reglas anidadas, que nos permiten definir reglas siguiendo una estructura más legible y fácilmente reconocible por su paralelismo con la estructura del documento:
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
:hover { text-decoration: none }
}
}
- Visibilidad de variables. Las variables pueden ser declaradas de forma global (como en el primer ejemplo) o asociadas a algún selector, lo que les aporta ámbito de visibilidad de forma muy similar a los lenguajes tradicionales:
@var: red;
#page {
@var: white;
#header {
color: @var; // color será “white”
}
}
- Accesores. Less permite utilizar valores de propiedades y variables como contenido para otras propiedades de forma muy natural:
#defaults {
@width: 960px;
@color: black;
}
.article { color: #294366; }
.comment {
width: #defaults[@width];
color: .article['color'];
}
Fijaos que el bloque #defaults no tiene por qué corresponder con un elemento del documento a formatear, se trata sólo de una forma de agrupar variables y reglas, consiguiendo un efecto empaquetador muy similar a los espacios de nombres.
- Comentarios en línea, al más puro estilo C++ ó C#:
// Get in line!
@var: white;
- Importación de archivos, permitiendo acceder a reglas y variables definidas en otros archivos:
@import "library"; // Si la extensión es .less, se puede omitir
@import "typo.css";
¿Y cómo funciona esto? Muy sencillo. En primer lugar, escribimos la hoja de estilos en un archivo .less, en el que podemos utilizar las características descritas anteriormente, y lo incluimos en las páginas donde nos interese, como lo hacemos siempre:
<link href="/Content/estilos.less" rel="stylesheet" type="text/css" />
Es interesante tener en cuenta que Less es compatible con CSS, lo que quiere decir que si simplemente renombramos el .css a .less, ya tendremos una hoja de partida.
A continuación, debemos introducir en el web.config una declaración que asocie la extensión .css al compilador Less:
<httpHandlers>
<add validate="false" path="*.less" verb="*"
type="dotless.Core.LessCssHttpHandler, dotless.Core" />
</httpHandlers>
Cuando llega una petición, el handler se encargará de compilar el archivo .less, generar el .css correspondiente y enviarlo minimizado al cliente, cacheando el resultado para posteriores usos, si se lo indicamos en la configuración, una sección opcional del web.config.
.Less está diseñado para ASP.NET 3.5 o superior, y por supuesto, es válido tanto para Webforms como para ASP.NET MVC. Se distribuye bajo licencia Apache 2.0, y está aún en fase beta, por lo que habrá que estar atento a la evolución de este interesantísimo proyecto.
Enlaces:
Publicado en: Variable not found.
Publicado por José M. Aguilar a las 11:07 a. m.
Etiquetas: asp.net, aspnetmvc, componentes, css, web