Category Archives: .Net (C#)

ASP.Net MVC Razor, la evolución desde apsx webforms hacia MVC y fundamentos básicos de ASP.Net MVC

aspnetQuienes hayan trabajado alguna vez con .Net, conocerán el sistema de plantillas de ASP.Net llamado webforms. Los webforms fueron un sistema de vistas con extensión aspx que podían ir o no acompañadas de un codebehind y controles. El objetivo de Microsoft cuando diseño esta parte del framework de .Net fue mover a los desarrolladores a crear aplicaciones en nube, que aunque ahora este tan de moda el termino nube, estamos en un contexto del año 2000. Los webforms permitían desarrollar una web, tal y como los desarrolladores del viejo Visual Basic hacían sus aplicaciones de escritorio, donde las páginas eran llamadas formularios (de ahí el término webform) y los elementos tales como inputs, botones, etc, se arrastraban con un editor wysiwyg. Los antiguos webforms, aunque simulaban un entorno de escritorio, en cuanto a formularios, no eran otra cosa que webs y como tales podías tocar el html desde el editor y no solo tener la opción de editor wysiwyg, encontrando bajo el capo una web de código espagueti tal y como siempre se habló de php por ejemplo, salvo que parte de la lógica estaba en el codebehind. Esta última parte era lo peor de todo, puesto que si el desarrollador era experto, el código espagueti era minúsculo, pero a medida que descendía la pericia del programador, aumentaba el tamaño tanto del codebehind como del propio espagueti html que era ese aspx webform.

Microsoft publico todo esto en las primeras versiones del .Net framework y fue un bombazo, cualquiera podía hacer una web con muchos formularios en un tris, pero claro, ahí esta está el cliente para recordarnos que era muy feo y que lo querían mas bonito como habían visto por internet otras páginas. Es entonces cuando empiezan a verse los primeros problemas a la hora de realizar webs y es que aspnet 1 no tenia soporte para páginas maestras, por lo que los desarrolladores acababan en practicas comunes en otros lenguajes y que eran tan criticadas como copiar y pegar la misma estructura de página (controles, cabecera, menu, pie, etc) por todas y cada una de las páginas que tuviéramos en nuestro proyecto. Así que como novedad, Microsoft pensó que aparte de cambiar la forma de incluir los controles en una web, automatizando todo el proceso, penso que era hora de crear un concepto mas que necesario, una masterpage. Una masterpage, no es mas que como su nombre indica, una página maestra, digamos que todo ese contexto de cabeceras, menu, pie, etc que ibamos copiando de página a página pero que ahora se centraliza en un sitio, marcando en esa página maestra, donde queremos que se renderice el contenido de la página. Esto supuso un gran avance, ya que las páginas desarrolladas con ASP.Net, fueron mejorando en el punto que eran mas limpias. Aun y con todo, seguian los problemas, el auge de librerías de javascript dinámicas, con efectos y llamadas de ajax, dejaba en ridículo a controles muy cerrados tipo updatepanels y los desarrolladores pedían a gritos mas flexibilidad.

Cuando uno ha vivido toda la vida amamantado por la teta de Microsoft, no se percata de cierta rigidez a la hora de desarrollar una web con ASP.Net, pero quien tocara cualquier otro entorno, veia como en php y python, aparecian framework MVC, que permitian utilizar todas esas librerias de ajax pero sin montar un pipote (caos) de código para que funcionen bien. Es entonces cuando aparece MVC. El concepto de MVC es un concepto creado en 1979, no trae ninguna novedad como tal, pero si que introduce ese concepto en ASP.Net teniendo una serie de caracteristicas fundamentales (en un sistema normal sin mucha floritura):

  • Los controladores son siempre los que reciben las peticiones, ya no hay controladores genéricos ashx, servicios asmx, paginas aspx, controles ascx, ni masterpages master. Los controles son clases donde por defecto, sus métodos serán aciones del controlador.
  • Las vistas son solo eso, vistas, con sintaxis webform en MVC 1 y 2 y con Razor en MVC 3 y 4.
  • Los modelos son clases con propiedades multifunción, validar automáticamente datos, enviar y recibir formularios, sincronizar datos con la base de datos (Entity Framework Code First).
  • El proyecto es un binario cerrado, como ocurría en la primera versión de ASP.Net y en el resto si lo cambiabas a proposito, ya no hay mas código abierto con el que dejar a IIS que compile el código, como si fuera php.

Hasta aquí, una breve explicación de como surge MVC, pero ¿Y Razor? Razor es el nuevo sistema de templates de ASP.Net MVC. Quien haya programado con webforms, se habrá dado cuenta que en una página con un poco de lógica, acaba creciendo mucho y complicando la sintaxis con abre código <%, mete código, cierra código %>, haciendo que no solo crezca una página, sino que además, el código se vuelve mas y mas feo por momentos. Razor soluciona esto con 2 procedimientos, el primero es su cierre automático inteligente, es decir, la etiqueta de apertura será una arroba @, pero no tendrá cierre como tal. La segunda peculiaridad es que el código es mucho mas fluido puesto que se aprovecha del propio html para formar ciertas partes de la sintaxis. Ademas, Razor tiene algunas ventajas como son poder indicar un modelo que utiliza la página para hacer validaciones, formularios y pintar datos de una forma mas sencilla.

Veamos un par de ejemplos de código hecho con Razor frente al hecho con webform:

@model Indacalsa.Models.LoginModel

@using (Html.BeginForm("Login", "Account", FormMethod.Post)) {
  @Html.AntiForgeryToken()
  <fieldset id="login">
    <legend>Datos de acceso @ViewBag.Title</legend>
    <p>
      <label>
        <span class="title">Usuario:</span>
        @Html.TextBoxFor(m => m.UserName)
        @Html.ValidationMessageFor(m => m.UserName)
      </label>
    </p>
    <p class="center">
        <input type="submit" value="Acceder" class="btn" />
    </p>
  </fieldset>
}
<form method="post" action="/Login/Account.aspx" runat="server">
  <fieldset id="login">
    <legend>Datos de acceso <%=this.Title%></legend>
    <p>
      <label>
        <span class="title">Usuario:</span>
        <asp:TextBox name="UserName" id="UserName" runat="server" />
        <asp:RegularExpressionValidator ID="validatorUserName" runat="server" ControlToValidate="UserName" ErrorMessage="La longitud mínima es de 5 caracteres" ValidationExpression=".{5}.*" />
      </label>
    </p>
    <p class="center">
        <asp:Button value="Acceder" class="btn" runat="server" />
    </p>
  </fieldset>
</form>

Lo he simplificado, primero en Razor y luego en ASP.Net webforms. La parte de webforms la he simplificado sin utilizar el tipico form que ocupa toda la página y sin mucha historia, para dar un acercamiento de como va el tema. Aparte de este ejemplo hay que sacar la mala experiencia de utilizar controles de webform y sus ids mágicos, si es que luego queremos dinamizar la página con ajax o javascript.

Y para los que vengan de atras, aquí van algunas similitudes entre webform y Razor:

  • Las masterpage de webform ahora son llamadas Layouts
  • Los controles de webform ahora son vistas parciales, pero con la salvedad de que no tendrán codebehind.
  • Para especificar código espagueti o en linea en webforms se hace con <% codigo %> y <%=codigo%>. Con Razor se hace con @micodigo o @(micodigo_muy_complejo).
  • Para ir renderizando texto dentro del código de Razor ya no es necesario abrir y cerrar las etiquetas de codigo <% y %>, sino que podemos usar <text>texto a renderizar</text>
  • Los asp:content de las masterpages ahora son sections.

Espero que os guste y os sirva un poco a aquellos rehacios a migrar a MVC o desde otros lenguajes.

ASP.Net y los errores de “La operación no es válida debido al estado actual del objeto” y como solucionarlo con MaxHttpCollectionKeys

A veces en ASP.Net, se da el caso de que una página tiene un formulario inmenso, cuando por ejemplo queremos mandar un modelo gigantesco. Aunque de darse este caso, deberiamos plantearnos si no debemos cambiar nuestro código, puede que si lo ejecutamos nos de un error indicando "La operación no es válida debido al estado actual del objeto" o en ingles "Operation is not valid due to the current state of the object". Esto pasa porque hemos sobrepasado el límite máximo de parámetros que se pueden enviar.

La solución es bien sencilla, solo debemos modificar nuestro web.config para que admita mas parámetros

<configuration>
  <appSettings>
    <add key="aspnet:MaxHttpCollectionKeys" value="5000" />
  </appSettings>
</configuration>

Añadiendo la key MaxHttpCollectionKeys y aumentandola hasta 5000, el problema se soluciona.

Ordenar los bundles de ASP.Net MVC

Si alguna vez habeis intentado hacer un gran proyecto con ASP.Net MVC, vereis que utilizar los bundles para incluir el código tanto javascript (ScriptBundle) como css (StyleBundle) en nuestra página es muy útil ya que nos ofrece diferentes formas de tratar los archivos a incluir, uno de mis favoritos es unificar todo el bundle compilado y minimizado. Todo parece un camino de rosas, poder agrupar todos nuestros css y javascript en una sola linea incluyendo archivos o directorios.

No todo es maravilloso y aunque Microsoft suele hacer las cosas bastante bien, siempre se deja algún extraño por el camino. En este caso el extraño es el orden en que se cargan los archivos en la página usando Bundles. Cuando tenemos multitud de archivos javascript o css por ejemplo, se da el caso en que no todos los archivos se cargan en el orden en que lo incluimos. No se si tiene algo que ver mezclar inclusiones por archivos y directorios a la vez, pero no mantiene el orden igual. Es una locura, puesto que aparentemente todo sigue un orden, pero cuando tenemos una docena de archivos javascript o css, a veces hay alguno que se descoloca. A mi me pasó con backbone y underscore, que como sabreis quien haya trabajado con estas librerias, backbone requiere de underscore y si no esta incluido previamente provoca un error.

Lo primero que tenemos que hacer es crear una nueva clase para hacer el IBundleOrderer.OrderFiles que ordene los bundles, en nuestro caso, realmente no queremos que ordene sino que los muestre en el orden en que los escribimos. La clase en cuestión sería:

public class UserDefinedBundleOrderer : IBundleOrderer {
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) {
        return files;
    }
}

