Настраиваемый атрибут проверки MVC 3 для нескольких флажков - PullRequest
0 голосов
/ 29 февраля 2012

Я делаю проверку на длинную форму, используя пользовательский атрибут.Одним из входящих полей является длинная серия флажков, которые я использую, чтобы позволить пользователям устанавливать несколько значений для соответствующего поля базы данных (я знаю, что мог бы использовать MultiSelectList, но я не большой поклонник их).Затем я собираю различные значения флажков в методе POST ActionResult в одну строку перед загрузкой в ​​базу данных.Эта часть работает хорошо.

Но мне нужно проверить, что они отметили хотя бы один флажок (т.е. само значение базы данных не может быть нулевым).Поэтому я написал собственный атрибут проверки, который проверяет наличие каждого флажка, и если хотя бы один из них присутствует, он проходит проверку.Вот код, который я написал для самой проверки:

public class ConfirmLAAttribute : ValidationAttribute
{
    public ConfirmLAAttribute()
    {
    }

    protected override ValidationResult IsValid(Object value, ValidationContext validationContext)
    {
        string lAppTest = String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAAccent") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAShade") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAArticulation") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAMassing") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAScreening") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LARock") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAEdging") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAWindbreak") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAGroundcover") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LANaturalizing") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAOrchard") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LATopiary") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAHerb") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LAContainer") != null) ? "X" : String.Empty;
        lAppTest += (validationContext.ObjectType.GetProperty("LABog") != null) ? "X" : String.Empty;

        if (String.IsNullOrEmpty(lAppTest)) {
            return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
        }
        return ValidationResult.Success;
    }
}

Я вызываю проверку как атрибут в модели представления:

[ConfirmLA(ErrorMessage = "You must select at least one Landscape Application!")]
public string Landscape_Application { get; set; }

HTML-код в модели представленияпросто повторение:

<input type="checkbox" name="LAAccent" value="true" /> Accent/Feature<br />

внутри таблицы (т.е. это 15 раз, по одному на каждый флажок).

Проблема в том, что это всегда выдает ошибку.Я отлаживал внутри самого кода проверки, и он не распознает ни один из флажков по именам их свойств.Другими словами, каждый из них:

lAppTest += (validationContext.ObjectType.GetProperty("LAAccent") != null) ? "X" : String.Empty;

преобразуется в ноль, даже если флажок был установлен.Я также подтвердил, что проверенные значения обязательно присутствуют в FormCollection в ActionResult.Как будто у меня неправильный синтаксис или что-то в этом роде, например, метод GetProperty не находит эти флажки по именам их свойств.Что я здесь не так делаю?

Ответы [ 2 ]

4 голосов
/ 29 февраля 2012

Измените свою модель представления на

[Required(ErrorMessage = "You must select at least one Landscape Application!")]
public ICollection<string> LandscapeServices { get; set; }

Измените свой HTML-код на

<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAAccent" /> Accent/Feature<br />
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAShade" /> Accent/Feature<br />
<input type="checkbox" class="required-checkbox" name="LandscapeServices" value="LAArticulation" /> Accent/Feature<br />
/*etc etc*/

Когда вы нажмете "Отправить", все выбранные значения будут добавлены в свойство LandscapeServices.

Обратите внимание, что это будет работать только для проверки на стороне сервера.Если вы хотите выполнить проверку на стороне клиента, вам нужно создать расширение для Required с вашей собственной функцией проверки JavaScript.

EDIT - чтобы адресовать комментарий @ ScubaSteve о проверке на стороне клиента от SO answer

$(function(){
    $.validator.addMethod('required_group', function(value, element) {
        var $module = $(element).parents('form');
        return $module.find('input.checkbox:checked').length;
    }, 'Select at least one Service please');
    $.validator.addClassRules('required-checkbox', { 'required_group' : true });
0 голосов
/ 29 февраля 2012

Я бы не использовал атрибут для этого, если бы вы не хотели выполнять проверку на стороне клиента.Вместо этого я просто сделал бы вашу модель производной от IValidatableObject и выполнил валидацию в методе IsValid этого.Гораздо проще и без позднего связывания.

...