asp.net MVC: редактирование встроенных объектов
-
05-07-2019 - |
Вопрос
Я хотел бы встроить экземпляр объекта A в объект B. У меня уже есть действие и представление редактирования, которое отображает форму для объекта B. Я сделал это строго типизированным частичным представлением, принимающим B.
Сейчас я имею дело с действием Create, поэтому я делаю b = new B (); b.A = новый A ();
Теперь я отрисовываю форму для B, а затем вызываю частичное представление для A, передавая его b.A.
Но я получаю либо FormCollection, либо мой новый объект A с полем B, установленным в нуль. В первом случае все хорошо, но что я буду делать, если форма не сможет фальсифицировать? Нужно ли создавать объекты вручную с неверными данными и снова передавать их с недействительным ModelState? Возможен ли второй вариант?
Или мне просто нужно избегать наличия вложенного представления? В качестве альтернативы я подумал, что нужно создать специальный объект модели просто для обработки формы со всеми значениями как для A, так и для B, а затем, когда эта форма будет проверена, я вручную заполню объекты A и B и сохраню их. Это единственное решение?
Решение
Вы должны быть в состоянии использовать A и B, как вы описали.
Предположим, у нас есть следующее:
public class B {
public A A {get; set;}
public string X {get; set;}
public int Y {get;set;}
}
public class A {
public string Z {get; set;}
}
//then in your controller:
public ActionResult Edit () {
return View (
new B {
A = new A { Z = "AyyZee" } ,
X = "BeeEcks",
Y = 7
} );
}
Итак, ваша модель является экземпляром B.
Ваше представление и ваше вложенное частичное представление должны генерировать HTML примерно так:
<input type="text" name="A.Z" value="AyyZee" />
<input type="text" name="X" value="BeeEcks" />
<input type="text" name="Y" value="7" />
Теперь связыватель модели по умолчанию должен иметь возможность подключить это:
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Edit (B input) {
// apply changes
//the binder should have populated input.A
}
Обратите внимание, что это работает, только если A и B имеют конструктор по умолчанию и являются относительно простыми классами. Если у вас есть что-то более сложное, вы можете использовать свое собственное связующее:
[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Edit ( [ModelBinder( typeof( BBinder ) )] B input) {
//...
}
public class BBinder : IModelBinder
{
public object BindModel( ControllerContext controllerContext, ModelBindingContext bindingContext )
{
return
new B {
A = new A { Z = Request["A.Z"] } ,
X = Request["X"],
Y = int.Parse(Request["Y"])
};
}
}
Другие советы
создайте свою собственную пользовательскую модель, которая включает в себя A и B, затем создайте представление из этой модели Когда вы отправите форму, вы сможете просто обновить свою пользовательскую модель и обновить / добавить отдельные модели.
public class CustomViewModel
{
public ModelA myAModel {get;set;}
public ModelB mybModel {get;set;}
}
представление для этой модели создаст форму, которая включает в себя A и B и позволит вам затем Ваша отправленная коллекция форм может затем использоваться для установки значений для каждой отдельной модели и обновления / создания, а затем разделения.
Мои проблемы с этим кодом были вызваны двумя причинами, оба в классе модели:
<Ол>Таким образом, классы из приведенного выше решения должны быть:
public class B {
public A a {get; set;}
public string x {get; set;}
public int y {get;set;}
public B() {
a = new A();
}
}
public class A {
public string z {get; set;}
public A() {}
}