c# - Uri.EscapeDataString()-URI no válido: la cadena Uri es demasiado larga
exception-handling httpwebrequest (5)
Estoy usando framework / C # compacto en Windows Mobile.
En mi aplicación, estoy cargando datos en el servidor al serializar objetos y usar una solicitud HttpWebRequest / POST para enviar la información. En el servidor, los datos de la publicación se des-serializan y se guardan en la base de datos.
El otro día me di cuenta de que tenía un problema con los caracteres especiales en los datos de la publicación (ampersands, etc.). Así que introduje Uri.EscapeDataString () en el método y todo estuvo bien.
Sin embargo, hoy he descubierto que hay un problema cuando la aplicación intenta cargar una gran cantidad de datos (¡no estoy seguro de qué significa exactamente "grande" en este momento!)
Código existente (tipo de)
var uploadData = new List<Things>();
uploadData.Add(new Thing() { Name = "Test 01" });
uploadData.Add(new Thing() { Name = "Test 02" });
uploadData.Add(new Thing() { Name = "Test with an & Ampersand " }); // Do this a lot!!
var postData = "uploadData=" + Uri.EscapeDataString(JsonConvert.SerializeObject(uploadData, new IsoDateTimeConverter()));
Problema
La llamada a Uri.EscapeDataString () está causando la siguiente excepción:
System.UriFormatException: URI no válido: la cadena Uri es demasiado larga.
Pregunta
¿Hay alguna otra forma de preparar los datos para subir?
Hasta donde puedo ver, HttpUtility (que tiene sus propios métodos de codificación / decodificación) no está disponible para el marco compacto.
He estado usando System.Web.HttpUtility.UrlEncode y parece manejar las cadenas más largas mucho mejor.
La respuesta de "Alberto de Paola" es buena.
No obstante, no es un poco más complicado que los datos escapados se escapen, ya que debe evitar cortar la cadena codificada en medio de un carácter codificado (o romperá la integridad de la cadena original).
Aquí está mi manera de solucionar este problema:
public static string EncodeString(string str)
{
//maxLengthAllowed .NET < 4.5 = 32765;
//maxLengthAllowed .NET >= 4.5 = 65519;
int maxLengthAllowed = 65519;
StringBuilder sb = new StringBuilder();
int loops = str.Length / maxLengthAllowed;
for (int i = 0; i <= loops; i++)
{
sb.Append(Uri.EscapeDataString(i < loops
? str.Substring(maxLengthAllowed * i, maxLengthAllowed)
: str.Substring(maxLengthAllowed * i)));
}
return sb.ToString();
}
public static string DecodeString(string encodedString)
{
//maxLengthAllowed .NET < 4.5 = 32765;
//maxLengthAllowed .NET >= 4.5 = 65519;
int maxLengthAllowed = 65519;
int charsProcessed = 0;
StringBuilder sb = new StringBuilder();
while (encodedString.Length > charsProcessed)
{
var stringToUnescape = encodedString.Substring(charsProcessed).Length > maxLengthAllowed
? encodedString.Substring(charsProcessed, maxLengthAllowed)
: encodedString.Substring(charsProcessed);
// If the loop cut an encoded tag (%xx), we cut before the encoded char to not loose the entire char for decoding
var incorrectStrPos = stringToUnescape.Length == maxLengthAllowed ? stringToUnescape.IndexOf("%", stringToUnescape.Length - 4, StringComparison.InvariantCulture) : -1;
if (incorrectStrPos > -1)
{
stringToUnescape = encodedString.Substring(charsProcessed).Length > incorrectStrPos
? encodedString.Substring(charsProcessed, incorrectStrPos)
: encodedString.Substring(charsProcessed);
}
sb.Append(Uri.UnescapeDataString(stringToUnescape));
charsProcessed += stringToUnescape.Length;
}
var decodedString = sb.ToString();
// ensure the string is sanitized here or throw exception if XSS / SQL Injection is found
SQLHelper.SecureString(decodedString);
return decodedString;
}
Para probar estas funciones:
var testString = "long string to encode";
var encodedString = EncodeString(testString);
var decodedString = DecodeString(encodedString);
Console.WriteLine(decodedString == testString ? "integrity respected" : "integrity broken");
Espero que esto pueda ayudar a evitar algunos dolores de cabeza;)
O simplemente puede dividir la cadena y llamar a Uri.EscapeDataString(string)
para cada bloque, para evitar la reimplementación de la función.
Código de muestra:
String value = "large string to encode";
int limit = 2000;
StringBuilder sb = new StringBuilder();
int loops = value.Length / limit;
for (int i = 0; i <= loops; i++)
{
if (i < loops)
{
sb.Append(Uri.EscapeDataString(value.Substring(limit * i, limit)));
}
else
{
sb.Append(Uri.EscapeDataString(value.Substring(limit * i)));
}
}
Use System.Web.HttpUtility.UrlEncode
(basado en esta respuesta ):
value = HttpUtility.UrlEncode(value)
.Replace("!", "%21")
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("*", "%2A")
.Replace("%7E", "~"); // undo escape
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < originalString.Length; i++)
{
if ((originalString[i] >= ''a'' && originalString[i] <= ''z'') ||
(originalString[i] >= ''A'' && originalString[i] <= ''Z'') ||
(originalString[i] >= ''0'' && originalString[i] <= ''9''))
{
stringBuilder.Append(originalString[i]);
}
else
{
stringBuilder.AppendFormat("%{0:X2}", (int)originalString[i]);
}
}
string result = stringBuilder.ToString();