2013-01-18 23 views
21

Powiązanie modelu w środowisku ASP.NET MVC jest świetne, ale jest zgodne z ustawieniami narodowymi. W moim locale separatorem dziesiętnym jest przecinek (","), ale użytkownicy również używają kropki ("."), Ponieważ są leniwi, aby przełączać układy. Chcę to zaimplementować w jednym miejscu dla wszystkich pól decimal w moich modelach.Akceptuj przecinek i kropkę jako separator dziesiętny

Czy powinienem wdrożyć mój własny dostawca wartości (lub modelowy segregator) dla typu decimal, czy też przeoczyłem prosty sposób na zrobienie tego?

+0

Przyjęte rozwiązanie nie działa w niektórych przypadkach. Poniższy link ma rozwiązanie, które działa we wszystkich przypadkach: https://stackoverflow.com/a/5117441/1314276 –

Odpowiedz

35

najczystszym sposobem jest, aby zaimplementować własną spoiwa modelu

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 
    }  
} 

i zarejestrować go wewnątrz Application_Start():

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

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

+1

Gdzie umieścić klasę DecimalModelBinder? –

+1

@ ИванБишевац Umieściłem mój w \ Common \ ModelBinders. –

+0

Convert.ToDecimal (valueProviderResult.AttemptedValue) działa poprawnie dla przecinka, ale dla kropki liczba jest mnożona przez 100. Sugestie? –

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

plus. kocham koleś! –

5

Aby prawidłowo obsługiwać separator grupy , wystarczy wymienić

Convert.ToDecimal(valueProviderResult.AttemptedValue); 

w wybranych odpowiedzi z

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

Lub NumberStyles.Any, jeśli chcesz przejść dziki. – user15741

2

Dzięki odpowiedź przyjętą skończyło się z poniższym realizacji do obsługi float, double i dziesiętne.

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; 
} 

Wtedy po prostu trzeba ustawić ModelBinders na Application_Start metody

ModelBinders.Binders[typeof(float)] = new SingleModelBinder(); 
ModelBinders.Binders[typeof(double)] = new DoubleModelBinder(); 
ModelBinders.Binders[typeof(decimal)] = new DecimalModelBinder(); 
Powiązane problemy