Una vez tengamos nuestra clase IBundleOrderer, solo deberemos indicar a nuestro bundle, bien sea un ScriptBundle, un StyleBundle o un Bundle genérico, que utilice como Orderer nuestra clase que se encarga de la "ordenación" o en este caso, dejar las cosas como están. Lo haremos con el Bundle.Orderer como se muestra en el ejemplo:

myBundle.Orderer = new UserDefinedBundleOrderer();

Y ahora os dejo un ejemplo real sacado directamente de un proyecto propio. Así quedaría todo el archivo completo. Podemos ver como el BundleConfig donde definimos la carga de Bundles, tenemos un StyleBundle que cargará nuestros css, mientras que el ScriptBundle cargará nuestras librerías javascript y es a esta clase donde aplicamos nuestra clase para la ordenación de Bundles.

using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Optimization;

namespace MyWeb {
  public class BundleConfig {
    public static void RegisterBundles(BundleCollection bundles) {
      BundleTable.EnableOptimizations = true;

      bundles.Add(new StyleBundle("~/assets/css").Include(
        "~/Content/css/dark-hive/jquery-ui.css",
        "~/Content/css/bootstrap.css",
        "~/Content/css/site.css"
      ));

      ScriptBundle libs = new ScriptBundle("~/assets/libs");
      libs.Orderer = new UserDefinedBundleOrderer();
      libs.Include(
        "~/Scripts/libs/jquery-1.8.2.js",
        "~/Scripts/libs/jquery-ui-1.8.24.js",
        "~/Scripts/libs/jquery-ui.datepicker.es.js", 
        "~/Scripts/libs/underscore-1.4.1.js",
        "~/Scripts/libs/backbone-0.9.2.js",

      bundles.Add(libs);
    }
  }

