【问题标题】:Server side validation of int datatypeint 数据类型的服务器端验证
【发布时间】:2012-04-12 20:17:30
【问题描述】:

我制作了自定义验证器属性

partial class DataTypeInt : ValidationAttribute
{
    public DataTypeInt(string resourceName)
    {
        base.ErrorMessageResourceType = typeof(blueddPES.Resources.PES.Resource);
        base.ErrorMessageResourceName = resourceName;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        string number = value.ToString().Trim();
        int val;
        bool result = int.TryParse(number,out val );
        if (result)
        {
            return ValidationResult.Success;
        }
        else 
        {
            return new ValidationResult("");
        }
    }
}

但是当我在我的文本框中输入字符串而不是 int 值时,然后是 value==null,当我输入 int 值时,然后是 value==entered value;。为什么?

是否有任何替代方法可以实现相同的效果(确保仅在服务器端)

【问题讨论】:

    标签: c# asp.net .net asp.net-mvc-3 validation


    【解决方案1】:

    发生这种情况的原因是模型绑定器(在任何验证器之前运行)无法将无效值绑定到整数。这就是为什么在你的验证器中你没有得到任何价值。如果您希望能够验证这一点,您可以为整数类型编写自定义模型绑定器。

    这种模型绑定器的外观如下:

    public class IntegerBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            int temp;
            if (value == null || 
                string.IsNullOrEmpty(value.AttemptedValue) || 
                !int.TryParse(value.AttemptedValue, out temp)
            )
            {
                bindingContext.ModelState.AddModelError(bindingContext.ModelName, "invalid integer");
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
                return null;
            }
    
            return temp;
        }
    }
    

    您将在Application_Start注册它:

    ModelBinders.Binders.Add(typeof(int), new IntegerBinder());
    

    但您可能会问:如果我想自定义错误消息怎么办?毕竟,这就是我最初想要实现的目标。当默认的模型绑定器已经为我这样做时,编写此模型绑定器有什么意义,只是我无法自定义错误消息?

    嗯,这很容易。您可以创建一个自定义属性,用于装饰您的视图模型并包含错误消息,并且在模型绑定器中,您将能够获取此错误消息并使用它。

    所以,你可以有一个虚拟的验证器属性:

    public class MustBeAValidInteger : ValidationAttribute, IMetadataAware
    {
        public override bool IsValid(object value)
        {
            return true;
        }
    
        public void OnMetadataCreated(ModelMetadata metadata)
        {
            metadata.AdditionalValues["errorMessage"] = ErrorMessage;
        }
    }
    

    你可以用来装饰你的视图模型:

    [MustBeAValidInteger(ErrorMessage = "The value {0} is not a valid quantity")]
    public int Quantity { get; set; }
    

    并调整模型绑定器:

    public class IntegerBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            int temp;
            var attemptedValue = value != null ? value.AttemptedValue : string.Empty;
    
            if (!int.TryParse(attemptedValue, out temp)
            )
            {
                var errorMessage = "{0} is an invalid integer";
                if (bindingContext.ModelMetadata.AdditionalValues.ContainsKey("errorMessage"))
                {
                    errorMessage = bindingContext.ModelMetadata.AdditionalValues["errorMessage"] as string;
                }
                errorMessage = string.Format(errorMessage, attemptedValue);
                bindingContext.ModelState.AddModelError(bindingContext.ModelName, errorMessage);
                bindingContext.ModelState.SetModelValue(bindingContext.ModelName, value);
                return null;
            }
    
            return temp;
        }
    }
    

    【讨论】:

    • 我不想构建自定义模型绑定器。我可以将资源文件中的验证消息放入客户端验证中吗?
    • @djCool,服务器端验证呢?这是您在考虑客户端验证之前应该注意的第一件事。完成此操作后,我们就可以讨论客户端了。
    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 2011-06-19
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多