MVC3不显眼的验证组输入

Sha*_*eKm 43 asp.net-mvc asp.net-mvc-3

我需要验证3个或更多输入字段(至少需要一个).例如,我有电子邮件,传真,电话.

我需要至少填写一个.我需要服务器和客户端'不显眼的验证'.请帮忙.我查看了"比较"方法并尝试修改它但没有运气.请帮忙.谢谢

Dar*_*rov 85

您可以编写自定义属性:

public class AtLeastOneRequiredAttribute : ValidationAttribute, IClientValidatable
{
    private readonly string[] _properties;
    public AtLeastOneRequiredAttribute(params string[] properties)
    {
        _properties = properties;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (_properties == null || _properties.Length < 1)
        {
            return null;
        }

        foreach (var property in _properties)
        {
            var propertyInfo = validationContext.ObjectType.GetProperty(property);
            if (propertyInfo == null)
            {
                return new ValidationResult(string.Format("unknown property {0}", property));
            }

            var propertyValue = propertyInfo.GetValue(validationContext.ObjectInstance, null);
            if (propertyValue is string && !string.IsNullOrEmpty(propertyValue as string))
            {
                return null;
            }

            if (propertyValue != null)
            {
                return null;
            }
        }

        return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ErrorMessage = ErrorMessage,
            ValidationType = "atleastonerequired"
        };
        rule.ValidationParameters["properties"] = string.Join(",", _properties);

        yield return rule;
    }
}
Run Code Online (Sandbox Code Playgroud)

可用于装饰您的一个视图模型属性(如果验证失败,您希望突出显示该属性):

public class MyViewModel
{
    [AtLeastOneRequired("Email", "Fax", "Phone", ErrorMessage = "At least Email, Fax or Phone is required")]
    public string Email { get; set; }
    public string Fax { get; set; }
    public string Phone { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后是一个简单的控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel();
        return View(model);
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}
Run Code Online (Sandbox Code Playgroud)

呈现以下视图,该视图将负责定义自定义客户端验证器适配器:

@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(
        'atleastonerequired', ['properties'], function (options) {
            options.rules['atleastonerequired'] = options.params;
            options.messages['atleastonerequired'] = options.message;
        }
    );

    jQuery.validator.addMethod('atleastonerequired', function (value, element, params) {
        var properties = params.properties.split(',');
        var values = $.map(properties, function (property, index) {
            var val = $('#' + property).val();
            return val != '' ? val : null;
        });
        return values.length > 0;
    }, '');
</script>

@using (Html.BeginForm())
{
    @Html.ValidationSummary(false)

    <div>
        @Html.LabelFor(x => x.Email)
        @Html.EditorFor(x => x.Email)
    </div>

    <div>
        @Html.LabelFor(x => x.Fax)
        @Html.EditorFor(x => x.Fax)
    </div>

    <div>
        @Html.LabelFor(x => x.Phone)
        @Html.EditorFor(x => x.Phone)
    </div>

    <input type="submit" value="OK" />
}
Run Code Online (Sandbox Code Playgroud)

当然,自定义适配器和验证器规则应该外部化为单独的javascript文件,以避免将脚本与标记混合.

  • @Shane Km,是否在web.config中将`ClientValidationEnabled`属性设置为true?还要确保您使用的是与jquery兼容的jquery.validate插件版本.有一个与jQuery 1.5不兼容的旧版本. (2认同)
  • 此处的验证仅附加到电子邮件.如果仅输入传真或电话,验证如何触发?如果填写了传真然后删除,则验证不会触发. (2认同)

Bal*_*dar 5

我花了36个多小时为什么代码对我不起作用..最后,我发现在我的情况下,我不应该在这行代码中使用属性名称

[AtLeastOneRequired("Email", "Fax", "Phone", ErrorMessage = "At least Email, Fax or Phone is required")]
Run Code Online (Sandbox Code Playgroud)

但我必须使用HTMl元素ID来代替属性名称,它就像魔法一样.

如果这对某人有帮助,可以在这里发布.