Tag Archives: dotnet

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.

Lenguajes de programación semánticos (python) contra matemáticos (c#)

Hace tiempo escribí un artículo en el que hablaba de frameworks web para programar y fui criticado por criticar django. Bueno como aclaratoria, escribo este artículo, en el que detallo las diferencias de los programadores, una gran batalla entre lenguajes semánticos vs matematicos; en este caso python vs c#.

Veamos primero que es cada uno, un lenguaje semántico es un lenguaje de programación que pretende ser similar a un lenguaje real, como el español, inglés, etc. mientras que un lenguaje matemático es mas parecido a ecuaciones con llaves, corchetes, paréntesis, etc. Pero veamos mas diferencias, un lenguaje semántico, sea cual sea, persigue el "de un vistazo", generalmente esta ausente de llaves y basa su estructuración en identación y estructuras muy semánticas como delimitadores de texto. Para este caso tenemos como ejemplo a VB, en el que terminamos un if con un End If, un for con un Next, etc. la identación automática que propone el propio ide de programación o como en el caso de Python, la identación es necesaria para que el interprete de Python entienda el código.

Un lenguaje matemático es en contra de un lenguaje semántico, un lenguaje de formulas y ecuaciones, que sin tener unas nociones de matemáticas y que estas nos gusten se nos pueden atragantar bastante. A diferencia de lo que ocurre en los lenguajes semánticos, este tipo de lenguajes a pesar de que la identación suele ser importante para la claridad y el entendimiento, también nos permite escribir todo nuestro código en una sola línea. Las funciones suelen estar delimitadas por llaves {} así como las clases y namespaces. Las lineas de un lenguaje matemático suelen estar delimitadas por puntos y coma ";", y como mencione antes, al tener delimitadores de linea todo el código puede estar en una única linea, como ocurre en el caso de los frameworks de javascript que comprimen su código hasta que ocupe una única linea.

¿Pero qué es mejor? Pues depende de la persona, igual que hay zapatillas para los corredores según su tipo de pisada, hay lenguajes según como programes. Hay programadores que son mas de letras, les gusta ver su código y creer que están leyendo un libro. Para ellos, un lenguaje semántico es ideal, un python o un visual basic. Para aquellos programadores que como me ocurre a mi, nos gusta ver una cierta simetría en nuestro código y que al ver el código parezca una libreta de un matemático, lleno de formulas, lenguajes como c# o java, son para mi.

¿Y cual es mejor? Pues ninguno. Lo mas importante es sentirse a gusto con el entorno con el que se trabaja. Si por ejemplo, eres un matemático puro, python es horrible, pero no quiere decir que no lo puedas utilizar. Por contra, si eres muy semántico, c# sería incomprensible. A la hora de trabajar, hay que tener en cuenta 3 factores básicos. En primer lugar en que lenguaje nos sentimos mas cómodos. Evidentemente no vamos a programar como no nos gusta (salvo que nuestro jefe nos lo diga). En segundo lugar hay que saber elegir bien el lenguaje con sus herramientas. En Lenguajes como PHP tenemos multitud de librerías y aplicaciones ya desarrolladas, en python django tenemos muchos módulos, etc. en c# el deploy es muy sencillo, pero no se nos ocurriría hacer una web en shell script por ejemplo, ya que no tenemos el mismo potencial de librerías. Por último hay que elegir sabiamente según lo que vayamos a hacer. Si por ejemplo vamos a desarrollar una pequeña aplicación, con un PHP vamos sobrados, si queremos generar una página sencilla, podemos utilizar django, pero si queremos hacer una aplicación grande y escalable, quizás c# nos convenga mas. Hay que saber equilibrar todo estos puntos para elegir siempre la mejor opción según lo que vayamos a desarrollar.

Yo programo las aplicaciones prefabricadas (wordpress, prestashop, etc) o páginas muy muy sencillas en PHP, otros proyectos a medida de mayor envergadura pero pequeños en python con django o pylons y los grandes proyectos en c# con mono aspnet mvc y AltairStudios.Core. Y tu, ¿En qué programas?

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.

Por que no usar django. Breve comparativa entre django, ruby y Mono ASP.Net con MVC

Hace un tiempo empecé a oír hablar de django y empecé a interesarme por el. La verdad que al principio me llamaba mucho la atención porque la gente no hacia mas que alabar las virtudes de django. Investigando encontraba mas y mas alabanzas, incluso expertos que comparaban django con otros entornos como Mono ASP.Net con MVC o ruby.

A veces las comparaciones son odiosas y esto es que lo les pasa a los demás entornos cuando los comparamos con django. Al comparar django con Mono ASP.Net con MVC, comentaban como un mismo proyecto realizado por programadores expertos en django, realizaban muchas mas tareas que los expertos en ASP.Net en el mismo tiempo y que el resultado final del proyecto es que era mas rápido y consistente el desarrollo en django que en ASP.Net. Yo no digo que django sea un mal entorno, ni que los programadores de ASP.Net sean malos, pero la calidad de un programador de .Net realizando una web deja un poco que desear en la mayoría de los casos, no asi un programador friki de python que ha decidido hacer webs y que seguramente sea mucho mas versátil que uno de asp.net aunque hiciera la web en php y para mi esto no es comparable. Por otro lado comparaban django con ruby y no me gusto nada la comparación, ya que al comparar, decían que ruby on rails era para “nenas” y django para “hombre de pelo en pecho”. La verdad que esta comparación, es un poco ridícula, hasta llego a hacerme gracia a pesar de no gustarme.

Ahora vayamos a mi experiencia personal. Decidí instalarme django, ruby y Mono ASP.Net con MVC. Al buscar información, tutoriales o algo de guía para instalar e iniciar django, me encuentro con poca información y además centrada para linux, seguía las guías para mac y me costo sudor y lágrimas hacerlo correr (mi amigo @saikus no fue capaz). Cuando ya conseguí, intente hacer una prueba pero fui incapaz, bastante complicado para empezar sin un libro o sin que alguien te enseñe. Aun así, vi que utiliza una especie de servidor propio, por lo que para por ejemplo hacerlo correr en apache, hay que arrancarlo desde ssh y enlazarlo por un fastcgi o similar con apache, pero la cuestión es, cuanta comunidad puede generar algo que es muy muy muy dificil que sin ser pro y sin gastar un dineral en hosting, puedan hacer pruebas (yo en mi hosting no puedo instalarlo de momento).

Por ejemplo, mi experiencia con ruby o asp.net es muy mas satisfactoria, puesto que ruby es tan fácil como instalarlo desde algún apt-get, ports, descargable, etc y luego instalar las mil y una gemas necesarias. De una forma rápida y fácil puedes hacer funcionar un ejemplo o programar algo no solo en linux, sino en MacOSX, que es importante, ya que cada vez hay mas gente que usa este sistema. Por otro lado Mono ASP.Net con MVC es también muy fácil, quizás algo mas complejo que ruby, pero tan fácil como bajarse el instalable o en el peor de los casos las fuentes de la web de mono y compilar. Mono ya tiene XSP que es su propio server como ocurre con django y rails, y con mod_mono lo compilamos e instalamos en un periquete en apache.

Por que me gusta mas usar Mono ASP.Net con MVC que usar ruby o django. Django lo descarto por el costo de su instalación, porque no tengo un buen IDE donde poder programarlo y si quisiera pagar aunque fuera poco por los IDES, ¿Por qué no volverme a Windows y usar Visual Studio? Ruby es un poco parecido, es mas fácil de instalar y trabajar, pero falta un buen IDE, Netbeans tiene soporte, al igual que Eclipse para django, pero son plugins para mi gusto no estan muy muy depurados. Por el lado de Mono ASP.Net con MVC tenemos la opción de monodevelop, que si bien es cierto que sus primeras versiones eran como los plugins antes mencionados, las ultimas han mejorado sustancialmente y no hay que olvidar que en lugar de ser un IDE de java con plugins para python o ruby, es un IDE de .Net (dotnet), por lo que mvc esta soportado nativamente.

En conclusión, a django le veo demasiadas pegas que ensombrecen las virtudes que tiene. Ruby es quizás el mas equilibrado en cuanto a potencia y tiempo de desarrollo y Mono ASP.Net con MVC es mas lento en cuanto a desarrollo pero muy potente, además de no ser un framework añadido a un lenguaje (mvc si, pero no asp) sino todo un entorno preparado para la web, donde con un par de clicks es muy fácil generar clientes de servicios web, o crear un servicio web xml, una pagina web o mil cosas mas. Es por esto que yo personalmente me quedo con Mono ASP.Net con MVC.

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.

Descodificar Quoted Printable para leer correos de GMail en Visual Basic

Un amigo esta realizando un proyecto en Visual Basic .Net, que entre otras cosas se conecta a GMail para recibir correos e introducirlos en una base de datos para mostrarlos en un panel de administración. Hasta aquí todo normal, el problema viene cuando en los correos utiliza caracteres, que vamos a llamar extraños, como tildes por ejemplo. Cuando recibimos por código un mail que por ejemplo contenía la cadena "conexión", este texto no se nos devuelve así, sino que nos devolvería "conexi=F3n" y he aqui el problema, ya que esto no es codificación normal de UTF-8 a ASCII o similares sino que es completamente diferente.

Los servidores de correo utilizan protocolos bastante antiguos, en los que todo se basta en texto. Para separar encabezados se utilizan saltos de linea tipo "rn" o "n" y por ejemplo para adjuntar archivos hay que declarar una marca y decirle que el contenido del archivo esta entre marca y marca. Como no, todo esta basado en texto ASCII por lo que los caracteres extraños, letras con acento, eñes y similares, suelen encontrarse en una codificación que se llama "Quoted printable".

Quoted Printable o simplemente acortado QP es un sistema de codificación de 8 bits compatible con ASCII que basa su codificación de caracteres extraños en un formato de un símbolo igual seguido de 2 posiciones hexadecimales. Se rige por el estándar RFC-1345. Aunque algunos lenguajes traen incorporado por defecto funciones o librerías para codificación y descodificación de caracteres, .Net no tiene nada para descodificar este tipo de codificación. A continuación os mostrare un ejemplo de función de Visual Basic para la descodificación de estos caracteres, que básicamente recoge estos caracteres hexadecimales, los convierte a entero y obtiene el caracter de ASCII extendido de 255 caracteres, no el tradicional de 128 caracteres. De esta forma, obtendrá el carácter correcto ya traducido. Os dejo el ejemplo de la función:

Función de descodificación de cadenas de texto Quoted Printable

Public Shared Function QuotedPrintableDecode(ByVal text As String) _
As String
  Dim i As Integer
  Dim DecodedString As StringBuilder
  Dim Chars As Char()
  Dim CharsValue As String
  Dim HexValue As Integer

  Chars = text.ToCharArray()
  DecodedString = New StringBuilder

  For i = 0 To Chars.Length - 1
    If Chars(i) = "=" Then
      CharsValue = Nothing
      HexValue = Nothing

      If Chars(i + 1) = "0" Then
        CharsValue = Chars(i + 2)
      Else
        CharsValue = Chars(i + 1) & Chars(i + 2)
      End If

      HexValue = Val("&H" & CharsValue)

      If CharsValue.ToUpper = Hex(HexValue) Then
        DecodedString.Append(ChrW(HexValue))
        i += 2
      Else
        DecodedString.Append(Chars(i))
      End If
    Else
      DecodedString.Append(Chars(i))
    End If
  Next

  Return DecodedString.ToString
End Function

Ahora solo hace falta llamar a esa función pasando la cadena a convertir:

Public Shared Sub Main()
  Dim text As String = "conexi=F3n"
  Console.WriteLine(Application.QuotedPrintableDecode(text))
End Sub

El resultado de aplicar esto seria la cadena "conexión". Para que funcione es necesario importar el namespace System.Text, pero solo para el StringBuilder

Imports System.Text

Espero que os sirva de ayuda.

Conectar a una url, webservice o REST en C#

Hoy en día se necesita conectar con páginas web, bien sea para extraer información de una página o para conectar contra un WebService. DotNet o .Net, nos provee de una serie de herramientas para la conexión contra WebServices, pero hay casos excepcionales, en los que necesitaremos conectarnos de una manera más arcaica y tradicional, al estilo de la librería cURL por ejemplo. En este caso mostrare un ejemplo de como conectarnos a una url de un WebService ficticio y como recoger su contenido para luego ser tratado. En primer lugar crearemos un String donde poner la url de la conexión. Seguidamente conectaremos utilizando los objetos HttpWebRequest y HttpWebResponse y generaremos un StreamReader con la respuesta. El código quedaría así:


String baseUri = "http://rutaalwebserice";
HttpWebRequest connection = (HttpWebRequest)HttpWebRequest.Create(baseUri);
connection.Method = "GET";
HttpWebResponse response = (HttpWebResponse)connection.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);

Ya tenemos nuestra variable sr (StreamReader) para poder utilizarla para trabajar con el supuesto XML o HTML devuelto. Es importante apuntar, que para utilizar estas librerías, necesitamos incluir los siguientes nombres de espacio:


using System.Web;
using System.Net;
using System.IO;
using System.Text;