2013-01-18 22 views
21

Model Bindung in ASP.NET MVC ist großartig, aber es folgt Locale-Einstellungen. In meinem Locale-Dezimaltrennzeichen ist Komma (','), aber Benutzer verwenden auch Punkt ('.'), Weil sie faul sind, Layouts zu wechseln. Ich möchte dies an einem Ort für alle decimal Felder in meinen Modellen implementiert.Akzeptieren Sie Komma und Punkt als Dezimaltrennzeichen

Sollte ich meinen eigenen Value Provider (oder Event Model Binder) für decimal Typ implementieren oder habe ich eine einfache Möglichkeit verpasst, dies zu tun?

+0

Die akzeptierte Lösung in einigen Fällen nicht funktioniert. Der folgende Link hat eine Lösung, die für alle Fälle funktioniert: https://stackoverflow.com/a/5117441/1314276 –

Antwort

35

sauberste Weg, um Ihr eigenes Modell Bindemittel

public class DecimalModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue); 
     // of course replace with your custom conversion logic 
    }  
} 

und registrieren Sie es innerhalb Application_Start() zu implementieren:

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder()); 

Credits: Default ASP.NET MVC 3 model binder doesn't bind decimal properties

+1

Wo DecimalModelBinder Klasse? –

+1

@ ИванБишевац Ich legte meine bei \ Common \ ModelBinders. –

+0

Convert.ToDecimal (valueProviderResult.AttemptedValue) funktioniert gut für Komma, aber für Punkt wird die Zahl mit 100 multipliziert. Vorschläge? –

1
var nfInfo = new System.Globalization.CultureInfo(lang, false) 
{ 
    NumberFormat = 
    { 
     NumberDecimalSeparator = "." 
    } 
}; 
Thread.CurrentThread.CurrentCulture = nfInfo; 
Thread.CurrentThread.CurrentUICulture = nfInfo; 
+0

plus. Ich liebe dich! –

5

Um richtig zu behandeln Gruppenseparator , ersetzen Sie einfach

Convert.ToDecimal(valueProviderResult.AttemptedValue); 

in ausgewählte Antwort mit

Decimal.Parse(valueProviderResult.AttemptedValue, NumberStyles.Currency); 
+2

Oder NumberStyles.Any, wenn Sie wild gehen wollen. – user15741

2

Dank akzeptierte Antwort, die ich mit der folgenden Umsetzung endete float, double und decimal zu handhaben.

public abstract class FloatingPointModelBinderBase<T> : DefaultModelBinder 
{ 
    protected abstract Func<string, IFormatProvider, T> ConvertFunc { get; } 

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     if (valueProviderResult == null) return base.BindModel(controllerContext, bindingContext); 
     try 
     { 
      return ConvertFunc.Invoke(valueProviderResult.AttemptedValue, CultureInfo.CurrentUICulture); 
     } 
     catch (FormatException) 
     { 
      // If format error then fallback to InvariantCulture instead of current UI culture 
      return ConvertFunc.Invoke(valueProviderResult.AttemptedValue, CultureInfo.InvariantCulture); 
     } 
    } 
} 

public class DecimalModelBinder : FloatingPointModelBinderBase<decimal> 
{ 
    protected override Func<string, IFormatProvider, decimal> ConvertFunc => Convert.ToDecimal; 
} 

public class DoubleModelBinder : FloatingPointModelBinderBase<double> 
{ 
    protected override Func<string, IFormatProvider, double> ConvertFunc => Convert.ToDouble; 
} 

public class SingleModelBinder : FloatingPointModelBinderBase<float> 
{ 
    protected override Func<string, IFormatProvider, float> ConvertFunc => Convert.ToSingle; 
} 

Dann müssen Sie nur noch Ihren Modelbinder auf Application_Start Methode setzen

ModelBinders.Binders[typeof(float)] = new SingleModelBinder(); 
ModelBinders.Binders[typeof(double)] = new DoubleModelBinder(); 
ModelBinders.Binders[typeof(decimal)] = new DecimalModelBinder(); 
Verwandte Themen