Po prostu ponownie przeanalizowałem problem w prawdziwym projekcie i ostatecznie znalazłem działające rozwiązanie. Prawidłowe rozwiązanie ma mieć spinacza modelu niestandardowych dla typu decimal
(i decimal?
jeśli ich użyciem):
using System.Globalization;
using System.Web.Mvc;
public class DecimalModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
object result = null;
// Don't do this here!
// It might do bindingContext.ModelState.AddModelError
// and there is no RemoveModelError!
//
// result = base.BindModel(controllerContext, bindingContext);
string modelName = bindingContext.ModelName;
string attemptedValue =
bindingContext.ValueProvider.GetValue(modelName).AttemptedValue;
// Depending on CultureInfo, the NumberDecimalSeparator can be "," or "."
// Both "." and "," should be accepted, but aren't.
string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator;
string alternateSeperator = (wantedSeperator == "," ? "." : ",");
if (attemptedValue.IndexOf(wantedSeperator) == -1
&& attemptedValue.IndexOf(alternateSeperator) != -1)
{
attemptedValue =
attemptedValue.Replace(alternateSeperator, wantedSeperator);
}
try
{
if (bindingContext.ModelMetadata.IsNullableValueType
&& string.IsNullOrWhiteSpace(attemptedValue))
{
return null;
}
result = decimal.Parse(attemptedValue, NumberStyles.Any);
}
catch (FormatException e)
{
bindingContext.ModelState.AddModelError(modelName, e);
}
return result;
}
}
Następnie w Global.asax.cs w Application_Start():
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
Zauważ, że kod nie jest mój, faktycznie znalazłem go na blogu Kristof Neirynck here. Właśnie edytowałem kilka linii i dodawałem segregator dla określonego typu danych, nie zastępując domyślnego segregatora.
Właśnie zaktualizowałem swoją odpowiedź, dodając dodatkowe sprawdzenie kodu, aby poprawnie obsługiwać właściwości zerowania. Odkryłem, że jeśli znajdzie pusty ciąg jako wartość próby, wyrzuci wyjątek, nawet jeśli powiązana właściwość jest zerowa. Teraz powinno działać dobrze. –
Istnieje dodatkowa kompilacja po stronie klienta, która powinna zostać zastosowana wzdłuż tej. Znajdziesz go tutaj: http://stackoverflow.com/a/8102159/41420 –
Nie działa z ciągiem znaków jako danych wejściowych – Furtiro