c# - int 数据类型的服务器端验证

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

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

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;。为什么?

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

最佳答案

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

下面是这种模型 Binder 的样子:

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());

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

嗯,这很简单。您可以创建一个自定义属性,它将用于装饰您的 View 模型并将包含错误消息,并且在模型 Binder 中您将能够获取此错误消息并改用它。

因此,您可以拥有一个虚拟验证器属性:

public class MustBeAValidInteger : ValidationAttribute, IMetadataAware
{
    public override bool IsValid(object value)
    {
        return true;
    }

    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.AdditionalValues["errorMessage"] = ErrorMessage;
    }
}

你可以用来装饰你的 View 模型:

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

并调整模型 Binder :

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;
    }
}

关于c# - int 数据类型的服务器端验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9921067/

相关文章:

c# - 我可以停止 .NET 吃掉 ID 吗?

c# - 如何抛出 HTTP 错误?

C#线程问题

c# - 主题页面错误中的 ELMAH

c# - 检查 pst 文件是否受密码保护

asp.net - 找不到指定文化或中性文化的任何资源

c# - 将 SqlConnection 传递给类会在处理后丢失其连接字符串

c# - 我如何让 TestDriven.net 使用 NCover 生成有用的代码覆盖率 XML 文件?

c# - ASP.Net 页面输入键导致回发

c# - 网页中dll的弹出控件