Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

18 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
viernes, 28 de diciembre de 2007
Imagen de la firma del contratoAunque hace varias semanas que el rumor saltó a la blogosfera, hoy han confirmado la noticia en una rueda de prensa conjunta: a partir del próximo 1 de enero Stallman formará parte de la plantilla de Microsoft en Redmond.

La nota de prensa publicada por Microsoft recoge, textualmente, los siguientes párrafos:
"Microsoft siempre apuesta por el talento, y Richard Stallman es uno de los más reputados ideólogos del mundo del desarrollo del software."
[...]
"Sin duda, se trata de una de las incorporaciones más importantes a la compañía de los últimos años, por lo que no hemos escatimado en recursos. Las negociaciones las han llevado a cabo directamente Gates y Ballmer, los dos máximos directivos, lo que demuestra la magnitud de la apuesta estratégica que se está llevando a cabo"
Por su parte, Richard Stallman, que nunca ha destacado por su aprecio a la multinacional, justifica la decisión en su blog:

"En realidad nuestras posturas nunca han estado muy alejadas, aunque veíamos las cosas desde perspectivas diferentes. Microsoft, al igual que GNU y el conjunto del movimiento Open Source, pretende hacer llegar el software a todo el mundo y hacer que sea un bien universal."
[...]
"Hay más puntos en común que diferencias, sólo era cuestión de sentarnos y dialogar sobre hacia dónde podíamos caminar juntos"

Gates y Stallman en la rueda de prensaEn principio Stallman encabezará una nueva división en Microsoft destinada al análisis y evaluación de soluciones de software libre para el segmento SOHO (Small Office, Home Office) y grandes corporaciones, así como a dirigir la adaptación de ciertos componentes del microkernel de Linux a Windows Server 2012 (codename "MindBreaker"), que se lanzará al mercado en unos años y del que ya están disponibles vía MSDN algunos whitepapers y documentos muy muy preliminares.

Este movimiento forma parte de la estrategia de acercamiento de Microsoft al mundo del software libre, como se lleva viendo algún tiempo. Los acuerdos entre Microsft y Novell, la publicación del código fuente de .NET Framework y la gran cantidad de líneas de actuación que están promoviendo así lo demuestran.

Y por cierto, se dice que el próximo en la lista de Most Wanted People de Microsoft y con el que hay conversaciones bastante avanzadas (de nuevo, pues ya las hubo hace tiempo) es Miguel de Icaza, líder del proyecto Mono, aunque él todavía no ha declarado nada al respecto. Otros en la lista son el mismísimo Linus Torvalds, creador del primer núcleo de Linux, firme candidato a liderar el área de arquitectura de servidores y servicios, y Vinton Cerf, considerado el padre de internet, para el puesto de Technical Chief Developer de la línea de productos Internet Explorer.

Habrá que esperar para ver a qué conduce esta reorientación en la estrategia que se viene observando desde hace unos meses, y sobre todo en qué se traduce la fiebre por los fichajes de figuras del mundillo. El tiempo lo dirá.

Actualización 29/12
Nota para despistados, que haberlos, haylos: obviamente la noticia no es real, se trata de una broma del día de los inocentes.
Por cierto, hay muchos comentarios simpáticos en mi blog en geeks.ms.


Publicado en: www.variablenotfound.com.
lunes, 24 de diciembre de 2007
Árbol de NavidadPara conocer si un equipo remoto tiene un puerto abierto existen multitud de técnicas. Hace tiempo describí una muy potente llamada idle scan y hoy, haciendo honor a la fecha en que nos encontramos, describiremos el escaneo "Xmas Tree" (árbol de navidad).

Esta técnica consiste en enviar un segmento TCP al puerto deseado del dispositivo a investigar con los bits FIN, URG y PUSH activos. Esto hace que el byte de flags contenga "00101001", lo cual parece ser que recuerda a las luces de un árbol de navidad, y de ahí su nombre. Imaginación y espíritu navideño que no falte. ;-)

