代码之家  ›  专栏  ›  技术社区  ›  Michael Cook

使用货币格式值的TryUpdateModel?

  •  5
  • Michael Cook  · 技术社区  · 16 年前

    有没有任何方法可以让updateModel或tryUpdateModel将一个货币或货币格式的值(如$1200.00)解析为十进制,而不进行分块?

    3 回复  |  直到 16 年前
        1
  •  3
  •   eglasius    16 年前
        2
  •  2
  •   Michael Cook    16 年前

    由于弗雷德里奥斯的链接为我提供了执行此操作的基础,因此他获得了答案,但代码需要进行一些修改:

       // http://www.crydust.be/blog/2009/07/30/custom-model-binder-to-avoid-decimal-separator-problems/
    public class MoneyParsableModelBinder : DefaultModelBinder
    {
    
        public override object BindModel(ControllerContext controllerContext,
          ModelBindingContext bindingContext)
        {
    
            object result = null;
            // Added support for decimals and nullable types - c.
            if (
                bindingContext.ModelType == typeof(double)
                || bindingContext.ModelType == typeof(decimal)
                || bindingContext.ModelType == typeof(double?)
                || bindingContext.ModelType == typeof(decimal?)
                )
            {
    
                string modelName = bindingContext.ModelName;
                string attemptedValue = bindingContext.ValueProvider[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);
                }
    
                // If SetModelValue is not called it may result in a null-ref exception if the model is resused - c. 
                bindingContext.ModelState.SetModelValue(modelName, bindingContext.ValueProvider[modelName]);
    
                try
                {
                    // Added support for decimals and nullable types - c.
                    if (bindingContext.ModelType == typeof(double) || bindingContext.ModelType == typeof(double?))
                    {
                        result = double.Parse(attemptedValue, NumberStyles.Any);
                    }
                    else
                    {
                        result = decimal.Parse(attemptedValue, NumberStyles.Any);
                    }
                }
                catch (FormatException e)
                {
                    bindingContext.ModelState.AddModelError(modelName, e);
                }
            }
            else
            {
                result = base.BindModel(controllerContext, bindingContext);
            }
    
            return result;
        }
    }
    

    它不漂亮,但很管用。

        3
  •  1
  •   Adam Ralph    16 年前

    在调用这两个方法之前,您是否能够预先解析该值?如果是这样,您可以使用以下方法来执行此操作

        var provider = (NumberFormatInfo)CultureInfo.InvariantCulture.NumberFormat.Clone();
        provider.CurrencySymbol = "$";
        var x = decimal.Parse(
            "$1,200",
            NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands,
            provider);