Подтвердить что ты не робот

MVC3 ненавязчивая группа валидации

Мне нужно проверить 3 или более полей ввода (требуется только для одного). Например, у меня есть электронная почта, факс, телефон.

Мне нужно заполнить хотя бы ОДИН. Мне нужна "ненавязчивая проверка" сервера и клиента. пожалуйста помоги. Я изучил метод "Сравнить" и попытался изменить его, но не повезло. пожалуйста помоги. спасибо

4b9b3361

Ответ 1

Вы можете написать собственный атрибут:

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

а затем простой контроллер:

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" />
}

Конечно, пользовательское правило адаптера и валидатора должно быть выведено в отдельный файл javascript, чтобы избежать смешивания script с разметкой.

Ответ 2

Я потратил более 36 часов, почему код не работал у меня. В конце я узнал, что в моем случае я не должен был использовать имена свойств в этой строке кода

[AtLeastOneRequired("Email", "Fax", "Phone", ErrorMessage = "At least Email, Fax or Phone is required")]

Но мне пришлось использовать идентификаторы элементов HTMl вместо имен свойств, и он работал как магия.

Проводя это здесь, если это может помочь кому-то.

Ответ 3

Поскольку вы используете MVC 3, посмотрите отличное видео Брэд Уилсон был на mvcConf. Там все, что вам нужно для создания клиента + сервер Ненавязчивая проверка

Ответ 4

Решение @Darin Kimitrov, вероятно, является стандартом создания специального атрибута проверки, который работает с ненавязчивой проверкой. Однако использование пользовательских атрибутов проверки для ненавязчивой проверки имеет некоторые недостатки, такие как:

  • Пользовательский атрибут проверки привязан только к одним свойствам, поэтому проверка клиента не будет работать, если на других двух входах есть событие изменения.
  • Сообщение об ошибке отлично работает с ValidationSummary, но если вы хотите отобразить 1 сообщение об ошибке для всей группы (что, я думаю, является нормой), это было бы почти невозможно.
  • Чтобы избежать первой проблемы, мы можем добавить специальный атрибут проверки для каждого элемента в группе, что вызовет еще одну проблему: мы должны проверить все элементы группы, а не останавливаться на первом недопустимом элементе группы. И, конечно же, вторая проблема - отдельные сообщения об ошибках для каждого элемента - все еще остается.

Существует еще один способ обработки клиентской проверки группы входов, используя группы, установленные в валидаторе jquery (https://jqueryvalidation.org/validate/#groups). Единственная проблема (и большая) заключается в том, что ненавязчивая проверка не поддерживает по умолчанию группы проверки jQuery, поэтому нам нужно немного настроить.

Хотя этот ответ вряд ли "ненавязчивый", на мой взгляд, стоит попытаться избавиться от ненужного усложнения кода, если ваша конечная цель - проверить группу входов при использовании ненавязчивой библиотеки проверки подлинности Microsoft.

Во-первых, поскольку настройки групп по умолчанию для проверки подлинности jquery недоступны в jQuery-ненавязчивом валидаторе, мы должны переопределить ненавязчивые настройки (ссылка Как настроить ненавязчивую проверку в ASP.NET MVC 3 соответствует моему стилю?)

$("form").on('submit', function () {
    var form = this;
    var validator = $(this).data("validator");

    if (validator.settings && !validator.settings.submitHandler) {
        $.extend(true, validator.settings.rules, validationSettings.rules);
        $.extend(true, validator.settings.groups, validationSettings.groups);
        initGroups(validator);

        var fnErrorReplacement = validator.settings.errorPlacement;
        validator.settings.errorPlacement = function (error, element) {
            validationSettings.errorPlacement(error, element, fnErrorReplacement, form);
        }
        validator.settings.submitHandler = formSubmitHandler;
    }
});

function formSubmitHandler(form) {
    form.submit();
}

После этого переопределите ненавязчивые группы валидаторов, правила и параметры настройки ошибки.

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

Поскольку ненавязчивый валидатор не реализует настройки групп для jquery validator, нам нужно повторно использовать две функции из двух библиотек, чтобы: (1). имена групп .split(повторное использование кода из jquery validator) и (2) добавить элемент ошибки без удаления класс "input-validation-error" (повторное использование функции onError из ненавязчивой библиотеки).

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

Наконец, используйте HtmlExtensions.ValidationMessage для создания диапазона ошибок группы флажков.

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

Необходимо соблюдать класс "проверка правильности ввода-ошибки", поэтому валидатор jquery будет проверять все 3 элемента (электронная почта, телефон, факс) группы флажков в целом, вместо проверки по одному. Ненавязчивая библиотека проверки удаляет этот класс по умолчанию в функции onError, поэтому мы должны настроить это, как показано в функции onGroupError выше.

Ответ 5

Я отправил ответ здесь question, который похож на этот. Мое решение является более естественным способом использования require_from_group (смотрите этот folder) метод, созданный командой проверки запроса.

Решение является общим, потому что оно работает для каждого типа input, textarea и select. Вы также можете указать количество необходимых полей, которые необходимо заполнить для действительного действи.

Надеюсь, что это поможет!