asp.net MVC: редактирование встроенных объектов

StackOverflow https://stackoverflow.com/questions/1410942

  •  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() {}
     } 
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top