15

我的表单具有默认帮助文本的输入,可指导用户输入内容(而不是使用标签)。这使得验证变得棘手,因为输入值永远不会为空。

如何扩展不显眼的验证来处理这个问题?如果名称输入等于“请输入您的姓名...”,则该表单应该无效

我开始阅读Brad Wilson 关于验证适配器的博客文章,但我不确定这是否是正确的方法?我需要能够根据字段验证不同的默认值。

谢谢

4

6 回答 6

34

这是一个示例,说明如何继续实现自定义验证属性:

public class NotEqualAttribute : ValidationAttribute, IClientValidatable
{
    public string OtherProperty { get; private set; }
    public NotEqualAttribute(string otherProperty)
    {
        OtherProperty = otherProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var property = validationContext.ObjectType.GetProperty(OtherProperty);
        if (property == null)
        {
            return new ValidationResult(
                string.Format(
                    CultureInfo.CurrentCulture, 
                    "{0} is unknown property", 
                    OtherProperty
                )
            );
        }
        var otherValue = property.GetValue(validationContext.ObjectInstance, null);
        if (object.Equals(value, otherValue))
        {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return null;
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessage,
            ValidationType = "notequalto",
        };
        rule.ValidationParameters["other"] = OtherProperty;
        yield return rule;
    }
}

然后在模型上:

public class MyViewModel
{
    public string Prop1 { get; set; }

    [NotEqual("Prop1", ErrorMessage = "should be different than Prop1")]
    public string Prop2 { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel
        {
            Prop1 = "foo",
            Prop2 = "foo"
        });
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

并查看:

@model MyViewModel

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
<script type="text/javascript">
    jQuery.validator.unobtrusive.adapters.add(
        'notequalto', ['other'], function (options) {
            options.rules['notEqualTo'] = '#' + options.params.other;
            if (options.message) {
                options.messages['notEqualTo'] = options.message;
            }
    });

    jQuery.validator.addMethod('notEqualTo', function(value, element, param) {
        return this.optional(element) || value != $(param).val();
    }, '');
</script>

@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(x => x.Prop1)
        @Html.EditorFor(x => x.Prop1)
        @Html.ValidationMessageFor(x => x.Prop1)
    </div>
    <div>
        @Html.LabelFor(x => x.Prop2)
        @Html.EditorFor(x => x.Prop2)
        @Html.ValidationMessageFor(x => x.Prop2)
    </div>
    <input type="submit" value="OK" />
}
于 2011-04-21T10:01:23.233 回答
3

是的,这是正确的方法。您应该实现自己的属性并实现IClientValidatable.

您还可以将所需的布尔值最初设置false为隐藏的表单字段。当用户更改文本框时,将其设置为 true。

于 2011-04-20T21:20:55.460 回答
0

您可以让您的 ViewModel 实现 IValidatableObject,并在实现 Validate 方法(来自 IValidatableObject)时添加一些逻辑来检查属性的值,例如

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
        var results = new List<ValidationResult>();

        if (Name == "Please enter your name...") 
            results.Add(new ValidationResult("You must enter a name");

        ...
        Enter other validation here
        ...     

        return results;
    }

现在,当在您的控制器中调用 Model.IsValid 时,将运行这部分逻辑并正常返回验证错误。

于 2011-04-21T09:31:08.033 回答
0

自从提出您的问题以来,花了一点时间,但是如果您仍然喜欢数据注释,则可以使用此库轻松解决此问题:

[Required]
[AssertThat("FieldA != 'some text'")]
public string FieldA { get; set; }

上面,字段值与一些预定义的文本进行了比较。或者,您可以相互比较字段值:

[AssertThat("FieldA != FieldB")]

...并且当比较字符串的情况无关紧要时:

[AssertThat("CompareOrdinalIgnoreCase(FieldA, FieldB) != 0")]
于 2014-07-17T21:28:21.297 回答
0

为了改进@Darin Dimitrov 的答案,如果你想从资源中添加消息ErrorMessageResourceName and ErrorMessageResourceType,只需将其添加到错误消息中ErrorMessage = ErrorMessage ?? ErrorMessageString

ErrorMessageString 将查找您使用这些参数(ErrorMessageResourceName 和 ErrorMessageResourceType)在模型中设置的错误消息的本地化版本

于 2016-01-18T18:39:20.813 回答
-1

理想的解决方案是自定义属性,您可以在其中指定最小和最大长度以及 MustNotContain="请输入您的姓名..."。

于 2011-04-20T22:03:48.507 回答