  public class UserDefinedBundleOrderer : IBundleOrderer {
    public virtual IEnumerable<FileInfo> OrderFiles(BundleContext context, IEnumerable<FileInfo> files) {
      return files;
    }
  }
}

Espero que os sirva de ayuda.

Microsoft prefiere GIT, codeplex y la influencia de github

CodeplexCodeplex, la famosa web de forge de Microsoft me sorprende cada día mas. Aunque Codeplex no me gusta tanto como Github, es cierto que da muy buena salida a los proyectos realizados en .Net, por lo que aunque en mis proyectos open source utilizo Github, tengo los repositorios clonados en Codeplex. Microsoft cada día me sorprende mas, si ya me sonreía al entrar en la pagina de asp.net y encontrar que muchos proyectos que Microsoft recomienda, muchos de ellos eran en PHP. Ahora Microsoft vuelve a sorprender, esta vez con Codeplex, donde originalmente se ofrecían servicios de control de código fuente por Team Foundation, poco a poco han ido ampliando la variedad de servicios, añadiendo SVN, Mercurial y poco después GIT.

Si navegamos entre los diferentes repositorios de Codeplex, podremos encontrar el de ASP.Net MVC, que curiosamente, no está en Team Foundation, ni SVN, no no, esta en GIT y solo GIT. Curioso ver esta jugada de Microsoft, ¿Será que los propios ingenieros prefieren usar la potencia de GIT en lugar de sus propias herramientas? Para el interesado que quiera verlo, puede entrar en la web del proyecto de ASP.Net MVC en Codeplex.

Deploy de ASP.Net MVC en Apache con mod_mono

Lo que voy a escribir aquí no es una guía de como instalar Mono ASP.Net con MVC sobre apache con mod_mono, aunque la escribiré, sino como hacer el deploy de una aplicación. Cuando montamos un sistema Mono ASP.Net con MVC sobre apache con mod_mono, hay que tener 3 cosas en cuenta para su correcto funcionamiento, son pequeños detalles pero que te pueden dar algún que otro quebradero de cabeza. Las 3 cosas a tener en cuenta son:

  • Apache no entiende que tu app es MVC, por lo que hay que decirselo.
  • Apache ni mod_mono son capaces de dictaminar tu index
  • Siempre hay que tener algo para recompilar el backend en caso de cacheo o fallo (generalmente cuando desarrollamos).

Bueno, expliquemos cada una, en primer lugar apache no sabe que tu app es un MVC de ASP.Net, por lo que cuando hagamos un deploy o creemos un proyecto nuevo de Mono ASP.Net con MVC, lo primero a crear es un .htaccess forzando a que es un MVC. El código del htaccess es:

ForceType application/x-asp-net

Con esto ya  podemos poner a funcionar nuestra aplicación web. El siguiente paso para hacer las cosas bien, sería crear un index, ¿Por qué? ¿Acaso no saben cual es mi index? Pues no, todas las pruebas, tanto en Linux como en Mac OS X, es que mod_mono no es capaz de entender cual es el index que definimos en el global.asax, por lo que lo mejor es crear un index.aspx que cargue nuestro HomeController, o el que queramos. El index estaría en el raiz del proyecto y su código sería:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<%
   this.Context.RewritePath("Home", false);

   IHttpHandler httpHandler = new MvcHttpHandler();
   httpHandler.ProcessRequest(this.Context);
%>

Lo que hacemos con este index.aspx es decirle que cuando cargue la home (el index) cargue automáticamente el HomeController. Ahora solo nos falta crear un sistema de reseteo de backend por si se queda en cache y queremos cambiar algo. Para ello creamos una carpeta, por ejemplo, reset-mono-backend y creamos un .htaccess dentro de esa carpeta. Cabe decir que al htaccess lo podemos otorgar de un sistema de autentificación y cosas por el estilo para acceder, pero como esto es un ejemplo, será lo más básico. El contenido del .htaccess será:

ForceType None
SetHandler mono-ctrl

Al entrar en /nuestroproyecto/reset-mono-backend, nos aparecerá una interfaz que nos permitirá entre otras cosas, resetear el backend. Otro día explicaré como se instala el sistema en si.

Habilitar sesiones en un handler.ashx con IRequiresSessionState e IReadOnlySessionState

En .Net, bien sea en C# o en VB.Net, hay un tipo de clases llamadas controladores genéricos que nos proveen de un nivel muy básico de controlador web. En ASP.Net, los handlers o  HttpHandler son un tipo de clases tan básicas, que no implementan entre otras cosas, las sesiones, por lo que tendremos que indicar explícitamente en la clase que tipo de sesión vamos a implementar.

Me voy a centrar en explicar 3 casos que son los más comunes, a la hora de implementar un handler:

  • Sin sesión: para esto no hay que hacer nada, con la declaración por defecto nos es suficiente. No tendremos acceso a la sesión, que sera nula si hacemos un context.Session
  • Sesión de solo lectura: para esto debemos implementar la interfaz IReadOnlySessionState, de tal modo que al hacer context.Session, tenga los valores de la sesión, pero no podremos añadir o actualizar datos sobre la sesión.
  • Sesión de lectura y escritura: para esto debemos implementar la interfaz IRequiresSessionState, que nos permitirá acceder a los datos de la sesión, así como añadir y actualizar los datos.
A continuación dejo unos ejemplos en C# y en VB.Net para que os hagais una idea.
[sourcecode language="csharp" title="Ejemplo de implementación de handlers en C#"] //Este ejemplo devolverá un error ya que context.Session es Nothing
public class IndalcasaSessionHandler : System.Web.IHttpHandler {
public void ProcessRequest(HttpContext context) {
Object value;

context.Session.Add("value", "un valor");
value = context.Session.Item("value");

context.Response.Write(value);
}
}

//Este ejemplo no devolverá un error ya que context.Session no es Nothing
//pero value tendrá el valor original que tuviera y no el valor "nuevo valor"
//ya que no se puede escribir en la sesión
public class IndalcasaSessionHandler : System.Web.IHttpHandler, System.Web.SessionState.IReadOnlySessionState {
public void ProcessRequest(HttpContext context) {
Object value;

context.Session.Add("value", "un valor");
value = context.Session.Item("value");

context.Response.Write(value);
}
}

//Este ejemplo no devolverá un error ya que context.Session no es Nothing
//y actualizará el valor de la sesión correctamente
public class IndalcasaSessionHandler : System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState {
public void ProcessRequest(HttpContext context) {
Object value;

context.Session.Add("value", "un valor");
value = context.Session.Item("value");

context.Response.Write(value);
}
}
[/sourcecode] [sourcecode language="vb" title="Ejemplo de implementación de handlers en VB.Net"] 'Este ejemplo devolverá un error ya que context.Session es Nothing
Public Class IndalcasaSessionHandler
Implements System.Web.IHttpHandler

Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim value As Object

context.Session.Add("value", "un valor")
value = context.Session.Item("value")

context.Response.Write(value)
End Sub
End Class

'Este ejemplo no devolverá un error ya que context.Session no es Nothing
'pero value tendrá el valor original que tuviera y no el valor "nuevo valor"
'ya que no se puede escribir en la sesión
Public Class IndalcasaSessionHandler
Implements System.Web.IHttpHandler, System.Web.SessionState.IReadOnlySessionState

Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim value As Object

context.Session.Add("value", "nuevo valor")
value = context.Session.Item("value")

context.Response.Write(value)
End Sub
End Class

'Este ejemplo no devolverá un error ya que context.Session no es Nothing
'y actualizará el valor de la sesión correctamente
Public Class IndalcasaSessionHandler
Implements System.Web.IHttpHandler, System.Web.SessionState.IRequiresSessionState

Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim value As Object

context.Session.Add("value", "nuevo valor")
value = context.Session.Item("value")

context.Response.Write(value)
End Sub
End Class
[/sourcecode]

Espero que os saque de un apuro en el que alguna vez me he visto metido por no recordar las interfaces que hay que implementar para poder leer y/o escribir en la sesión en un controlador genérico de ASP.Net.

Double.Parse y Decimal.Parse con símbolos de putuación

Un problema que me encuentro a menudo en .Net por igual en Visual Basic o en C#, es cuando tengo que parsear un decimal o un double desde un string. Muchas veces, cuando parseas un double o un decimal, encontramos un error ya que en operaciones matemáticas, el símbolo de puntuación para la parte decimal es el punto, por lo que al hacer un Double.Parse(number) o un Decimal.Parse(number), lo que hace es ignorar el punto y por tanto tomar la parte decimal como si fuera parte entera. Para que esto no nos pase, tenemos que indicar que el sistema numérico utilizado es el matemático, aquel que no varia con la cultura. Con un ejemplo se verá mas claro.

Un ejemplo en C#:

[sourcecode language="csharp" title="Ejemplo en C#"] string number = "15.3";
double doNumber;
decimal deNumber;

doNumber = double.Parse(number);
deNumber = decimal.Parse(number);

/*
Los valores son:
doNumber = 153
deNumber = 153
*/

doNumber = double.Parse(number, CultureInfo.InvariantCulture);
deNumber = decimal.Parse(number, CultureInfo.InvariantCulture);

/*
Los valores son:
doNumber = 15.3
deNumber = 15.3
*/
[/sourcecode]

Un ejemplo en VB.Net

[sourcecode language="vb" title="Ejemplo en VB.Net"] Dim number As String = "15.3";
Dim doNumber As Double;
Dim deNumber As Decimal;

doNumber = double.Parse(number);
deNumber = decimal.Parse(number);

'Los valores son:
'doNumber = 153
'deNumber = 153

doNumber = double.Parse(number, CultureInfo.InvariantCulture);
deNumber = decimal.Parse(number, CultureInfo.InvariantCulture);

'Los valores son:
'doNumber = 15.3
'deNumber = 15.3
[/sourcecode]

CultureInfo es una clase que provee de información de las culturas y en concreto, la propiedad InvariantCulture o CultureInfo.InvariantCulture, es quien provee la información de la cultura que no varia por localizaciones, vease el simbolo de puntuación matemático. La clase CultureInfo se encuentra en el namespace System.Globalization, quedado la ruta así: System.Globalization.CultureInfo.InvariantCulture.

Por qué usar StringBuilder en lugar de concatenar Strings

Ando un poco liado y llevo una temporada sin escribir. Hay un apunte, que es común para varios lenguajes que son Java y por ejemplo .Net, tanto Visual Basic .Net y C#, así como el resto de lenguajes de la plataforma .Net que es la clase StringBuilder. Hay gente que no sabe por que o cuando utilizar la clase StringBuilder y realmente es uno de esos pequeños detalles de buenas prácticas, que a simple vista en un proyecto pequeño no se aprecian, pero cuando entre manos tenemos un gran proyecto que recibe millones de peticiones diarias, estas pequeñas nuevas practicas pueden suponer un gran referente de ahorro en el consumo de memoria y procesador de un servidor.

Tanto en Java como en .Net, cuando creamos un nuevo String, instanciamos un objeto String en una variable, cuando con la sentencia "+=" vamos concatenando mas texto, lo que hacen estas plataformas es crear una nueva instancia del objeto con la concatenación de las dos variables de texto. Por otro lado, cuando tenemos un StringBuilder instanciamos una clase StrringBuilder, llamando al método "append" en Java y "Append" en .Net, lo que hacemos es realizar una concatenación real de texto en el buffer de texto para luego instanciar un nuevo objeto String cuando llamemos al método "toString" en Java y "ToString" en .Net. A simple vista parece una tontería, cuando tenemos un texto que concatenamos 2 o 3 veces, realmente no merece la pena generar un StringBuilder, pero cuando concatenamos repetidamente texto varias veces el rendimiento es mayor si utilizamos StringBuilder, ya que si tenemos 20 concatenaciones seguidas, utilizando Strings normales concatenados, tendríamos 20 instancias de objetos, mientras que con StringBuilder solo 2. Como he dicho antes, en un pequeño proyecto, esto es prácticamente inapreciable, pero cuando tenemos un proyecto que recibe millones de peticiones diarias, algo tan tonto como utilizar concatenaciones de texto o StringBuilder puede suponer tener que añadir mas memoria al servidor para soportar tantas instancias de objetos e incluso un procesador mas potente para soportar el paso del recolector de basura para tantos objetos instanciados, esto en el mejor de los casos, si no llegamos al caso de tener que añadir un servidor al cluster para soportar todo esto.

Un cumulo de buenas practicas pueden suponer un gran ahorro de recursos, que se traducen en ahorro de dinero, cuando se trata de grandes proyectos.

Continue de un bucle en Visual Basic

Es curioso. El otro día estaba trabajando con unos bucles o loops como les dicen algunos, en el curro con Visual Basic .Net 1.1, es decir VB.Net en su versión de 2003. La verdad es que yo siempre he sido un hombre de bandera (jajaja) pero no se porque me empeñe en usar el continue. Probando con diferentes formas de ponerlo, "Continue", "Next" y alguna más que no recuerdo, buscando por internet y preguntando ha algun compañero, al final llegue a la conclusión, de que no existe un "Continue" ni equivalente en Visual Basic .Net, una lástima teniendo en cuenta que en C# si tiene continue. Seguiré usando mis banderitas que me funcionan en todos los lenguajes.

Por si hay alguien que no entiende para que sirve el continue, básicamente lo que hace es saltar a la siguiente iteración de un bucle ignorando todo el código de ese bucle desde que se llama hasta que llega al final del bucle, por llamarlo de alguna manera, "esta vuelta ha terminado".

Char curiosidad de IsLetter e IsDigit

El otro día, nos disponíamos mi jefe y yo a realizar un control sobre un campo de texto de una aplicación web. La idea era que en este campo solo se pudiera incluir texto o números, pero en ningún caso debería de poderse incluir caracteres raros. Seamos sinceros y siempre que hemos necesitado usar esto en lenguajes donde su framework no estaba preparado para diferenciar que tipo de carácter era, acabamos o bien creando un array diccionario y comparando los caracteres o bien usando expresiones regulares. Como no, desde el salto a tecnología de Microsoft (en este caso Visual Basic .Net) me propuse buscar alguna clase o método que hiciera solo lo que quería hacer, y la encontré.

En .Net existe la clase Char, que tiene el método Char.IsLetterOrDigit (boleano) donde le indicas un char o carácter y este te devuelve true o false si es un número o letra y false si no lo es. Monto una función para recorrer carácter a carácter del campo de texto comprobando si es alfanumérico o no, con la idea de borrar los caracteres que no sean alfanuméricos. Una vez montada la función, la pruebo unas cuantas veces y todo funciona estupendamente. Cuando nos vamos a disponer a subir a producción... sorpresa, la última prueba a fallado (pero es imposible), se nos deslizo el dedo y por poner un "1", pusimos un "º". Cuando nos ponemos a investigar (ha probar con jabatos) nos damos cuenta de que esta función, establece que los caracteres "º" y "ª" son alfanuméricos, vamos que son letras, supongo que la "o" y la "a".

Por supuesto esto lo controlamos y listo, pero si alguien se encuentra en nuestra misma situación y conoce alguna función que si trabaje correctamente que lo comente. Y si alguien buscando por internet se encuentra bloqueado y se ve encuentra con este post, ya puede respirar tranquilo, porque no es que funcione mal, es que no funciona del todo bien. (Si, ya se que para algunos "º" y "ª" son letras, pero realmente son caracteres especiales)

Bucle do-while en VisualBasic

Llevo tiempo currando con Visual Basic .Net, pero como persona formada desde hace años en lenguajes tipo C (C, C++, Java, C#, PHP, etc) el paso a programar en Visual Basic, cuesta mucho y cosas tan cotidianas como hacer un bucle, un switch o similares pueden convertirse en una peligrosa trampa que nos consumira muchos minutos muy valiosos.

La ultima que me he topado ha sido el bucle do while. En cualquier lenguaje tipo C, practicamente independiente del lenguaje estos bucles son iguales:

  do {
    sentencias
  } while(condicion);

Pero como no, estamos con Visual Basic y aqui todo funciona de manera diferente, es como nuestro tipico amigo que siempre lleva la contraria a todo. Por ejemplo para hacer un bucle do-while (me sorprende que en 9 meses sea la primera vez que me vea obligado a hacerlo, el bucle es do-loop-while, siendo su sintaxis

  Do
    sentencias
  Loop While condicionn

Puede que la gente que conozca o programe en Visual Basic lo vea una tonteria, pero para gente como yo que por razones laborales se ven obligadas a programar en dicho lenguaje y que por muchos meses se que lleve sigan prefiriendo C# a VB.Net, cosas tan cotidianas pueden convertirse en un minimundo.

Ya de paso y para aprovechar el post, explico que los bucles do while, son bucles que se recorreran igual que los while, en funcion de una condicion que de ser cierta dara una vuelta mas al bucle y que la principal diferencia entre los bucles while y do while, radica en que el while, primero comprueba la condicion antes de hacer una iteracion al bucle, mientras que los do while primero dara una iteracion al bucle y al final comprobara si debe de seguir haciendo iteraciones. Dicho de otro modo, el el while, primero comprobamos que debemos entrar al bucle y de ser cierto, entramos, en los do while, primero entramos al bucle y al final de este comprobamos si debemos dar una vuelta mas.

SharpOs, un sistema operativo diferente.

SharpOs es un sistema operativo que en lugar de estar desarrollandose como la mayoría de los sistemas operativos en C o C++, este sistema operativo se esta desarrollandose completamente en C#. El proyecto es GNU y esta disponible su código fuente desde SourceForge o desde la web de SharpOs.

De momento se encuentra en una fase alpha pero he descargado el código fuente y compilado con SharpDevelop y lo he ejecutado con MVWare. La verdad es que me sorprende que funcione correctamente y bueno, es cuestión de esperar un poco a que este más desarrollado, pero ya de por si tiene muy buena pinta.

Captura de SharpOs

La anterior captura es una realizada con la compilación desde mi equipo con VMWare donde se aprecia la ayuda de los comandos, como aparece un nuevo comando "test" y cuando lo ejecutamos aparece el texto "Testeando la aplicacion.....".

Espero que vaya subiendo rápido, que tengo ganas de poder desarrollar alguna que otra aplicación para este sistema operativo.