#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), и эти классы могут быть массивами. Не уверен, что вы сложные свойства, не видя ответа..