Cuando la víctima del escano recibe este segmento, según dictan las directrices marcadas por el protocolo,

  • si el puerto está cerrado, devuelve un segmento con el bit RST activo, indicando que se resetee la conexión en cliente.
  • si el puerto está abierto, ignora el paquete recibido y no responde nada.
Atendiendo a la respuesta (o ausencia de ella), el atacante puede determinar el estado del puerto que está investigando de una forma realmente silenciosa, puesto que no inicia ninguna conexión (como los sondeos SYN, que inician un 3-way-handshake), y sorteando a veces filtros que no esperan este tipo de combinaciones en los flags.

Sin embargo, como aspectos negativos, podemos decir que es bastante sencillo de filtrar y detectar, y que ponen al descubierto la dirección del atacante, por lo cual es conveniente realizarlos desde zombies o intermediarios. También es complicado determinar la veracidad del resultado, puesto que:

  • la respuesta puede ser la misma (o sea, ninguna) si un puerto está abierto o si el paquete ha sido interceptado por un elemento de seguridad (como un firewall).
  • también un puerto puede parecer cerrado sin estarlo debido a una interpretación errónea de la RFC.
En cualquier caso, podemos realizarlo de forma muy sencilla utilizando la herramienta nmap (si usas alguna distribución de linux basada en Debian, como Ubuntu, puedes descargar e instalarla haciendo un apt-get install nmap.). El escaneo lo realizaríamos con la orden (siendo w.x.y.z la dirección IP de la víctima):
nmap -sX w.x.y.z

Ah, por cierto, ¡feliz navidad!

Publicado en: http://www.variablenotfound.com/.
miércoles, 19 de diciembre de 2007
Hace unos días me topé con los Diez Mandamientos del Abogado, el célebre decálogo formulado por el jurista uruguayo Eduardo J. Couture, donde se recogen una serie de normas éticas y de conducta que deberían guiar las acciones de estos profesionales.

Me llamó la atención porque muchas de estas líneas son totalmente aplicables a otros ámbitos y colectivos, y por supuesto al mundo del desarrollo de software, dado que contiene perlas como: "Estudia, puesto que el Derecho evoluciona constantemente", o "Piensa, puesto que el Derecho se aprende estudiando pero se ejerce pensando".

Sin embargo, el que me hizo reflexionar fue el décimo:

10. AMA TU PROFESION. Trata de considerar la abogacía de tal manera, que el día en que tu hijo te pida consejo sobre su destino, consideres un honor para ti proponerle que se haga abogado.

Y es que la pregunta es: ¿estamos tan satisfechos de nuestra profesión como para aconsejar a un hijo, al que se supone que debemos desearle lo mejor del mundo, dedicarse a ella?

No son pocos los profesionales del desarrollo de software que, bien por circunstancias laborales, personales, falta de vocación u otros motivos, reniegan continuamente, y a veces no sin razón, de este mundillo. Y es que con mucha frecuencia se trata de un trabajo mal pagado, muy duro, con horarios imposibles, estrés continuo, necesidad de actualización de conocimientos frecuente, y escaso reconocimiento social.

Así está el patio como está. Cada vez más gente que huye dando el salto a otras profesiones, las matrículas en informática por los suelos, los ingenieros en continua protesta (;-)) ... en fin, un panorama nada alentador para el futuro.

A pesar de esto, yo soy de los que estarían encantados de que alguno de mis hijos (hijas, en este caso) se dedicara al mundo del desarrollo de software, siempre, eso sí, que consiguieran apasionarse por ello. Nunca se la recomendaría como una salida profesional más, pues creo que al igual que es una dedicación fascinante para el que le gusta, estoy seguro de que debe ser una auténtica pesadilla para el que no disfrute creando software.

