Abbiate
pazienza, non è mia abitudine lamentarmi, ma
stavolta lo sbottare ci sta davvero tutto. Ma prima del fatto è bene che vi racconti
l'antefatto. Stasera, io e il collega Andrea Dottor ci siamo scontrati con un
comportamento apparentemente inspiegabile. Un pezzo di codice apparentemente
perfetto falliva miseramente e inspiegabilmente. In buona sostanza quello che
stavamo facendo era tutto sommato semplice; Un campo di tipo Textbox riceveva
una stringa in che rappresentava una valuta, per la precisione "0,5" in seguito
tale stringa arrivava al validatore serverside che utilizzando
decimal.TryParse() verificava che si trattasse effettivamente di un decimal.
Questo controllo, applicato sia con la CultureInfo che senza veniva eseguito
perfettamente restituendo un chiaro e lampante "true". Tuttavia, pochi
millisecondi dopo, quando la datasource tentava di mappare i campi su un oggetto
di business, l'operazione miseramente scoppiava, con il seguente errore: "0,5"
is not a valid value for Decimal.
Alla fine, solo analizzanto il codice del
framework linea per linea con Reflector siamo giunti a capire il motivo per cui
questa banale operazione scoppiava:
private static object ConvertType(object value, Type type, string paramName)
{
string text1 = value as string;
if (text1 != null)
{
TypeConverter converter1 = TypeDescriptor.GetConverter(type);
if (converter1 == null)
{
return value;
}
try
{
value = converter1.ConvertFromInvariantString(text1);
}
catch (NotSupportedException)
{
throw new InvalidOperationException(
SR.GetString("ObjectDataSourceView_CannotConvertType",
new object[] { paramName, typeof(string).FullName, type.FullName }));
}
catch (FormatException)
{
throw new InvalidOperationException(
SR.GetString("ObjectDataSourceView_CannotConvertType",
new object[] { paramName, typeof(string).FullName, type.FullName }));
}
}
return value;
}
Questo codice, estratto dalla classe ObjectDataSourceView è la
causa del misfatto e precisamente la riga che chiama il metodo
ConvertFromInvariantString() del TypeConverter. La ObjectDataSourceView, per
inciso, è l'oggetto che all'interno della ObjectDataSource si incarica di
effettuare le operazioni incapsulando al suo interno una rappresentazine dello
storage. La chiamata a ConvertFromInvariantString() scritta in questo modo
impone che un dato decimal, ma con tutta probabilità anche una data o un double,
debba essere formattato con cultura neutra, e cioè nel nostro caso con il punto
al posto della virgola. Una chiamata corretta sarebbe stata la
seguente:
value = converter1.ConvertFromString(null, CultureInfo.CurrentCulture, text);
In questo modo la datasource avrebbe tenuto conto della cultura
corrente e quindi si sarebbe adeguata al contesto del thread,
consentendo alla conversione di avvenire correttamente. Ora, purtroppo i
metodi in questione sono privati e perciò non è possibile porre rimedio a questo
problema cercando di sostituire la ObjectDataSourceView con un oggetto che sia
stato patchato. In realtà credo di avere un'idea per una soluzione, che però
tenterò domattina, ma lasciatemi dire che un errore del genere non me lo sarei
mai aspettato.