Группы проверки ASP.NET MVC?

У меня есть форма, в которой я хотел бы требовать различные поля в зависимости от того, какая кнопка отправки нажата. Пример: поле A является обязательным, если вы нажимаете кнопку "Отправить" 1, но только поле B требуется, если вы нажимаете кнопку "Отправить" 2. Если бы я все еще использовал веб-формы, я бы назначил разные "группы проверки" для каждой комбинации кнопки / средства проверки. Есть ли способ сделать это в MVC, предпочтительно с аннотациями данных на модели? Я бы предпочел реализовать проверку клиента и сервера с помощью одного решения, но я возьму то, что смогу получить...

Заранее спасибо!

2 ответа

Решение

Как насчет настраиваемого атрибута проверки с включенной проверкой клиента (чтобы вы получили проверку как клиента, так и сервера)? В приведенном ниже решении используется ненавязчивая проверка jQuery. Чтобы использовать это, вам нужно дать всем вашим кнопкам конкретные имена и передать имя атрибуту проверки. Кнопка также должна иметь какое-то значение, чтобы ее можно было отправить обратно (чтобы ее мог проверить код на стороне сервера, т.е. <input type="submit" name="myButton" value="1" />). Я не тестировал этот код, поэтому я не уверен, что он выходит из коробки. Вам может понадобиться сделать несколько модов:

Атрибут проверки для вашей модели:

public class RequiredIfButtonClickedAttribute : ValidationAttribute, IClientValidatable
{
    private RequiredAttribute _innerAttribute = new RequiredAttribute();
    public string ButtonName { get; set; }

    public RequiredIfButtonClickedAttribute(string buttonName)
    {
        ButtonName = buttonName;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if ((value == null && !string.IsNullOrEmpty(HttpContext.Current.Request.Form[ButtonName])))
        {
            if (!_innerAttribute.IsValid(value))
            {
                return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
            }
        }

        return ValidationResult.Success;
    }

    #region IClientValidatable Members

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule() { ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()), ValidationType = "requiredifbuttonclicked" };
        rule.ValidationParameters.Add("buttonname", ButtonName);
        yield return rule;
    }

    #endregion
}

Клиентский скрипт:

/// <reference path="jquery-1.4.4-vsdoc.js" />
/// <reference path="jquery.validate.unobtrusive.js" />

// When a button is clicked remove the clicked button class from all buttons and add it to the on that was clicked
$(":submit").click(function () {
    $(":submit").removeClass('clickedButton');
    $(this).addClass('clickedButton');
});

$.validator.addMethod('requiredifbuttonclicked',
    function (value, element, parameters) {

        // if the condition is true, reuse the existing 
        // required field validator functionality
        if ($(".clickedButton").val("name") === parameters['buttonname'])
            return $.validator.methods.required.call(
              this, value, element, parameters);

        return true;
    }
);

$.validator.unobtrusive.adapters.add(
    'requiredifbuttonclicked',
    ['buttonname'],
    function (options) {
        options.rules['requiredifbuttonclicked'] = {
            buttonname: options.params['buttonname']
        };
        options.messages['requiredifbuttonclicked'] = options.message;
});

И используйте это так:

[RequiredIfButtonClicked("myButtonName")]
public string Name { get; set; }

Вы можете дать одно и то же имя каждой кнопке отправки и разное значение. Затем в вашей модели представления есть свойство с именем типа string. Когда форма отправлена, ее значение будет соответствовать значению нажатой кнопки. Теперь вы можете создать собственный атрибут валидатора, который будет использоваться для украшения вашей модели представления. В его реализации IsValid вы получите экземпляр вашей модели представления и на основании значения специального свойства вы будете выполнять проверки. Это ужасно, я знаю, но DataAnnotations действительно полезны для простых ситуаций проверки, но когда вы начинаете писать приложения реального мира, вы понимаете их ограничения.

Лично я использую FluentValidation.NET, и сценарий, подобный описанному здесь, довольно тривиален для реализации.

Другие вопросы по тегам