Probablemente dedicándose a esto no conseguirán nunca hacerse ricas, ni famosas, ni llegar todos los días pronto a casa... pero bueno, tampoco siendo médicos, ni abogados, ni taxistas. Y, en cambio, tendrían por delante una profesión (y muchas veces hobby) donde volcar toda su creatividad y talento, la satisfacción de la investigación y aprendizaje continuos, de crear software que ayuden a otros a trabajar, estudiar o pasar buenos ratos de ocio... en fin, un universo de posibilidades.

¿Y tú, recomendarías a tu hijo que se dedicara al mundo del desarrollo?

Publicado en: www.variablenotfound.com
martes, 18 de diciembre de 2007
Hace unos días Rosario C. realizaba, a través de un comentario en el post "Llamar a métodos estáticos con ASP.Net Ajax", una consulta sobre un problema con el se había topado al intentar retornar DataSets desde un método de página (PageMethod) de ASP.Net Ajax, un tema tan interesante que vale la pena escribir un post en exclusiva.

Recordemos que los métodos estáticos de página son una interesante capacidad que nos ofrece este framework para poder invocar desde cliente (javascript) funciones de servidor (codebehind) de una forma realmente sencilla. Además, gracias a los mecanismos de seriación incluidos, y como ya vimos en el post "Usando ASP.NET AJAX para el intercambio de entidades de datos", es perfectamente posible devolver desde servidor entidades o estructuras de datos complejas, y obtenerlas y procesarlas directamente desde cliente utilizando javascript, y viceversa.

Es es ahí donde reside el problema con los DataSets: precisamente este tipo de datos no está soportado directamente por el seriador JSON incorporado, que es el utilizado por defecto, de ahí que se genere una excepción como la que sigue:

System.InvalidOperationException
A circular reference was detected while serializing an object of type 'System.Globalization.CultureInfo'.
en System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat serializationFormat)\r\n en System.Web.Script.Serialization.JavaScriptSerializer.SerializeValue(Object o, StringBuilder sb, Int32 depth, Hashtable objectsInUse, SerializationFormat [...]

Pero antes de nada, un inciso. Dado que la excepción se produce en el momento de la seriación, justo antes de enviar los datos de vuelta al cliente, debe ser capturada en cliente vía la función callback especificada como último parámetro en la llamada al método del servidor:

// Llamada a nuestro PageMethod
PageMethods.GetData(param, OnOK, OnError);
[...]


function OnError(msg)
{
// msg es de la clase WebServiceError.
alert("Error: " + msg.get_message());
}
 
Aclarado esto, continuamos con el tema. La buena noticia es que el soporte para DataSets estará incluido en futuras versiones de la plataforma. De hecho, es perfectamente posible utilizar las librerías disponibles en previews disponibles en la actualidad. Existen multitud de ejemplos en la red sobre cómo es posible realizar esto, aunque será necesario instalar alguna CTP y referenciar librerías en el Web.config. Podéis echar un vistazo a lo descrito en este foro.

Esta solución sin embargo no es muy recomendable en estos momentos, puesto que estaríamos introduciendo en un proyecto librerías y componentes que, en primer lugar, están ideados sólo para probar y tomar contacto con las nuevas tecnologías, y, en segundo lugar, las características presentadas en ellos pueden modificarse o incluso eliminarse de las futuras versiones.

Existen otras formas de hacerlo, como la descrita en siderite, que consiste en crear un conversor justo a la medida de nuestras necesidades extendiendo la clase JavaScriptConverter, aunque aún me parecía una salida demasiado compleja al problema.

Sin embargo, la solución que he visto más simple es utilizar XML para la seriación de estas entidades, lo que se puede lograr de una forma muy sencilla añadiendo al método a utilizar un atributo modificando el formato de respuesta utilizado por defecto, de JSON a XML.

He creado un proyecto de demostración para VS2005, esta vez en VB.NET aunque la traducción a C# es directa, con una página llamada DataSetPageMethods.aspx en el que se establece un PageMethod en el lado del servidor, con la siguiente signatura:

<WebMethod()> _
<Script.Services.ScriptMethod(ResponseFormat:=ResponseFormat.Xml)> _
Public Shared Function ObtenerClientes(ByVal ciudad As String) As DataSet
 
Este método estático obtendrá de la tradicional base de datos NorthWind (en italiano, eso sí, no tenía otra a mano O:-)) un DataSet con los clientes asociados a la ciudad cuyo nombre se recibe como parámetro.

