Asp.net mvc MVC3不引人注目的输入验证组

Asp.net mvc MVC3不引人注目的输入验证组,asp.net-mvc,asp.net-mvc-3,Asp.net Mvc,Asp.net Mvc 3,我需要验证3个或更多输入字段(至少需要一个)。例如,我有电子邮件、传真、电话 我要求至少填写一份。我需要服务器和客户端的“不引人注目的验证”。请帮忙。我研究了“比较”方法并试图修改它,但没有成功。请帮忙。 谢谢既然您使用的是MVC 3,请看一看Brad Wilson在mvcConf上的表现。创建客户端+服务器非干扰性验证所需的一切都有了您可以编写一个自定义属性: public class AtLeastOneRequiredAttribute : ValidationAttribute, ICl

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

我要求至少填写一份。我需要服务器和客户端的“不引人注目的验证”。请帮忙。我研究了“比较”方法并试图修改它,但没有成功。请帮忙。
谢谢

既然您使用的是MVC 3,请看一看Brad Wilson在mvcConf上的表现。创建客户端+服务器非干扰性验证所需的一切都有了

您可以编写一个自定义属性:

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;
    }
}
然后是一个简单的控制器:

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

    [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(
        '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" />
}
@model MyViewModel
jQuery.validator.unobtrusive.adapters.add(
'atleastonerequired',['properties'],函数(选项){
options.rules['atleastonerequired']=options.params;
options.messages['atleastonerequired']=options.message;
}
);
jQuery.validator.addMethod('atleastonerequired',函数(值、元素、参数){
var properties=params.properties.split(',');
var值=$.map(属性、函数(属性、索引){
var val=$('#'+属性).val();
返回val!=''?val:null;
});
返回值.length>0;
}, '');
@使用(Html.BeginForm())
{
@Html.ValidationSummary(false)
@LabelFor(x=>x.Email)
@EditorFor(x=>x.Email)
@LabelFor(x=>x.Fax)
@Html.EditorFor(x=>x.Fax)
@LabelFor(x=>x.Phone)
@EditorFor(x=>x.Phone)
}

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

我花了36个多小时来解释为什么代码不适合我。。最后,我发现在我的例子中,我不应该在这行代码中使用属性名

[AtLeastOneRequired("Email", "Fax", "Phone", ErrorMessage = "At least Email, Fax or Phone is required")]
但是我不得不使用HTMl元素ID来代替属性名,这就像魔术一样


如果这可能对某人有所帮助,请将其发布在此处。

@Darin Dimitrov的解决方案可能是创建自定义验证属性的标准,该属性可用于不引人注目的验证。但是,使用自定义验证属性进行不引人注目的验证有一些缺点,例如:

  • 自定义验证属性仅附加到一个属性,因此如果在其他两个输入上发生更改事件,则客户端验证将不起作用
  • 错误消息与ValidationSummary配合得很好,但是如果您想为整个组显示一条错误消息(我认为这是正常的),这几乎是不可能的
  • 为了避免第一个问题,我们可以向组中的每个元素添加自定义验证属性,这将导致另一个问题:我们必须验证组中的所有元素,而不是在第一个无效的组元素处停止。当然,第二个问题——每个元素都有单独的错误消息——仍然存在
还有另一种处理输入组的客户端验证的方法,使用jqueryvalidator()中的groups设置。唯一的问题(也是一个大问题)是,默认情况下,不引人注目的验证不支持jquery验证的组,因此我们必须定制一点

虽然这个答案很难做到“不引人注目”,但在我看来,如果您的最终目标是在使用Microsoft的“不引人注目的验证程序库”时验证一组输入,那么尝试消除代码中不必要的复杂性是值得的

首先,由于默认jquery验证器的组设置在jquery unobtrusive validator中不可用,我们必须覆盖unobtrusive设置(ref.)

之后,覆盖不引人注目的验证器的组、规则和errorPlacement设置

var validationSettings = {
groups: {
    checkboxgroup: "Email Fax Phone"
},
rules: {
    Email: {
        required: function () {
            return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]);
        }
    },
    Fax: {
        required: function () {
            return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]);
        }
    },
    Phone: {
        required: function () {
            return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]);
        }
    }
}
,
errorPlacement: function (error, element, fnUnobtrusive, form) {
    switch (element.attr("name")) {
        case "Email":
        case "Fax":
        case "Phone":
            onGroupError(error, "CheckBoxGroup", form);
            break;
        default:
            fnUnobtrusive(error, element);
            break;
    }
}
}

