2010-06-23

StringWriter y con distintos Encodings

Recientemente me topé con un pequeño problema al armar una consigna de un trabajo práctico del colegio: La idea era armar un helper para que los chicos puedan bajar facilmente archivos XML.

El problema fue que yo me encargaba de bajar el stream del archivo, lo retocaba un poco y luego lo pasaba desde un XDocument a un string utilizando un StringWriter, entonces al escribir el string, lo hacía agregando el header de XML de encoding="utf-16". Todo esto no sería un problema si no fuese porque, la idea detrás de esto era que asi como les llegaba el string, lo pudiesen guardar a disco con StreamWriter, utilizando los constructores mas simples, sin tener que especificar encodings.

Dado que StringWriter no permite modificar el encoding que utiliza, la solución fue crear una subclase de StringWriter y hacer override de la propiedad Encoding.

La pequeña clase quedó asi:


class UTF8StringWriter : StringWriter
{
public override System.Text.Encoding Encoding
{
get
{
return System.Text.Encoding.UTF8;
}
}
}

Espero que les sea útil!

Zaiden


2010-06-21

Problemas al querer cargar un XML de un string Unicode

Hace poco, por cierta necesidad me encontré con un error bastante extraño. Al intentar leer un XML con un XmlDocument obtenía el siguiente error: "Data at the root level is invalid. Line 1, position 1".

El string obtenido provenía de un stream, el cual se iba leyendo de a partes.

Luego de varias idas y vueltas, encontré finalmente la casua del problema: al escribirse el stream original, se estaba haciendo lo siguiente:

var writer = new StreamWriter(stream, Encoding.Unicode);
writer.Write(text);

El problema que traía esto es que, por la forma en la que se estaba leyendo el stream del otro lado (codigo externo, revisado gracias al amigo Lutz!) se estaba interpretando mal la marca de uso de Unicode, al comienzo del string.

Para poder solucionar esto, bastó con reemplazar las lineas en la que se crea y usa el StreamWriter, por la siguiente:

var writer = new StreamWriter(stream, new UnicodeEncoding(false, false));
writer.Write(text);

Esta forma de crear el encoding, le indica que no se deberá incluir la marca de Unicode al comienzo del string, solucionando el problema antes mencionado

Espero poder ayudar a alguien con esto.
Saludos!

Zaiden


2010-06-07

Uso de certificados emitidos por Windows 2008 R2 desde .NET Framework

Si tienen la suerte de tener que utilizar certificados con un template v3 desde Windows Vista o superior, y los mismos fueron emitidos por un Windows Server 2008 R2, se encontrarán con una feliz excepción (Invalid provider type specified.) al intentar obtener la propiedad PrivateKey de una instancia de X509Certificate.

Esto ocurre, como bien se explica en este post debido a que la forma en que Windows Vista y Seven almacenan este tipo de certificado - utilizando Microsoft Software Key Storage Provider - solamente está soportado por CryptoAPI, pero no por las librerías provistas por .NET Framework 4.0 o anterior.

La forma de solucionar esto es utilizando las librerías provistas por los amigos del equipo de CLR Security:

  • Incluir "using Security.Cryptography.X509Certificates;" en el archivo que utilizará los certificados para traer los extension methods para la clase X509Certificate2
  • Preguntar por HasCngKey() en la instancia de X509Certificate2 para saber si la clave esta almacenada de esta forma. En caso afirmativo, crear una nueva instancia de RSACng utilizando el método GetCngPrivateKey() como parámetro.
Hasta la próxima!

Zaiden