Como podréis observar, el método está precedido por la declaración de dos atributos. El primero de ellos, WebMethod(), lo define como un PageMethod y lo hará visible desde cliente de forma directa. El segundo de ellos redefine su mecanismo de seriación por defecto, pasándolo a XML. Si queréis ver el error al que hacía referencia al principio, podéis modificar el valor del ResponseFormat a JSON, su valor por defecto.

Desde cliente, al cargar la página rellenamos un desplegable con las distintas ciudades. Cuando el usuario selecciona un elemento y pulsa el botón "¡Pulsa!", se realizará una llamada asíncrona al PageMethod, según el código:

function llamar()
{
PageMethods.ObtenerClientes($get("<%= DropDownList1.ClientID %>").value , OnOK, OnError);
}
 
La función callback de notificación de finalización de la operación, OnOk, recibirá el DataSet del servidor y mostrará en la página dos resúmenes de los datos obtenidos que describiré a continuación. He querido hacerlo así para demostrar dos posibles alternativas a la hora de procesar desde cliente los datos recibidos, el DataSet, desde servidor.

En el primer ejemplo, se crea en cliente una lista sin orden con los nombres de las personas de contacto de los clientes (valga la redundancia ;-)), donde muestro cómo es posible utilizar el DOM para realizar recorridos sobre el conjunto de datos:

var nds = data.documentElement.getElementsByTagName("NewDataSet");
var rows = nds[0].getElementsByTagName("Table");
var st = rows.length + " filas. Personas:  br />";
st += "<ul>";
for(var i = 0; i < rows.length; i++)
{
st += "<li>" + getText(rows[i].getElementsByTagName("Contatto")[0])+ "</li>";
}
st += "</ul>";
etiqueta.innerHTML = st;
 
En el segundo ejemplo se muestra otra posibilidad, la utilización de DOM para crear una función recursiva que recorra en profundidad la estructura XML mostrando la información contenida. La función javascript que realiza esta tarea se llama procesaXml.

Como se puede comprobar analizando el código, utilizar la información del DataSet en cliente es necesario, en cualquier caso, un conocimiento de la estructura interna de est tipo de datos, lo cual no es sencillo, por lo que recomendaría enviar y gestionar los DataSets en cliente sólo cuando no haya más remedio.

Una alternativa que además de resultar menos pesada en términos de ancho de banda y proceso requerido para su tratamiento es bastante más sencilla de implementar sería enviar a cliente la información incluida un un array, donde cada elemento sería del tipo de datos apropiado (por ejemplo, un array de Personas, Facturas, o lo que sea). La seriación será JSON, mucho más optimizada, además de resultar simplísimo su tratamiento en javascript.

El proyecto de demostración también incluye una página (ArrayPageMethods.aspx) donde está implementado un método que devuelve un array del tipo Datos, cuya representación se lleva también a cliente y hace muy sencillo su uso, como se puede observar en esta versión de la función de retorno OnOk:

function OnOK(datos)
{
var etiqueta = $get("lblMensajes");
var s = "<ul>";
for (var i = 0; i < datos.length; i++)
{
s += "<li>" + datos[i].Contacto;
s += ". Tel: " + datos[i].Telefono;
s += "</li>";
}
s += "</ul>";
etiqueta.innerHTML = s;
}
 

Por último, comentar que el proyecto de ejemplo funciona también con VS2008 (Web Developer Express), aunque hay que abrirlo como una web existente.

Publicado en: www.variablenotfound.com.


Enlace: Descargar proyecto VS2005.
martes, 11 de diciembre de 2007
He encontrado un post muy interesante sobre hábitos comunes en personas altamente innovadoras y creativas, extraídos del libro de Scott Berkun, "The myths of innovation", que me permito interpretar y recoger a continuación.

1. Trabajar duro

La innovación implica algo más que tener grandes ideas. Hay que tener fe, trabajar duro y luchar en contra de la marea para conseguir nuestros objetivos. Como dijo Thomas Alba Edison:
"La invención es un 1% de inspiración y un 99% de transpiración"

2. Evitar inhibiciones

Estas inhibiciones nos hacen sentirnos limitados y bloqueados, necesitamos abrir la mente eliminando asunciones y restricciones, abrirnos a nuevas ideas y soluciones sin limitaciones mentales de ningún tipo. La innovación tiene más que ver con la psicología que con el intelecto.

3. Asumir riesgos, cometer errores

El miedo al fracaso es uno de los causantes de que fabriquemos nuestras propias limitaciones. Está claro que algunas ideas fallarán durante el aprendizaje, por lo que es conveniente construir prototipos frecuentemente, probarlos, someterlos a discusión, usar el feedback y realizar cambios de forma incremental.

En lugar de tratar los errores como fracasos, es conveniente pensar en ellos como experimentos. En palabras de Scott Berkun,
"Los experimentos son los errores previstos para aprender algo deliberadamente"
Así, no debemos flagelarnos con los fallos, aceptémoslos y utilicemos la lección aprendida para encontrar nuevas y mejores soluciones. Los errores forman parte del camino hacia el éxito, positivémoslos; como decía Edison,
"No me he equivocado. Simplemente he encontrado 10.000 soluciones que no funcionaban"

4. Escapar

Cuando más relajados estamos internamente, más receptivos somos respecto a nuestra creatividad. Este es el motivo por el que frecuentemente tenemos grandes ideas en el cuarto de baño, en la cama o estando solos.

Cada uno de nosotros contacta con "su lado más creativo" de una forma diferente, sólo es cuestión de averiguar cómo. Los hay que caminan, que hacen footing, otros escuchan música... ¿cuál es tu método?

5. Anotar las ideas

Muchos creativos y personas innovadoras tienen siempre a mano algo donde apuntar ideas y pensamientos: libretas, post-it, papel, o algo más tecnológico. Da igual el soporte, lo importante es disponer de una forma de capturar sus pensamientos, pensar sobre el papel, romper con las inhibiciones y comenzar el proceso creativo.

El famoso manuscrito de Leonardo Da Vinci fue comprado por Bill Gates por más de 30 millones de dólares.

6. Encontrar patrones y combinarlos

Las ideas aparecen partiendo de otras ideas. Por ejemplo, Edison no fue el inventor de las bombillas, pero hizo que pudieran durar más tiempo creando un filamento de carbono e introduciéndolo en el interior de un cristal.

Ábrete a nuevas ideas, estúdialas y piensa en combinarlas para mejorar soluciones existentes.

7. Ser curioso

Muchos innovadores son simplemente personas curiosas a los que les gusta resolver problemas. Es una buena costumbre observar soluciones existentes y preguntarse si hay otras vías para hacerlo, cuestionarse las normas y métodos existentes.

Publicado en: Variable Not Found.
lunes, 10 de diciembre de 2007
Hasta la versión 3.0 de C#, la declaración de una variable se debía realizar indicando su tipo de datos antes del identificador elegido para la misma. También era muy frecuente definir en ese mismo momento su valor inicial, siguiendo un patrón similar al siguiente:
  string s = "cadena";
Sin embargo, la declaración anterior es redundante. Si la constante "cadena" es un string, ¿por qué hace falta indicar que la variable s también lo es?

Las variables locales implícitamente tipadas permiten obviar en su declaración el tipo que tendrán, dejando al compilador la tarea de averiguar cuál será en función de las variables o constantes que se usen al inicializarlo. Por tanto, será posible escribir código como:
  var x = XmlDateTimeSerializationMode.Local;
