MVC3模型绑定导致“从类型'System.Int32'到'System.Decimal'的参数转换失败 - 没有类型转换器”

时间:2011-03-31 12:53:18

标签: jquery asp.net-mvc-3

我遇到以下异常:

  

异常{“参数转换   从类型'System.Int32'到键入   'System.Decimal'失败,因为没有   类型转换器之间可以转换   这些类型。“} System.Exception   {System.InvalidOperationException}

这是在我使用JQuery Ajax帖子将json发布回控制器之后。 MVC3正确地将JSON绑定到模型,因为我可以看到监视中的所有数据,但是ModelState有这个错误。

视图有一个十进制字段和一个包含数字的文本框。 即使文本框有整数值,我也会收到此错误。

关于为何失败的任何想法?

2 个答案:

答案 0 :(得分:13)

问题似乎源于默认的Model Binder,它伴随着MVC3无法将整数转换为小数。但是,如果json中的源值是字符串或十进制值,则可以进行转换。

解决方案是为十进制值创建自定义模型绑定器。

将其添加到global.asax.cs

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

创建模型绑定器:

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

答案 1 :(得分:10)

为了略微改进jaffa的好答案,您可能希望使用Decimal.TryParse,以便不可转换的值(如空字符串)不会抛出异常,而是将其传递给基本绑定器以便以一致的方式处理。

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        decimal value;
        return valueProviderResult == null || !Decimal.TryParse(valueProviderResult.AttemptedValue, out value) ? base.BindModel(controllerContext, bindingContext) : value;

    }

据我所知,最初的失败是ValueProviderResult没有提供转换器,它在内部来自TypeDescriptor,无法提供合适的转换器。此时我停止了寻找:)

还记得处理Nullable小数:

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