Небольшая рекомендация для начала: я бы использовал модели представлений вместо классов сущностей в ваших представлениях, так как это обеспечит вам большую гибкость и поможет вам достичь ваших целей, не начиная загрязнять ваши представления кодом, который там не принадлежит. Вы могли бы, очевидно, сделать это со своими классами сущностей, хотя и внесли некоторые изменения, но я бы не рекомендовал это.
Вы получаете ошибку, я полагаю, потому что вы пытаетесь привязать к своей сущности классы, которые определяют свойства ICollection , а связыватель модели не имеет возможности определить конкретный тип, который следует использовать для их создания. Для быстрого исправления вы можете изменить свой ICollection на конкретный тип, например Collection или List . Но опять же, это первая моя рекомендация ...
Итак, чтобы сделать это правильно, вот что я бы сделал:
public class PersonViewModel
{
public int Age {get;set;}
public string Name {get;set;}
public List<HobbyViewModel> Hobbies {get;set;}
}
public class HobbyViewModel
{
public int HobbyID {get;set;}
public string Name {get;set;}
public string Type {get;set;}
public int? Rating {get;set;}
}
public class PersonController
: Controller
{
...
[HttpGet]
public IActionResult Create()
{
PersonViewModel viewModel = new PersonViewModel();
viewModel.Hobbies = this.DbContext.Hobbies.Select(h => new HobbyViewModel() { Name = h.Name, Type = h.Type }).ToList();
return this.View(viewModel);
}
[HttpPost]
public IActionResult Create(PersonViewModel model)
{
if(!this.ModelState.IsValid)
return this.BadRequest(model);
Person person = new Person(){ Age = model.Age, Name = model.Name };
foreach(HobbyViewModel hobbyViewModel in model.Hobbies)
{
//Check if the user has rated the hobby and if not, skip it
if(!hobbyViewModel.Rating.HasValue)
continue;
person.PersonHobbies.Add(new PersonHobby(){ HobbyId = hobbyViewModel.HobbyId, Rating = hobbyViewModel.Rating.Value });
}
this.DbContext.Persons.Add(person);
this.DbContext.SaveChanges();
return this.RedirectToAction(nameof(Index));
}
}
Другими словами, в вашем лице form, отобразите форму для каждого из увлечений, представленных в модели представления, с вводом Рейтинг. Когда пользователь публикует форму, проверьте все предоставленные хобби, чтобы проверить, оценил ли его пользователь (ie: проверьте, установлено ли свойство Rating, допускающее значение NULL), и, если да, добавьте новый PersonHobby в результирующую сущность Person. Вуаля!
Наконец, несколько рекомендаций по вашим моделям сущностей:
- Забудьте об утомительных PersonHobbies именах свойств. Это не повсеместный , и вы всегда должны стремиться к повсеместному распространению, когда это возможно : это делает ваш код красивее, проще для понимания и, следовательно, проще в сопровождении. Назовите свои свойства «Хобби» для сущности «Человек» и, например, «Лица или избиратели» для сущности «Хобби». конфигурация и / или аннотация данных. Более того, я ожидаю, что свойство Person Id будет ... ну, идентификатором Person. Нет необходимости указывать это.
- Я настаиваю, чтобы облегчить вашу жизнь, забудьте об использовании ваших типов сущностей в представлениях или, что еще хуже, в качестве возвращаемых типов Json / Xml. Вы должны использовать модели представлений для своих представлений и объекты передачи данных (DTO) для возвращаемых типов Json / Xml. Даже если эта концепция может показаться go противоречащей принципу KISS, поверьте мне, это не так. Со временем это просто упростит вашу жизнь, даже если поначалу это может показаться бессмысленной проблемой. Фактически, ваши типы сущностей, вероятно, будут со временем развиваться, а ваши представления - нет, и наоборот. Кроме того, для ваших представлений обычно требуется больше или отличная информация, чем для типов ваших сущностей, и, продолжая следовать этому пути, вы можете обнаружить, что начинаете объединять свои представления с вызовами и т. Д., Тогда как он должен просто содержать view logi c. Вызовы должны выполняться в действиях ваших контроллеров, и они должны заполнять модели всеми данными / информацией, необходимыми для ваших представлений.