Y será equivalente a:

XmlDateTimeSerializationMode x = XmlDateTimeSerializationMode.Local;
 
Creo que no hace falta decir cuál de ellas es más cómoda a la hora de programar, ¿no? Simplemente hemos indicado con la palabra var que preferimos que sea el compilador el que haga el trabajo sucio.

Otro contexto donde este tipo de variables pueden facilitarnos la vida de forma frecuente es en los bucles for, foreach y bloques using:
  // Un ejemplo de bucle...
var chars = "Saludicos".ToCharArray();
foreach (var ch in chars)
{
Console.Write(ch); // ch es char
}

// Y ahora un bloque using...
using (var ctx = new AppContext())
{
// usamos ctx, que es de tipo AppContext
}
 
También es importante la existencia de esta nueva forma de declaración para posibilitar la creación de objetos de tipo anónimo, es decir, aquellos cuya especificación de clase se crea en el mismo momento de su definición. Por tanto, una declaración como la siguiente será válida:
  var x = new { Nombre = "Juan", Edad = 23 };
Para no desviarme del objetivo de este post, otro día hablaremos más detenidamente de las clases anónimas, aunque adelantaré que una vez compilado el código anterior el resultado será algo parecido al siguiente:

class __Anonymous1
{
private string nombre ;
private int edad ;
public string Nombre { get { return nombre ; } }
public int Edad { get { return edad ; } }
public __Anonymous1(string nombre, int edad)
{
this.nombre = nombre;
this.edad = edad;
}
}
...
__Anonymous1 x = new __Anonymous1("Juan", 23);

 
Existen ciertas reglas de obligado cumplimiento para usar variables locales implícitamente tipadas:
  • La declaración debe incluir un valor de inicialización. En otras palabras, no será posible usar en una línea var i;, puesto que el compilador no podría inferir el tipo en este momento.
  • El valor de inicialización debe ser una expresión evaluable como clase en tiempo de compilación. Expresamente prohibido el valor null, es decir, nada de var n = null;, puesto que el compilador no sabría de qué tipo se trata; eso sí, si fuera necesario, podría forzarse un casting var str = null as string;.
  • La declaración no puede incluir más de una variable. Una línea como var i = 1, s = "hola"; generará un error en compilación.
  • El inicializador no puede referirse a la propia variable declarada, obviamente.
  • Sólo pueden utilizarse como variables locales en bloques de código, en bucles for y foreach y como recurso de un bloque using.

Por último, me gustaría añadir un par de detalles que considero interesantes.

Seguimos teniendo Intellisense...Primero, el hecho de utilizar la palabra "var" y no indicar de forma explícita el tipo puede hacernos pensar que estamos utilizando tipado dinámico en tiempo de ejecución, como lo hacemos con Javascript, sin embargo esto no es así. Como he comentado anteriormente, el compilador toma el tipo del lado derecho de la asignación de inicialización, por lo que si la variable no es inicializada se produce un error de compilación:
Implicitly-typed local variables must be initialized
(Las variables locales implícitamente tipadas deben ser inicializadas)
Por ello, un entorno como Visual Studio sabe en todo momento el tipo exacto de que se trata, y nos puede ofrecer las ayudas en la codificación, detección de errores sintáticos e intellisense, como se puede observar en la imagen.

Segundo, y muy interesante. Como ya comenté en su momento, la nueva versión de Visual Studio permite la generación de ensamblados para versiones anteriores de la plataforma, es decir, que es posible escribir código C# 3.0 y generar un ensamblado para el framework 2.0. Esto, a efectos prácticos, implica que una vez demos el salto definitivo a VS2008 podremos usar las variables locales de tipo implícito, así como otras novedades del lenguaje, incluso en aplicaciones diseñadas para .NET 2.0.



Publicado en: Variable Not Found.