There is a problem with the transfer of data from the ajax request to the controller action.
Here are my models:
public class Mark { public int Id { get; set; } [Required] [Display(Name = "Марка")] public string MarkName { get; set; } public virtual ICollection<CarModel> CarModels { get; set; } public virtual ICollection<Car> Cars { get; set; } public Mark() { CarModels = new List<CarModel>(); Cars = new List<Car>(); } } public class CarModel { public int Id { get; set; } [Required] [Display(Name = "Модель")] public string ModelName { get; set; } public int MarkId { get; set; } public virtual Mark Mark { get; set; } public virtual ICollection<Equipment> Equipments { get; set; } public virtual ICollection<Car> Cars { get; set; } public CarModel() { Equipments = new List<Equipment>(); Cars = new List<Car>(); } } Here are my partial views:
_AddMarkModel:
@model AutoStore.Domain.Core.CarModel <div id="AddMarkModel" class="modal fade"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Добавление новой марки/модели</h4> </div> @using (Ajax.BeginForm(new AjaxOptions { OnSuccess = "AddMarkSuccess", OnFailure = "AddMarkError" })) { <div class="modal-body"> @Html.Partial("_MarkModel") </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button> <button id="btnConfirm" type="submit" class="btn btn-success">Добавить</button> </div> } </div> </div> </div> _MarkModel:
@model AutoStore.Domain.Core.CarModel <div class="container"> <div class="row"> <div class="col"> @Html.LabelFor(i => i.Mark.MarkName, "Марка") </div> <div class="col-sm-3"> <div class="row"> <div class="col"> <div class="form-group"> @Html.RadioButton("Mark", "New", true) <span>Новая</span> @Html.EditorFor(i => i.Mark.MarkName, new { htmlAttributes = new { @id = "newMark", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Mark.MarkName, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.ModelName, "Модель") @Html.EditorFor(i => i.ModelName, new { htmlAttributes = new { @id = "txtPass", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.ModelName, "", new { @class = "text-danger" }) </div> </div> </div> </div> <div class="col-sm-3"> <div class="row"> <div class="col"> @Html.RadioButton("Mark", "Existing") <span>Существующая</span> @Html.DropDownListFor(i => i.Mark.Id, ViewBag.marks as SelectList, new { @id = "exMark", @class = "form-control", @disabled = "disabled" }) @Html.ValidationMessageFor(i => i.Mark.MarkName, "", new { @class = "text-danger" }) </div> </div> </div> </div> </div> They show that I use Html.AjaxBegin.
Which leads to the action:
[HttpPost] public JsonResult _AddMarkModel(CarModel model) { if (model == null) throw new Exception("Модель не найдена"); if (ModelState.IsValid) { unitOfWOrk.CarModels.Create(model); unitOfWOrk.Save(); return Json(new { result = true }); } else throw new Exception("Не все обязательные поля заполнены"); } But when I fill in the fields, only the data on the car model arrives in the action, but the data on the make of the car does not arrive:
Although I have another form where Car is used in the same way ajax.beginform passes data to the controller. And there all data on all other models connected with the help of foreign key are tightened. Here is the car class:
public class Car { public int Id { get; set; } [Required] [Display(Name = "Цена")] public int Price { get; set; } [Required] [Display(Name = "Количество на складе")] public int Count { get; set; } public int? MarkId { get; set; } public virtual Mark Mark { get; set; } public int CarModelId { get; set; } public virtual CarModel CarModel { get; set; } public int? EquipmentId { get; set; } public virtual Equipment Equipment { get; set; } public virtual ICollection<Order> Orders { get; set; } public Car() { Orders = new List<Order>(); } } I can not understand what the difference? Please tell me if anyone sees what the problem is. Perhaps the case in the database architecture and entity in the case of car somehow guesses where to put some data, but in the case of carmodel there is no, but I can not understand what exactly is the case.
UPDATE:
Here is an example of my working code with the problem that I described.
Models:
public class Car { public int Id { get; set; } [Required] [Display(Name = "Цена")] public int Price { get; set; } [Required] [Display(Name = "Количество на складе")] public int Count { get; set; } public int? MarkId { get; set; } public virtual Mark Mark { get; set; } public int CarModelId { get; set; } public virtual CarModel CarModel { get; set; } public int? EquipmentId { get; set; } public virtual Equipment Equipment { get; set; } public virtual ICollection<Order> Orders { get; set; } public Car() { Orders = new List<Order>(); } } public class Mark { public int Id { get; set; } [Required] [Display(Name = "Марка")] public string MarkName { get; set; } public virtual ICollection<CarModel> CarModels { get; set; } public virtual ICollection<Car> Cars { get; set; } public Mark() { CarModels = new List<CarModel>(); Cars = new List<Car>(); } } public class CarModel { public int Id { get; set; } [Required] [Display(Name = "Модель")] public string ModelName { get; set; } public int MarkId { get; set; } public virtual Mark Mark { get; set; } public virtual ICollection<Equipment> Equipments { get; set; } public virtual ICollection<Car> Cars { get; set; } public CarModel() { Equipments = new List<Equipment>(); Cars = new List<Car>(); } } public class Equipment { public int Id { get; set; } //Двигателя [Required] [Display(Name = "Двигатель")] public int Engine { get; set; } //Количество лошадиных сил [Required] [Display(Name = "Мощность")] public int Power { get; set; } //Год выпуска [Required] [Display(Name = "Год выпуска")] public int ReleaseYear { get; set; } //Тип привода [Required] [Display(Name = "Тип привода")] public string DriveType { get; set; } //КПП [Required] [Display(Name = "КПП")] public string Transmission { get; set; } //Кузов [Required] [Display(Name = "Кузов")] public string Body { get; set; } //Максимальная скорость [Required] [Display(Name = "Максимальная скорость")] public int MaxSpeed { get; set; } //Вес [Required] [Display(Name = "Вес")] public int Weight { get; set; } //Бак [Required] [Display(Name = "Бак")] public int MaxFuelVolume { get; set; } //Цвет автомобиля [Required] [Display(Name = "Цвет")] public string Color { get; set; } //Изорбражение автомобиля [Required] [Display(Name = "Изображение автомобиля")] public string Picture { get; set; } public int CarModelId { get; set; } public virtual CarModel CarModel { get; set; } public virtual ICollection<Car> Cars { get; set; } public Equipment() { Cars = new List<Car>(); } } On the form, I perform the addition of a new car with all the characteristics that stretch from other models. My form as well as in the past case is composed of a partial view. If it matters, my window made up of a partial view is modal and invoked using jquery. Here they are:
_AddAuto:
@model AutoStore.Domain.Core.Car <div id="AddAuto" class="modal fade"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Добавление нового автомобиля</h4> </div> @using (Ajax.BeginForm(new AjaxOptions { OnSuccess = "AddCarSuccess", OnFailure = "AddCarError" })) { <div class="modal-body"> @Html.Partial("_CarAttributes") </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Закрыть</button> <button id="btnConfirm" type="submit" class="btn btn-success">Добавить</button> </div> } </div> </div> </div> _CarAttributes:
@model AutoStore.Domain.Core.Car <div class="container"> <div class="row"> <div class="col-sm-4"> <div class="row"> <div class="col"> @Html.Label("Автомобиль:") </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Price, "Цена") @Html.EditorFor(i => i.Price, new { htmlAttributes = new { @id = "txtPrice", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Price, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Count, "Количество на складе") @Html.EditorFor(i => i.Count, new { htmlAttributes = new { @id = "txtCount", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Count, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Mark.MarkName, "Марка") @Html.EditorFor(i => i.Mark.MarkName, new { htmlAttributes = new { @id = "txtMarkName", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Mark.MarkName, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.CarModel.ModelName, "Модель") @Html.EditorFor(i => i.CarModel.ModelName, new { htmlAttributes = new { @id = "txtModelName", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.CarModel.ModelName, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> <br /> @Html.LabelFor(i => i.Equipment.Picture, "Изображение Автомобиля", new { @style = "padding-right: 50px" }) @Html.EditorFor(i => i.Equipment.Picture, new { htmlAttributes = new { @class = "form-control", @type = "hidden", @id = "image" } }) <br /> @Html.ValidationMessageFor(i => i.Equipment.Picture, "", new { @id = "pictureError", @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> <input id="fileLoader" type="file" accept="image/*" /> <img id="autoPicture" class="img-responsive" /> </div> </div> </div> </div> <div class="col-sm-6 col-sm-offset-1"> <div class="row"> <div class="col"> @Html.Label("Комплектация:") </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.Engine, "Двигатель") @Html.EditorFor(i => i.Equipment.Engine, new { htmlAttributes = new { @id = "txtEngine", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.Engine, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.Power, "Мощность") @Html.EditorFor(i => i.Equipment.Power, new { htmlAttributes = new { @id = "txtPower", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.Power, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.ReleaseYear, "Год выпуска") @Html.EditorFor(i => i.Equipment.ReleaseYear, new { htmlAttributes = new { @id = "txtYear", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.ReleaseYear, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.DriveType, "Тип привода") @Html.EditorFor(i => i.Equipment.DriveType, new { htmlAttributes = new { @id = "txtDriveType", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.DriveType, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.Transmission, "КПП") @Html.EditorFor(i => i.Equipment.Transmission, new { htmlAttributes = new { @id = "txtTransmission", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.Transmission, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.Body, "Кузов") @Html.EditorFor(i => i.Equipment.Body, new { htmlAttributes = new { @id = "txtBody", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.Body, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.MaxSpeed, "Максимальная скорость") @Html.EditorFor(i => i.Equipment.MaxSpeed, new { htmlAttributes = new { @id = "txtMaxSpeed", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.MaxSpeed, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.Weight, "Вес") @Html.EditorFor(i => i.Equipment.Weight, new { htmlAttributes = new { @id = "txtWeight", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.Weight, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.MaxFuelVolume, "Бак") @Html.EditorFor(i => i.Equipment.MaxFuelVolume, new { htmlAttributes = new { @id = "txtFuel", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.MaxFuelVolume, "", new { @class = "text-danger" }) </div> </div> </div> <div class="row"> <div class="col"> <div class="form-group"> @Html.LabelFor(i => i.Equipment.Color, "Цвет") @Html.EditorFor(i => i.Equipment.Color, new { htmlAttributes = new { @id = "txtColor", @class = "form-control" } }) @Html.ValidationMessageFor(i => i.Equipment.Color, "", new { @class = "text-danger" }) </div> </div> </div> </div> </div> </div> Notice that, but on partialview _CarAttributes, in order for me to have all the data gathered in the model through the Car model, I climb into other models in EditorFor, for example @Html.EditorFor(i => i.Equipment.Weight
And here is my controller:
[HttpPost] public ActionResult _AddAuto(Car car) { if (car == null) throw new Exception("Автомобиль не найден"); if (ModelState.IsValid) { unitOfWOrk.Cars.Create(car); unitOfWOrk.Save(); return PartialView("_Car", car); } else throw new Exception("Не все обязательные поля заполнены"); } Pay attention to the screenshot filled with all the data not only on the Car model but also on all the others, the same Weight that I cited as an example earlier. If you look at the View you will see everything.
And that's what flies me to the controller:
Please note that even though I use the Car model as input, all the other models also arrive. In the last screenshot, I gave an example that, in addition to the Car model, I also received the Equipment model, but there were also 2 models, Mark and CarModel. Here is an example of how it works.
Screen:





