我为一个十进制数字抛出了一个自定义ModelBinder
,它应该在发布一个值时考虑当前用户的小数点分隔符。
一切都按预期工作,除了一件事:如果我发布一个空值,基本的Required
验证器将不会触发,而是它将正常执行我的代码,并抛出一个{{1}然后由FormatException
转换为ModelState错误。
在查看source code for DefaultModelBinder时,我可以看到方法DefaultModelBinder
中的SetProperty
属性被考虑在内,但我不知道如何使用自己的粘合剂。
以下是验证器的代码:
的Global.asax.cs:
Required
DecimalModelBinder.cs:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
最后我的观点模型:
public class DecimalModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
var modelState = new ModelState {Value = valueResult};
object result = null;
var modelName = bindingContext.ModelName;
var attemptedValue =
bindingContext.ValueProvider.GetValue(modelName).AttemptedValue;
// Depending on CultureInfo, the NumberDecimalSeparator can be "," or "."
// Both "." and "," should be accepted, but aren't.
var wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator;
var alternateSeperator = (wantedSeperator == "," ? "." : ",");
if (attemptedValue.IndexOf(wantedSeperator, StringComparison.Ordinal) == -1
&& attemptedValue.IndexOf(alternateSeperator, StringComparison.Ordinal) != -1)
{
attemptedValue =
attemptedValue.Replace(alternateSeperator, wantedSeperator);
}
try
{
if (!(bindingContext.ModelMetadata.IsNullableValueType
&& string.IsNullOrWhiteSpace(attemptedValue)))
result = decimal.Parse(attemptedValue, NumberStyles.Any);
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return result;
}
}