Как повторно использовать проверку модели вне контроллера?

#c# #validation #model-view-controller

#c# #проверка #model-view-controller

Вопрос:

Специфическая функциональность проверки модели MVC, которую я хочу использовать, заключается в проверке данных ДО того, как они были назначены свойствам экземпляра объекта.

Например, если у меня есть класс:

 public class Test
{
    [Required(ErrorMessage="Id is required")]
    public int Id { get; set; }

    [Required(ErrorMessage="Name is required")]
    [RegularExpression(Constants.SomeRegex,  ErrorMessage = "Please enter a valid value for Name")]
    public int Name { get; set; }
}
  

Я хочу иметь возможность проверить, что значение, присвоенное ‘Id’, может быть, по крайней мере, присвоено, прежде чем пытаться создать экземпляр. В этом случае это означало бы возможность присвоения целому числу, поэтому значение «ABC» не пройдет проверку.

Конечно, я не могу создать экземпляр Test со значением «ABC» для Id, его нельзя назначить Int32.

Контроллеры MVC реализуют эту функциональность — сообщения об ошибках будут возвращены до того, как экземпляр класса модели может быть создан.

С этой целью я до сих пор пытался использовать System.ComponentModel.Примечания к данным.Валидатор

 public bool IsValid(IDictionary<object, object> data, out OfferConfig offerConfig)
{
    offerConfig = new OfferConfig();

    var context = new ValidationContext(offerConfig, data);
    var results = new List<ValidationResult>();

    return Validator.TryValidateObject(offerConfig, context, results, true);
}
  

И передача экземпляра, реализующего IDictionary

 var dict = new Dictionary<object, object>
{
    {"Id", dataTable.Rows[i][0].ToString()},
    {"Name", dataTable.Rows[i][1].ToString()}
} 
  

Вот так:

 Test testInstance;

bool isValid = IsValid(dict, out testInstance);
  

Но, возможно, средство проверки работает не так, как я ожидаю. Предполагается, что аргумент data является строковым представлением свойств модели? Результаты проверки отображаются так, как если бы значения просто не были назначены, а не были неверными.

Надеюсь, кто-нибудь сможет увидеть, чего я пытаюсь здесь достичь…

Комментарии:

1. Альтернативное решение — сделайте свойство строкой и напишите пользовательский валидатор, чтобы проверить, что строка может быть преобразована в целое число. Затем напишите другое свойство, которое вернет значение в виде целого числа для использования в контроллере.

2. Это хорошее предложение, но я предполагаю, что то, что я пытаюсь сделать, должно быть возможным, поскольку это делает MVC. Если я могу избежать создания второго класса, это было бы лучше (свойства должны оставаться в текущих типах данных по причинам, которые я не буду здесь описывать)

3. Я не уверен, что вы имеете в виду — если значение не будет привязано к свойству, свойство просто примет значение по умолчанию (если только фреймворк не считает, что он может его привязать, и произойдет сбой, что является сценарием исключения), кроме того (для реальных сценариев проверки) значения присваиваются модели, но Model.IsValid имеют значение false — способ отразить это с помощью строкового свойства и пользовательского средства проверки.

4. Итак, в приведенном выше примере, если бы я попытался отправить форму в действие контроллера, а значением для id было ‘abc’, MVC вернул бы ошибку проверки, сообщающую, что это недопустимое значение, независимо от того, добавил ли я какие-либо атрибуты проверки. Именно это поведение я хочу использовать вне контроллера.

5. Работа в вашем комментарии работает, но это означает, что мне пришлось создать дополнительный класс.

Ответ №1:

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

 public class StringIdLengthRangeAttribute : ValidationAttribute
{
    public int Minimum { get; set; }
    public int Maximum { get; set; }

    public StringLengthRangeAttribute()
    {
       this.Minimum = 0;
       this.Maximum = int.MaxValue;
    }

    public override bool IsValid(object value)
    {
        string strValue = value as string;
        if (!string.IsNullOrEmpty(strValue))
        {
            int len = strValue.Length;
            return len >= this.Minimum amp;amp; len <= this.Maximum;
        }
        return true;
    }
}
  

Это пример проверки длины — замените его своей логикой проверки.
И ваш класс:

 public class Test
{
   [Required]
   [StringIdLengthRange(Minimum = 10, Maximum = 20)]
   public string Id { get; set; }
}
  

С таким атрибутом вы можете использовать эту логику в любых других полях.

Комментарии:

1. Извините, это не то, что я спрашивал.