Как заставить мои пользовательские аннотации данных работать (это находится в списке, и каждый элемент в списке переопределяет последний тест проверки) - PullRequest
2 голосов
/ 07 февраля 2011

У меня проблемы с пользовательской проверкой в ​​asp.net mvc 3.0

Что я хочу к этому сделать.

  1. Быть установленным для свойства (сейчас я могу только выяснить, как сделать это в классе)
  2. Будьте достаточно умны, чтобы понять, что используется несколько экземпляров.

Сценарий

  1. textbox (id = "textbox1")
  2. выпадающий список (id = "ddl1")
  3. textbox (id = "textbox2") 4 выпадающий список (id = "ddl2")

значения в выпадающем списке одинаковы. («Дни» и «Минуты»)

Теперь пользователь вводит текстовое поле 30 и выбирает «дни» в ddl1. Затем он печатает в textbox2 10000 и "days" в ddl2. Первый действителен, второй недействителен, поскольку в году всего 365 дней.

Сценарий 2

Пользователь вводит в texbox1 99 и выбирает «минуты» в ddl1. Это, конечно, неверно и должно провалиться.

Так что может быть любая комбинация того, где они могут выбрать правильный день и недопустимое минутное время.

Или оба могут быть действительными

Итак, у меня есть это пока

Моя модель представления

  [ReminderFormat(ErrorMessage =  "test")]
    public class ReminderViewModel
    {
        public List<SelectListItem> DurationTypes { get; set; }
        public DurationTypes SelectedDurationType { get; set; }

        public string ReminderLength { get; set; }
    }

Это будет в списке моделей просмотра и генерирует количество нужных мне

List<ReminderViewModel> viewModel = new List<ReminderViewModel>()
// add ReminderviewModel to this collection

View

// do a for loop through the viewModel (  List<ReminderViewModel> )
// generate a textbox html box and drop down list for each one

аннотация данных

    // set attribute to class for now but I want it on a property but I can't
    // figure out how to get SelectedDurationType  and pass it in. if I have my attribute on ReminderLength 
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]

public class ReminderFormatAttribute : ValidationAttribute
{

    public override bool IsValid(object value)
    {

        var reminderViewModel = (ReminderViewModel)value;


        switch (reminderViewModel.SelectedDurationType)
        {
            case DurationTypes.Days:
                int length = Convert.ToInt32(reminderViewModel.ReminderLength);
                if (length > 30)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            default:
                throw new ArgumentOutOfRangeException();
        }
    }

Задача 1

Итак, как вы можете видеть, у меня есть аннотация к классу, и я предпочитаю иметь ее в свойстве ReminderLength.

Задача 2

Прямо сейчас у меня просто дни в 30, так что меньше набирать (я изменю это позже). Проблема, которую я сейчас нахожу, состоит в том, что если textbox1 содержит 31, это не пройдет мою проверку.

Это правильно. Но если у меня есть textbox2, значение которого равно 1, оно пройдет проверку. Это тоже правильно.

Что не правильно, так это то, что он переопределит первую недействительную проверку. Так что теперь он думает, что все проверки пройдены и входит в мой метод действия. Когда он должен отклонить его и вернуться к представлению и сообщить пользователю, что textbox1 не прошел проверку.

1 Ответ

1 голос
/ 22 июля 2011

Вот что я бы сделал для вашего атрибута проверки:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ReminderFormatAttribute: ValidationAttribute, IClientValidatable
{
    public string DurationProperty { get; set; }

    public ReminderFormatAttribute(string durationProperty)
    {
        DurationProperty = durationProperty;
        ErrorMessage = "{0} value doesn't work for selected duration";
    }

    public override string FormatErrorMessage(string propName)
    {
        return string.Format(ErrorMessage, propName);
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var durationType = validationContext.ObjectType.GetProperty(DurationProperty).GetValue(validationContext.ObjectInstance, null);
        var reminderLength = value;

        // Do your switch statement on durationType here
        // Here is a sample of the correct return values
        switch (durationType)
        {
            case DurationTypes.Days:
                if (reminderLength > 30)
                {
                    return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
                }
                else
                {
                    return null;
                }
        }
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
                      {
                        ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                        ValidationType = "reminderformat",
                      };
        rule.ValidationParameters["durationproperty"] = DurationProperty;
        yield return rule;
    } 
}

Теперь в вашей ViewModel вы можете аннотировать свойство ReminderLength следующим образом:

[ReminderFormat("SelectedDurationType")]
public string ReminderLength { get; set; }

Так я обычно делаю, когда проверка зависит от значения другого свойства. Метод GetClientValidationRules - это серверная часть, которую вам нужно связать с ненавязчивой проверкой клиента с помощью проверки jquery. Проверьте эту ссылку для другого примера ValidationAttribute: http://www.devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-2

Пример на этом сайте также включает в себя написание jQuery, необходимого для проверки клиента

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...