function validateCheckboxGroup(names) {
var result = true;
$.each(names, function (index, value) {
    if ($(value).is(":checked")) {
        result = false;
    }
});
return result;
}
由于unobtrusive validator没有实现jquery validator的组设置,我们需要重用两个库中的两个函数:(1)拆分组名(重用jquery validator中的代码)和(2)在不删除“input validation error”类的情况下追加错误元素(重用unobtrusive库中的函数onError)

最后,使用HtmlExtensions.ValidationMessage创建复选框组的错误范围

@Html.ValidationMessage("CheckBoxGroup", new { @class = "text-danger" }) 

保留“InputValidationError”类是必要的,这样jQueryValidator将作为一个整体验证复选框组的所有3个元素(电子邮件、电话、传真),而不是逐个验证。默认情况下,不引人注目的验证库会在函数onError上删除此类,因此我们必须按照上面的函数onGroupError中所示进行自定义。

这非常有帮助。谢谢出于某些原因,客户端验证不会启动:(.??@Shane Km,web.config中的
ClientValidationEnabled
属性是否设置为true?还要确保您使用的是与jquery兼容的jquery.validate插件版本。有一个旧版本与jquery 1.5不兼容。此处的验证仅附加到电子邮件。如果只有传真或电子邮件,如何启动验证是否输入了电话?如果填写传真然后删除,验证将不会启动。我不太确定这里的示例中的实现是如何工作的。唯一可行的方法是在其中一个属性上添加属性,如so
[MultiFieldRequired(新字符串[3]{“Phone1”、“Phone2”、“Phone3”},ErrorMessage=“Phone#required”)]
----代码只接受数组。我不确定人们是如何使用这些逗号分隔的字符串并使其工作的。您必须编写自定义验证器以及一些js,从这里开始
var validationSettings = {
groups: {
    checkboxgroup: "Email Fax Phone"
},
rules: {
    Email: {
        required: function () {
            return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]);
        }
    },
    Fax: {
        required: function () {
            return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]);
        }
    },
    Phone: {
        required: function () {
            return validateCheckboxGroup(["#Email", "#Fax", "#Phone"]);
        }
    }
}
,
errorPlacement: function (error, element, fnUnobtrusive, form) {
    switch (element.attr("name")) {
        case "Email":
        case "Fax":
        case "Phone":
            onGroupError(error, "CheckBoxGroup", form);
            break;
        default:
            fnUnobtrusive(error, element);
            break;
    }
}
}

function validateCheckboxGroup(names) {
var result = true;
$.each(names, function (index, value) {
    if ($(value).is(":checked")) {
        result = false;
    }
});
return result;
}
function initGroups(validators) {
validators.groups = {};
$.each(validators.settings.groups,
    function (key, value) {
        if (typeof value === "string") {
            value = value.split(/\s/);
        }
        $.each(value,
            function (index, name) {
                validators.groups[name] = key;
            });
    });
}

function onGroupError(error, inputElementName, form) {
var container = $(form).find("[data-valmsg-for='" + inputElementName + "']"),
replaceAttrValue = container.attr("data-valmsg-replace"),
replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;

container.removeClass("field-validation-valid").addClass("field-validation-error");
error.data("unobtrusiveContainer", container);

if (replace) {
    container.empty();
    error.appendTo(container);
}
else {
    error.hide();
}
}
@Html.ValidationMessage("CheckBoxGroup", new { @class = "text-danger" })