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

jaf*_*ffa 9 jquery asp.net-mvc-3

我收到以下异常:

异常{"从类型'System.Int32'到类型'System.Decimal'的参数转换失败,因为没有类型转换器可以在这些类型之间进行转换."} System.Exception {System.InvalidOperationException}

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

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

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

jaf*_*ffa 13

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

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

将其添加到global.asax.cs

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
Run Code Online (Sandbox Code Playgroud)

并创建模型绑定器:

  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);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Sim*_*sco 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;

    }
Run Code Online (Sandbox Code Playgroud)

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

还记得处理Nullable小数:

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
Run Code Online (Sandbox Code Playgroud)