【问题标题】:save comma separated number in databse decimal type在数据库十进制类型中保存逗号分隔的数字
【发布时间】:2015-01-23 17:04:50
【问题描述】:

我们有大型 MVC(5.0) 应用程序,其中我们在数据库中保存了大量的十进制数据。有来自 UI 的货币和小数输入。现在出现了一个新的更改请求,以在 UI 和表单中以逗号分隔的数字显示所有数值。我们有一个 jQuery 函数,可以将这些值更改为正确的格式。

我们的类字段被定义为十进制以接受这些值。当我尝试用逗号保存数据时出现问题。我们正在使用 jQuery.ajax 来 POST 加密逗号分隔数字的表单。

我不想用cultureInfo 去修改每个表单。有没有更好的方法,我设置一次,当我尝试保存在数据库中时,它将接受并转换这些逗号分隔的数字?

我尝试在 Global.asax 中设置文化信息,例如:

protected void Application_BeginRequest()
{
        System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture;
}

这似乎不起作用。有没有什么好的和干净的方法来解决这个问题而不改变每个字段?

【问题讨论】:

    标签: asp.net-mvc database csv cultureinfo


    【解决方案1】:

    我遇到了同样的问题,我通过写ModelBinder 解决了我的问题,如下所示

    public class MyModelBinder : DefaultModelBinder
    {
         public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType == typeof(decimal) || bindingContext.ModelType == typeof(Nullable<decimal>))
            {
                var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                if (valueProviderResult != null)
                {
                    decimal result;
                    var array = valueProviderResult.RawValue as Array;
                    string value;
                    if (array != null && array.Length > 0)
                    {
                        value = array.GetValue(0).ToString().Replace(",", ""); ;
                        if (decimal.TryParse(value.ToString(), out result))
                        {
                            string val = result.ToString(CultureInfo.InvariantCulture.NumberFormat);
                            array.SetValue(val, 0);
                        }
                    }
                }
            }
            else if (bindingContext.ModelType == typeof(int) || bindingContext.ModelType == typeof(Nullable<int>))
            {
                var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                if (valueProviderResult != null)
                {
                    int result;
                    var array = valueProviderResult.RawValue as Array;
                    string value;
                    if (array != null && array.Length > 0)
                    {
                        value = array.GetValue(0).ToString().Replace(",", ""); 
                        if (int.TryParse(value.ToString(), out result))
                        {
                            string val = result.ToString(CultureInfo.InvariantCulture.NumberFormat);
                            array.SetValue(val, 0);
                        }
                    }
                }
            }
            else if (bindingContext.ModelType == typeof(long) || bindingContext.ModelType == typeof(Nullable<long>))
            {
                var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                if (valueProviderResult != null)
                {
                    long result;
                    var array = valueProviderResult.RawValue as Array;
                    string value;
                    if (array != null && array.Length > 0)
                    {
                        value = array.GetValue(0).ToString().Replace(",","");
                        if (long.TryParse(value, out result))
                        {
                            string val = result.ToString(CultureInfo.InvariantCulture.NumberFormat);
                            array.SetValue(val, 0);
                        }
                    }
                }
            }
            var res = base.BindModel(controllerContext, bindingContext);
            return res;
        }
    }
    

    并将这些代码添加到Application_Start 中的global.asax

            ModelBinders.Binders.DefaultBinder = new MyModelBinder();
    

    【讨论】:

    • 谢谢,但每次查看 kill 的每个控件都会调用它。我只想为十进制类型调用它。
    • Sine 已经有一个DefaultBinder,每次操作都会调用它,并且由于有if 来检查类型,所以不用担心被杀死;)
    【解决方案2】:

    最后我找到了 3 个步骤的解决方案:

    1. 添加类以覆盖 DefaultModelBinder

      public class DecimalModelBinder : DefaultModelBinder
      {
         public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
         {
          var valueProvider = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
      
          object result = null;
          try
          {
              if (!string.IsNullOrEmpty(valueProvider.AttemptedValue))
                  result = decimal.Parse(valueProvider.AttemptedValue);
          }
          catch (FormatException e)
          {
              bindingContext.ModelState.AddModelError(bindingContext.ModelName, e);
          }
      
          return result;
      }
      

      }

    2. 在 Application_Start 的 Global.asax 中调用这个类

      ModelBinders.Binders.Add(typeof(decimal), new GOA.Department.ANS.Web.Model.DecimalModelBinder());
      ModelBinders.Binders.Add(typeof(decimal?), new GOA.Department.ANS.Web.Model.DecimalModelBinder());
      

    以上代码将解决服务器端验证。我们仍然需要使用 jquery.validate 在客户端进行验证。答案是扩展 validate 方法。

    1. 在调用 jquery.validate.js 之后,在你的页面中添加这些行或创建一个单独的 .js 文件,最后将被调用:

      $.validator.methods.range = function (value, element, param) {
        var val = value.replace(",", "");
        return this.optional(element) || (val >= param[0] && val <= param[1]);
      }
      
      $.validator.methods.min = function (value, element, param) {
        var val = value.replace(",", "");
        return this.optional(element) || (val >= param);
      }
      
      $.validator.methods.max = function (value, element, param) {
        var val = value.replace(",", "");
        return this.optional(element) || (val <= param);
      }
      
      $.validator.methods.number = function (value, element) {
        return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/.test(value);
      }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-14
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 2021-03-01
      • 1970-01-01
      • 2016-03-23
      相关资源
      最近更新 更多