asp.net mvc usa Accepter la virgule et le point comme séparateur décimal




séparateur décimal usa (4)

Cette question a déjà une réponse ici:

La liaison de modèle dans ASP.NET MVC est excellente, mais elle suit les paramètres régionaux. Dans mon environnement local, le séparateur décimal est une virgule (','), mais les utilisateurs utilisent également dot ('.'), Car ils sont paresseux pour changer de modèle. Je veux que cela soit implémenté en un seul endroit pour tous decimal champs decimal de mes modèles.

Dois-je implémenter mon propre fournisseur de valeur (ou modèle de classeur d'événement) pour decimal type decimal ou j'ai manqué un moyen simple de le faire?


Grâce à la réponse acceptée, je me suis retrouvé avec l'implémentation suivante pour gérer float, double et 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;
}

Ensuite, il vous suffit de définir vos ModelBinders sur la méthode Application_Start

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

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

Le moyen le plus propre est de mettre en œuvre votre propre modèle de classeur

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

Et enregistrez-le dans Application_Start ():

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

Crédits: le modèle ASP.NET MVC 3 par défaut ne lie pas les propriétés décimales


Pour gérer correctement le séparateur de groupe, remplacez simplement

Convert.ToDecimal(valueProviderResult.AttemptedValue);

dans la réponse sélectionnée avec

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






value-provider