Повторное использование модели представления, но применение других правил проверки в ASP.NET MVC

Поэтому мы используем DataAnnotations для проверки входных данных для наших форм ASP.NET MVC. Если бы мы начали заново, я бы подумал о Fluent Validation, но мы слишком далеко продвинулись, чтобы вносить изменения.

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

Затем мы превратили ввод Address в повторно используемый модуль, создав для него частичное представление _AddressEntry вместе со связанной моделью представления — AddressViewModel. Тогда модель представления для родительской формы выглядит так:

public class SubmitEnquiryViewModel
{
    public AddressViewModel Address { get; set; }

    public string Enquiry { get; set; }

    ...
}

Затем в виде _SubmitEnquiry мы вставляем частичный вид _AddressEntry, используя EditorFor().

Это работает нормально, пока мы не поймем, что разные экземпляры ввода Address имеют разные требования к проверке — атрибуты проверки, украшающие AddressViewModel, не всегда применяются. Чтобы обойти проблему, мы определяем IAddressViewModel:

public interface IAddressViewModel
{
    string LineOne { get; set; }

    string LineTwo { get; set; }

    ...
}

А затем определите конкретные реализации этого интерфейса для всех различных перестановок спецификации проверки - например. AddressViewModel (проверка по умолчанию), AddressNoValidationViewModel и т. д.

Затем частичное представление _AddressEntry привязывается к IAddressViewModel, и для свойства Address модели родительского представления выбирается соответствующая конкретная реализация.

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

Кто-нибудь еще сталкивался с этой проблемой раньше? Какое решение вы придумали? Что вы думаете о решении, описанном выше?


person James Rogers    schedule 25.10.2014    source источник
comment
Как именно вы проводите проверки?   -  person beautifulcoder    schedule 25.10.2014
comment
Используя DataAnnotations атрибуты проверки OOTB и позволяя DefaultModelBinder делать свое дело (и, таким образом, DataAnnotationsModelValidator, я думаю).   -  person James Rogers    schedule 25.10.2014


Ответы (2)


Вы можете изучить Атрибут ТипаМетаданных.

Базовый класс:

public abstract class AddressDetailsBase
{
  public string Line1 { get; set; }
  public string Line2 { get; set; }
  public string City { get; set; }
  public string State { get; set; }
  public int PostalCode { get; set;}
}

Проверка (я использую интерфейсы, чтобы их нельзя было случайно создать):

public interface IUserAddressDetailsValidation
{
  [required]
  string Line1 { get; set; }
  [required]
  string Line2 { get; set; }
  [required]
  string City { get; set; }
  [required]
  string State { get; set; }
  [required]
  int PostalCode { get; set;}
}

Посмотреть тип модели:

[MetadataType(typeof(IUserAddressDetailsValidation))]
public class UserAddressDetails : AddressDetailsBase { }
person Erik Philips    schedule 27.10.2014
comment
Спасибо, что обратили мое внимание на MetadataTypeAttribute. Это решение работает, кроме одной проблемы: привязка представления к AddressDetailsBase, помощники HTML не выбирают атрибуты проверки, примененные в IUserAddressDetailsValidation, поэтому проверка на стороне клиента не работает. Любые идеи? Я пытаюсь динамически изменить тип параметра выражения, переданного помощнику HTML, с AddressDetailsBase на UserAddressDetails, но в данный момент я борюсь! - person James Rogers; 29.10.2014
comment
В этом случае вы не будете использовать базовый объект для проверки, он не имеет проверки. Что касается борьбы с его изменением, я не могу вам помочь, поскольку вы не предоставили никаких подробностей. - person Erik Philips; 29.10.2014
comment
Фундаментальная проблема была выявлена ​​здесь: stackoverflow.com/a/15232767/3619572 Я решил проблему, используя не общие помощники HTML. - person James Rogers; 29.10.2014

Аннотации данных хороши для очень простых сценариев и для прототипов проектов. Как видите, вы уже боретесь с аннотациями, которые не подходят для работы в разных контекстах.

Просто используйте простой ModelState.AddModelError в действиях контроллера и создайте пользовательскую логику проверки в своем контроллере.

ModelState.AddModelError("Prop", "Your custom 'validation failed' message.");

Вы по-прежнему можете оценить ModelState.IsValid перед выполнением своей пользовательской проверки, поэтому вы все равно можете использовать DataAnnotations для простых случаев для повторного использования некоторого кода.

person George Polevoy    schedule 27.10.2014