Pregunta

Me gustaría incrustar una instancia del objeto A dentro del objeto B. Ya tengo una acción y una vista de edición que representa un formulario para el objeto B. Lo convertí en una vista parcial fuertemente tipada que acepta B.

Estoy lidiando con la acción Crear ahora, así que hago b = new B (); b.A = nuevo A ();

Ahora renderizaría el formulario para B, y luego llamaría a la vista parcial para A, pasándolo b.A.

Pero lo que obtengo es un FormCollection o mi nuevo objeto A con el campo B establecido en nulo. En el primer caso, todo está bien, pero ¿qué haré si el formulario no falla? ¿Debo crear los objetos manualmente con los datos incorrectos y volver a pasarlos con un ModelState no válido? ¿Es posible la segunda opción?

¿O solo necesito evitar tener la vista anidada? Pensé, como alternativa, crear un objeto modelo especial solo para manejar el formulario con todos los valores para A y B, y luego, cuando este formulario se validara, rellenaría manualmente los objetos A y B y los guardaría. ¿Es esta la única solución?

¿Fue útil?

Solución

Debería poder usar A y B como lo ha descrito.

Supongamos que tenemos lo siguiente:

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
        } );
}

Entonces su modelo es una instancia de B.

Su vista y su vista parcial anidada deberían producir HTML algo como esto:

 <input type="text" name="A.Z" value="AyyZee" />
 <input type="text" name="X" value="BeeEcks" />
 <input type="text" name="Y" value="7" />

Ahora la carpeta del modelo por defecto debería poder conectar esto:

[AcceptVerbs( HttpVerbs.Post )]
public ActionResult Edit (B input) {
    // apply changes
    //the binder should have populated input.A
}

Tenga en cuenta que esto solo funciona si A y B tienen un constructor predeterminado y son clases relativamente simples. Si tiene algo más complejo, puede usar su propia carpeta:

[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"])
            };
    }
}

Otros consejos

cree su propio modelo personalizado que incorpore A y B, luego cree una vista desde ese modelo cuando envíe su formulario, simplemente podrá actualizar su modelo personalizado y actualizar / agregar sus modelos individuales.

public class CustomViewModel
{
    public ModelA myAModel {get;set;}
    public ModelB mybModel {get;set;}
}

una vista para ese modelo creará un formulario que incorpora A y B y le permitirá luego su colección de formularios publicada se puede usar para establecer valores para cada modelo individual y actualizar / crear y separar.

Mis problemas con este código fueron causados ??por dos cosas, ambas en la clase de modelo:

  1. Los campos deben ser propiedades y no campos normales
  2. Faltaba el constructor que inicializaría los objetos internos

Entonces las clases de la solución anterior deberían ser:

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() {}
 } 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top