由于某些原因,当我将这个JSON发送到一个操作时:
{"BaseLoanAmount": 5000}
这个属性应该绑定到一个名为“BaseLoanAmount”的十进制数属性的模型上,但它没有绑定,仍然保持为0。但是,如果我发送:
{"BaseLoanAmount": 5000.00}
它确实绑定了属性,但为什么呢?即使它没有小数,难道5000不能被转换为十进制吗?
由于某些原因,当我将这个JSON发送到一个操作时:
{"BaseLoanAmount": 5000}
这个属性应该绑定到一个名为“BaseLoanAmount”的十进制数属性的模型上,但它没有绑定,仍然保持为0。但是,如果我发送:
{"BaseLoanAmount": 5000.00}
它确实绑定了属性,但为什么呢?即使它没有小数,难道5000不能被转换为十进制吗?
进入asp.net mvc源代码后,看起来问题在于转换时使用了框架的类型转换器,但由于某些原因,int到decimal的转换会返回false。最终我使用了自定义模型绑定提供程序和模型绑定器来处理decimal类型,你可以在这里看到:
public class DecimalModelBinder : DefaultModelBinder
{
#region Implementation of IModelBinder
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult.AttemptedValue.Equals("N.aN") ||
valueProviderResult.AttemptedValue.Equals("NaN") ||
valueProviderResult.AttemptedValue.Equals("Infini.ty") ||
valueProviderResult.AttemptedValue.Equals("Infinity") ||
string.IsNullOrEmpty(valueProviderResult.AttemptedValue))
return 0m;
return Convert.ToDecimal(valueProviderResult.AttemptedValue);
}
#endregion
}
为了注册此 ModelBinder,只需在 Application_Start()
函数中添加以下代码:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
尝试按照以下方式发送:
{ "BaseLoanAmount": "5000" }
return
语句中的布尔表达式valueProviderResult==null
不能评估为真,因为在之前,valueProviderResult.AttemptedValue
会抛出一个空引用异常。为了让内容更加通俗易懂,可以将其翻译为:“由于在valueProviderResult.AttemptedValue
之前可能会出现空引用异常,因此在return
语句中的布尔表达式valueProviderResult==null
不能为真。” - DiegovalueProviderResult.RawValue == null
来确定是否分配类型的默认值。 - MattvalueProviderResult
是否为null
,以避免NullReferenceException
,否则基础绑定将永远不会发生。然后,应该首先检查string.IsNullOrEmpty(valueProviderResult.AttemptedValue)
,因为在当前实现中它也会导致NullReferenceException
。此外,最好检查-Infinity
值。 - Eadel