asp.net mvc - Acepta la coma y el punto como separador decimal
asp.net-mvc modelbinders (4)
Esta pregunta ya tiene una respuesta aquí:
El enlace de modelo en ASP.NET MVC es excelente, pero sigue la configuración regional. En mi localidad, el separador decimal es coma ('',''), pero los usuarios también usan punto (''.''), Porque son flojos para cambiar de diseño. Quiero que esto se implemente en un solo lugar para todos decimal
campos decimal
en mis modelos.
¿Debo implementar mi propio Proveedor de valor (o Carpeta de modelo de evento) para tipo decimal
o me he perdido alguna forma simple de hacer esto?
Gracias a la respuesta aceptada terminé con la siguiente implementación para manejar float, double y decimal.
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;
}
Luego solo tiene que configurar sus ModelBinders en el método Application_Start
ModelBinders.Binders[typeof(float)] = new SingleModelBinder();
ModelBinders.Binders[typeof(double)] = new DoubleModelBinder();
ModelBinders.Binders[typeof(decimal)] = new DecimalModelBinder();
La forma más limpia es implementar su propio modelo de carpeta
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
}
}
Y registrarlo dentro de Application_Start ():
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
Créditos: el cuaderno de modelo predeterminado de ASP.NET MVC 3 no enlaza las propiedades decimales
Para manejar adecuadamente el separador de grupos, simplemente reemplace
Convert.ToDecimal(valueProviderResult.AttemptedValue);
en respuesta seleccionada con
Decimal.Parse(valueProviderResult.AttemptedValue, NumberStyles.Currency);
var nfInfo = new System.Globalization.CultureInfo(lang, false)
{
NumberFormat =
{
NumberDecimalSeparator = "."
}
};
Thread.CurrentThread.CurrentCulture = nfInfo;
Thread.CurrentThread.CurrentUICulture = nfInfo;