自定义验证属性 - 有效整数
Posted
技术标签:
【中文标题】自定义验证属性 - 有效整数【英文标题】:Custom Validation Attribute - Valid Integer 【发布时间】:2014-08-11 10:29:11 【问题描述】:我有一个奇怪的要求。
我有一个类,上面有 2 个属性,如下所示:
public class MyViewModel
[EnhancedServiceValidInteger("Name")]
public int NumberOfItems get; set;
public string Name get; set;
上面的类用作动态字段,用于构建动态表单。当 NumberOfItems 不正确(不是有效整数)时,应使用 Name 属性中的值作为 DisplayName 来显示错误消息,并且是任何错误消息的输出。
我已经实现了一个触发的自定义验证属性,但是如果用户输入一个字母,我希望该属性能够接收该字母。在这种情况下 (IsValid(object value, ...)) IsValid 方法值属性始终为 0,因此验证通过并且 MyCustomValidIntegerValidator 中没有断点被命中。如果这是在 UI 中输入的值,为什么不将值设置为“aaa”?
有人可以帮忙吗?
我有以下自定义验证属性:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
public class MyCustomValidInteger : ValidationAttribute
private readonly string _validationNameFromProperty;
public EnhancedServiceValidInteger(string validationNameFromProperty) : base("0 contains invalid character.")
_validationNameFromProperty = validationNameFromProperty;
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
// the the other property
var property = validationContext.ObjectType.GetProperty(_validationNameFromProperty);
// check it is not null
if (property == null)
return new ValidationResult(String.Format("Unknown property: 0.", _validationNameFromProperty));
// get the other value
var nameToUse = property.GetValue(validationContext.ObjectInstance, null).ToString();
if (value == null || value.ToString().Length == 0)
return ValidationResult.Success;
int i;
var errorMessage = string.Format("The value '0' is not valid for 1", value, nameToUse);
ValidationResult validationResult = !int.TryParse(value.ToString(), out i) ? new ValidationResult(errorMessage) : ValidationResult.Success;
return validationResult;
这是上述类的 DataAnnotationsModelValidator 实现:
public class MyCustomValidIntegerValidator : DataAnnotationsModelValidator<MyCustomValidInteger>
public MyCustomValidIntegerValidator(ModelMetadata metadata, ControllerContext context, EnhancedServiceValidInteger attribute)
: base(metadata, context, attribute)
if (!attribute.IsValid(context.HttpContext.Request.Form[metadata.PropertyName]))
var propertyName = metadata.PropertyName;
context.Controller.ViewData.ModelState[propertyName].Errors.Clear();
context.Controller.ViewData.ModelState[propertyName].Errors.Add(attribute.ErrorMessage);
【问题讨论】:
如果您使用通常的EditorFor()
html 帮助程序创建输入字段,请注意它也会使用required
创建一个type="number"
输入。如果您在其中输入字母,某些浏览器将不会返回值。
感谢 Tallmaris,我正在使用 @Html.TextboxFor(...)。
【参考方案1】:
至于为什么,当表单值回传到控制器时,DefaultModelBinder
首先将值绑定到属性(使用PropertyDescriptor
的SetValue()
方法)。由于属性是int
,值是string
,所以不能设置,分配默认值。直到此绑定完成,验证过程才开始。
不确定如何实现您想要的,但创建自定义 ModelBinder
可能是一种选择
【讨论】:
谢谢斯蒂芬,我会看看模型活页夹 您可能还需要将CustomModelBinderAttribute
应用于属性NumberOfItems
,它告诉ModelBinder
仅将您的自定义ModelBinder
用于此属性(您可能不想应用它到 int
) 类型的所有属性
你有例子吗?我的 Google-Fu 让我失望了
对不起,不是这种情况,但ModelBinder
有很多方法可以覆盖,例如OnModelUpdating()
,您应该能够在绑定之前获取发布的值,OnPropertyValidating()
发生在之前可能允许您改变行为的验证以上是关于自定义验证属性 - 有效整数的主要内容,如果未能解决你的问题,请参考以下文章