Частичная проверка на стороне сервера для сложного свойства

#c# #asp.net-mvc #asp.net-core #modelstate #server-side-validation

#c# #asp.net-mvc #asp.net-ядро #состояние модели #проверка на стороне сервера

Вопрос:

В ASP.NET В основном приложении MVC мне нужно пропустить проверку модели для определенного сложного свойства в действии контроллера.
Допустим, у меня есть следующая структура модели:

 public class Person
{
    public int PersonID { get; set; }
    public PersonalInfo PersonalInfo { get; set; }
    public ContactInfo ContactInfo { get; set; }

    public Person()
    {
        PersonalInfo = new PersonalInfo();
        ContactInfo = new ContactInfo();
    }
}

public class PersonalInfo 
{
        [Required(ErrorMessage = "First name is required")]
        public string FirstName { get; set; }

        [Required(ErrorMessage = "Last name is required")]
        public string LastName { get; set; }
}

public class ContactInfo 
{
        [Required(ErrorMessage = "Phone is required")]
        public string Phone { get; set; }

        [Required(ErrorMessage = "Email is required")]
        public string Email{ get; set; }
}
 

В post action я хотел бы пропустить проверку для ContactInfo, хотя она является частью модели и отправлена. Что-то вроде этого:

 [HttpPost]
public ActionResult SavePerson(Person model)
{
    ModelState.Remove("ContactInfo");
    if (ModelState.IsValid)
    { 
        (...)
    }
}
 

Это сработало бы, если бы ContactInfo был простым (правильный термин «скалярный»?) свойством.

Я знаю, что некоторые из вас предложили бы мне использовать отдельные viewmodels, но я не думаю, что это применимо в данном случае (я пытаюсь создать форму с несколькими шагами, и все данные должны быть в форме для отправки, чтобы сохраняться между шагами …)

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

Ответ №1:

ModelState.Удалить («ContactInfo»);

Похоже, что ModelState не содержит ключа «ContactInfo», поэтому он не будет работать. Если вы хотите отключить проверку в дочернем классе, как вы догадываетесь, вам нужно удалить все свойства в нем, такие как:

 ModelState.Remove("ContactInfo.Phone");
ModelState.Remove("ContactInfo.Email");
 

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

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

 foreach (var property in model.ContactInfo.GetType().GetProperties())
{
    ModelState.Remove("ContactInfo."   property.Name);
}
 

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

1. Привет @petra, если это полезно, вы можете принять это как ответ, спасибо :).

2. Это то, что мне было нужно. Извините, мне потребовалось некоторое время, чтобы принять, я хотел хорошо протестировать его.

Ответ №2:

Если у вас есть массивы, попробуйте выполнить следующее. Если вы не используете XmlElement с массивом, для сериализации Xml требуется два Xml-тега. Для использования XmlElement требуется только один тег. :

     [XmlElement()]
    public List<PersonalInfo> PersonalInfo { get; set; }
    [XmlElement()]
    public List<ContactInfo> ContactInfo { get; set; }
 

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

1. Спасибо за ответ, но я не понимаю, как это может мне помочь… Тем не менее, я попытался добавить этот атрибут в свойства, но я получаю сообщение об ошибке; должен ли я добавить ссылку на пространство имен? И я не знаю, что вы подразумеваете под «Если у вас есть массивы»?

2. Вам нужно посмотреть на строку ответа в контроллере, чтобы увидеть, как выглядит ответ. Если ответ представляет собой xml, корневым тегом является Person . У сложного свойства могут быть дочерние классы (дочерние классы xml), и эти классы могут быть массивами. Не уверен, что вы сложные свойства, не видя ответа..